Ruby / rails中的活动记录属性和类型转换

时间:2012-10-21 14:15:25

标签: ruby ruby-on-rails-3.2

我在attempts类型的数据库中有一个属性integer(初始值为0)

当我执行@user.attempts += 1时,它会抛出TypeError: can't convert Fixnum into String

因此,我得出结论,rails不会根据数据类型自动转换属性。

当我这样做时

@user.attempts.to_i +=1

它抛出NoMethodError: undefined method 'to_i=' for "0":String

当我这样做时,

@user.attempts.to_i = @user.attempts.to_i + 1

它再次抛出NoMethodError: undefined method 'to_i=' for "0":String

而且,

@user.attempts = @user.attempts.to_i + 1

工作正常。

我认为原因是,当我执行@user.attempts.to_i + 1时,它实际上会更改左侧的@user.attempts

有人可以对这种行为有所了解吗?

编辑

迁移

    class CreateUsers < ActiveRecord::Migration
      def change
        create_table :users do |t|
          t.string :email 
          t.string :email_pass 
          t.integer :attempts 
          t.timestamps
        end
      end
    end

创建表脚本

-- Table: users

-- DROP TABLE users;

CREATE TABLE users
(
  id serial NOT NULL,
  email character varying(255), 
  email_pass character varying(255), 
  attempts character varying(255),
  created_at timestamp without time zone NOT NULL,
  updated_at timestamp without time zone NOT NULL, 
  CONSTRAINT users_pkey PRIMARY KEY (id )
)
WITH (
  OIDS=FALSE
);
ALTER TABLE users
  OWNER TO jashwant;

我在db attempts中看到的是字符类型。

那么,改变其数据类型的正确方法应该是什么。 我也提出了我的第一个问题,那是什么类型转换的原因?

2 个答案:

答案 0 :(得分:2)

在迁移中使用change_column:

rails g migration change_attempts_to_integer_for_users

...

打开并修改迁移

def self.up
  change_column(:users, :attempts, :integer)
end

def self.down
  change_column(:users, :attempts, :text)
end

运行迁移。

答案 1 :(得分:1)

当你像这样使用+=时:

something += 1

它与:

相同
something = something + 1

当你这样做时,

obj.method = val

它与:

相同
obj.method=(val)

因此,您实际上在#to_i=上调用了@user.attempts不存在的内容。

执行@user.attempts = @user.attempts.to_i + 1时,您的通话与此通话相同:

@user.attempts=(@user.attempts.to_i + 1)

存在,因此工作正常。