Rails 深入学习 Migration limit

Posted by wxianfeng Sat, 16 Apr 2011 21:09:00 GMT

环境:ruby1.9.2 + rails 3.0.3

一直以为

add_column :users , :age  ,  :integer  , :limit=> 4  

在数据库里对应的类型是 int(4)

其实是错误的!!!

看下 limit的说明文档:

:limit - Requests a maximum column length. This is number of characters for :string and :text columns and number of bytes for :binary and :integer columns.

对于 string 和 text 比较简单,例如

add_column :users,:name , :string , :limit=> 60 

那么数据库中的 类型就是 varchar(60)

对于 binary 和 integer 的就不一样了 , 表示的是字节数 , 但是 :limit =>11 不是表示 11个字节的整数 , 是4 个字节整数

对应关系:

:limit          Numeric Type          Column Size
1                      tinyint                  1 byte
2                      smallint                  2 bytes
3                      mediumint             3 bytes
nil, 4, 11      int(11)                  4 bytes
5 to 8              bigint                  8 bytes

而mysql的integer类型(也是int型) 表示大小如下:

详细 here

rails 里的实现代码 here

核心代码:

 # Maps logical Rails types to MySQL-specific data types.
      def type_to_sql(type, limit = nil, precision = nil, scale = nil)
        return super unless type.to_s == 'integer'

        case limit
        when 1; 'tinyint'
        when 2; 'smallint'
        when 3; 'mediumint'
        when nil, 4, 11; 'int(11)'  # compatibility with MySQL default
        when 5..8; 'bigint'
        else raise(ActiveRecordError, "No integer type has byte size #{limit}")
        end
      end

从上面代码可以看出, 当limit 为 nil,4,11 的时候 , mysql的类型就是 int(11), 也就是常在 migration看到的 integer , :limit=>11

另外可以从已经有的表中得到字段的字节数

ruby-1.9.2-p0 > ActiveRecord::Migration.add_column :forms , :int9, :integer , :limit=>11
-- add_column(:forms, :int9, :integer, {:limit=>11})
  SQL (300.9ms)  ALTER TABLE `forms` ADD `int9` int(11)
   -> 0.3012s
 => nil 
ruby-1.9.2-p0 > Form.reset_column_information
 => nil 
ruby-1.9.2-p0 > Form.columns_hash["int9"].limit 
 => 4 
ruby-1.9.2-p0 > Form.columns_hash["int9"]
 => #<ActiveRecord::ConnectionAdapters::Mysql2Column:0xb8407c8 @null=true, @sql_type="int(11)", @name="int9", @scale=nil, @precision=nil, @limit=4, @type=:integer, @default=nil, @primary=false>

看到没,在迁移的时候 指定 :limit => 11 , 但是 通过 columns_hash 得到的 limit 确是4 , 也就是说 mysql 的 Column Size 是4 bytes , 如果指定 :limit => nil 或者 :limit=>4 得到的 都是 4 bytes

因为 rails 里面 主键id 默认是有符号的 int(11) ,所以 mysql的主键最大id 是 2147483647 , 如果改成无符号的 最大可以到 4294967295

ruby 如何得到 整数的字节数?

size 方法

ruby-1.9.2-p0 > 10_000_000_000.size
 => 8 
ruby-1.9.2-p0 > 1.size
 => 4 

如何让我的integer类型的字段变成无符号的?

ruby-1.9.2-p0 > ActiveRecord::Migration.add_column :forms , :int8, "integer unsigned"
-- add_column(:forms, :int8, "integer unsigned")
  SQL (297.4ms)  ALTER TABLE `forms` ADD `int8` integer unsigned
   -> 0.2976s
 => nil 

如何正确 添加mysql中int(4)类型的字段?

ruby-1.9.2-p0 > ActiveRecord::Migration.add_column :users , :number , "int(4)"
-- add_column(:users, :number, "int(4)")
  SQL (280.4ms)  ALTER TABLE `users` ADD `number` int(4)
   -> 0.2808s

最后看下 migration 类型 对应 数据库类型的关系:

SEE:

http://www.snowgiraffe.com/tech/366/rails-migrations-mysql-unsigned-integers-primary-keys-and-a-lot-of-fun-times/
http://thewebfellas.com/blog/2008/6/2/unsigned-integers-for-mysql-on-rails
http://www.kuqin.com/rubycndocument/man/built-in-class/class_object_numeric_integer.html


