英文:
value not setting with '=' in rails
问题
I have a model which looks something like this:
class At::ModalityCombo < Base
  self.table_name = 'at_modalites_at_combos'
  belongs_to :at_modality, :class_name => 'At::Modality', foreign_key: :modality_id
  belongs_to :at_combo, :class_name => 'At::Combo', foreign_key: :combo_id
  attr_reader :modality_day
  attr_writer :modality_day
end
Migration for modality_day column is like:
class AddDayInModalityCombo < ActiveRecord::Migration[5.2]
  def up
    add_column :at_modalites_at_combos, :modality_day, :integer, default: 0
  end
  def down
    remove_column :at_modalites_at_combos, :modality_day
  end
end
On rails console,
abc = At::ModalityCombo.new
abc.modality_day = 4
abc
Output:
modality_id: nil, combo_id: nil, modality_day: 0
Why modality_day is still 0?
英文:
I have a model which looks something like this:
class At::ModalityCombo < Base
  self.table_name = 'at_modalites_at_combos'
  belongs_to :at_modality, :class_name => 'At::Modality', foreign_key: :modality_id
  belongs_to :at_combo, :class_name => 'At::Combo', foreign_key: :combo_id
  attr_reader :modality_day
  attr_writer :modality_day
end
Migration for modality_day column is like:
class AddDayInModalityCombo < ActiveRecord::Migration[5.2]
  def up
    add_column :at_modalites_at_combos, :modality_day, :integer, default: 0
  end
  def down
    remove_column :at_modalites_at_combos, :modality_day
  end
end
On rails console,
abc = At::ModalityCombo.new
abc.modality_day = 4
abc
Output:
modality_id: nil, combo_id: nil, modality_day: 0
Why modality_day is still 0?
答案1
得分: 3
I think you are confusing Rails here.
- 你在一个 Active Record 模型上有一个名为 
modality_day的列。这允许你在At::ModalityCombo的实例上读取/写入该属性。 - 你还为 
modality_day设置了attr_reader和attr_writer。 
看起来 attr_writer/attr_reader 正在覆盖了通常用于管理数据库中定义的属性的方法。删除它们应该解决这个问题,使其按照你的预期工作。
attr_reader :modality_day 基本上等同于:
def modality_day
  @modality_day
end
而 attr_writer :modality_day 基本上等同于:
def modality_day=(value)
  @modality_day = value
end
这些方法管理一个实例变量,但 Active Record 不以相同的方式存储你的数据库数据。
英文:
I think you are confusing Rails here.
- You have a column named 
modality_dayon an Active Record model. This lets you read/write that property on instances ofAt::ModalityCombo. - You also have 
attr_readerandattr_writersetup formodality_day. 
It looks like attr_writer/attr_reader is overriding the methods that would normally let you manage the property defined in your database. Deleting those should fix this and make it work like you expect.
attr_reader :modality_day is basically equivalent to:
def modality_day
  @modality_day
end
And attr_writer :modality_day is basically equivalent to:
def modality_day=(value)
  @modality_day = value
end
These methods manage an instance variable, but Active Record does not store your database data in this same way.
答案2
得分: 0
attr_reader、attr_writer和attr_accessor不应该在Rails模型中使用(至少在Rails 5.0+中不应该使用)。它们是Ruby内置的元编程方法,用于创建setter和getter。
ActiveRecord实际上直接从数据库中读取模式,并创建与数据库表中的列相对应的特殊setter和getter。这些setter远远超越了基本的attr_writer setter - 它们进行了类型转换、脏数据跟踪等操作。
如果你使用attr_accessor,你会覆盖setter,你的模型将停止将属性持久化到数据库,等等。
对于不保存到数据库的"虚拟属性",请使用属性API,它提供了默认值和类型转换功能。
英文:
attr_reader, attr_writer and attr_accessor should not be used in Rails models at all (at least not in Rails 5.0+). They are Rubys built in metaprogramming methods for creating setters and getters.
ActiveRecord actually reads the schema straight from the db and creates special setters and getters corresponding to the columns in the db table. These setters are light years from the basic attr_writer setter - they do type casting, dirty tracking etc.
If you use attr_accessor you overwrite the setter and your model will stop persisting the attribute among other things.
For "virtual attributes" that are not saved to the database use the attributes api which does default values and typecasting.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论