Ruby Mixin 模块不保存 Active Record 属性
Ruby Mixin module not saving Active Record property
我有一个电子书资源,其值为 属性:
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
但它不会更新或保存模型。
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
我有一个电子书资源,其值为 属性:
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
但它不会更新或保存模型。
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