Rails 注意索引 name

Posted by wxianfeng Thu, 14 Apr 2011 17:56:00 GMT

测试环境:rails 2.X + rails 3.0.3

今天发现 rails api上索引name的命名规则是错误的,here

测试:

ruby-1.9.2-p0 > ActiveRecord::Migration.add_index :users , :email
-- add_index(:users, :email)
  SQL (0.4ms)  SHOW KEYS FROM `users`
  SQL (367.1ms)  CREATE INDEX `index_users_on_email` ON `users` (`email`)
   -> 0.3680s

按照 文档上写的应该是 users_email ,但是实际上是 index_users_on_email

ruby-1.9.2-p0 > ActiveRecord::Migration.add_index :users , :name , :unique=>true
-- add_index(:users, :name, {:unique=>true})
  SQL (0.3ms)  SHOW KEYS FROM `users`
  SQL (340.4ms)  CREATE UNIQUE INDEX `index_users_on_name` ON `users` (`name`)
   -> 0.3413s

按照文档写的应该是 users_name ,但是实际上是 index_users_on_name

ruby-1.9.2-p0 > ActiveRecord::Migration.add_index :users , [:login,:name] 
-- add_index(:users, [:login, :name])
  SQL (0.3ms)  SHOW KEYS FROM `users`
  SQL (314.3ms)  CREATE INDEX `index_users_on_login_and_name` ON `users` (`login`, `name`)
   -> 0.3152s

按照文档下写的应该是 users_login_name 而实际是 index_users_on_login_and_name

为什么 name 如此重要,因为 remove_index 也是根据name 来的,所以 规则必须记住!

例如文档上一个demo:

# Remove the suppliers_name_index in the suppliers table.
#   remove_index :suppliers, :name

其实 是删除 name 为 index_suppliers_on_name 的索引 ,而不是文档上说的 suppliers_name_index

文档上是错误的,从 源码中 也可以看出来

idnex_name method 源码:

 def index_name(table_name, options) #:nodoc:
        if Hash === options # legacy support
          if options[:column]
            "index_#{table_name}_on_#{Array.wrap(options[:column]) * '_and_'}" # HERE
          elsif options[:name]
            options[:name]
          else
            raise ArgumentError, "You must specify the index name"
          end
        else
          index_name(table_name, :column => options)
        end
      end

rails查看 表的索引:

ruby-1.9.2-p0 > ActiveRecord::Migration.indexes("users") # users 是表名

ssh 不输入密码连接服务器

Posted by wxianfeng Thu, 14 Apr 2011 17:39:00 GMT

环境:ubuntu10.10(client) + Centos 5.5 (server)

每次ssh连接服务器 ,scp 拷贝东西 , 或者rsync同步 ,都要输入密码验证,很麻烦,把publickey传到server上的 authorized_keys 中即可 ,建立信任后就不需要输入密码了

1,生成publickey

>ssh-keygen -t rsa # 或者用 dsa 加密

2,上传 publickey 文件到server

>scp  ~/.ssh/id_dsa.pub root@173.230.155.150:~/.ssh/authorized_keys # 173.230.155.150  换成你server的ip

3,ok了

======

本地普通用户免密码连接服务器上的普通用户
把服务器上的 authorized_keys 变为 600权限,.ssh 目录和用户主目录变为 700 / 755 权限

[entsea@www .ssh]$ ll
total 16
-rw-------. 1 entsea entsea  404 May 19 02:50 authorized_keys

=========

ssh时候直接写host连接,不写username配置

localhost:.ssh wangxianfeng$ cat ~/.ssh/config 
Host www.wxianfeng.com
    user wxianfeng

>ssh www.wxianfeng.com

http://liluo.org/2011/05/%E8%AE%BE%E7%BD%AE-ssh-%E8%87%AA%E5%8A%A8%E7%99%BB%E9%99%86%EF%BC%88%E5%85%8D%E5%AF%86%E7%A0%81%EF%BC%8C%E7%94%A8%E6%88%B7%E5%90%8D%EF%BC%89/
http://topic.csdn.net/u/20110701/12/2519a5cc-77d3-4fda-b2d0-88c62edd2556.html