我有一个具有value属性的电子书资源:
class EBook < ApplicationRecord
include Mixin
end
和一个模块:
module Mixin
extend ActiveSupport::Concern
included do
# validations
belongs_to :user
end
def change_value
@value = 200
end
end
我希望能够调用EBook.change_value
并将该实例的值设置为200
。我怎样才能做到这一点?这是反模式吗?我似乎找不到任何可以通过模块更改实例状态的东西。
使用rails控制台,我得到以下输出:
EBook Load (0.3ms) SELECT `e_books`.* FROM `e_books` ORDER BY `e_books`.`id` ASC LIMIT 1 OFFSET 1
=> 200
但它不会更新或保存模型。
答案 0 :(得分:3)
ActiveRecord不会对数据库中表示的属性使用单独的实例变量。
将方法更改为
def change_value
self.value = 200
end
为模型使用ActiveRecord生成的setter方法。
为了进一步清除它,这是您的代码所做的:
class Ebook < ApplicationRecord
attr_reader :value
def change_value
@value = 200
end
end
2.5.1 :001 > e = Ebook.new
=> #<Ebook id: nil, value: nil>
2.5.1 :002 > e.change_value # this sets your instance_variable
=> 200
2.5.1 :003 > e
=> #<Ebook id: nil, value: nil> # ActiveRecord's value remain nil
2.5.1 :004 > e.value # reads from instance variable as we've overwritten the method with attr_reader
=> 200
2.5.1 :005 > e.read_attribute(:value) # reads from ActiveRecord's attributes
=> nil
2.5.1 :006 > e.tap(&:save)
=> #<Ebook id: 3, value: nil> # as expected, nothing is saved