Ruby 创建ActiveRecord模型时出现问题:保存中缺少数据
我在开发的Sinatra应用程序中使用ActiveRecord在数据库中创建新模型行时遇到问题。正在创建的对象没有任何错误(使用save!,不会引发异常),但我为保存指定的大多数数据都不存在Ruby 创建ActiveRecord模型时出现问题:保存中缺少数据,ruby,activerecord,model,sinatra,Ruby,Activerecord,Model,Sinatra,我在开发的Sinatra应用程序中使用ActiveRecord在数据库中创建新模型行时遇到问题。正在创建的对象没有任何错误(使用save!,不会引发异常),但我为保存指定的大多数数据都不存在 class ProjectMeta < ActiveRecord::Base attr_accessor :completion_ratio, :num_stories, :num_completed_stories, :original_target_date, :current_targe
class ProjectMeta < ActiveRecord::Base
attr_accessor :completion_ratio, :num_stories, :num_completed_stories, :original_target_date, :current_target_date
...
def self.create_from_project(project)
meta = ProjectMeta.new
meta.project_id = project.id
meta.num_stories = project.num_stories
meta.num_completed_stories = project.num_completed_stories
meta.completion_ratio = ProjectMeta.calculate_ratio(project.num_completed_stories, project.num_stories)
meta.current_target_date = project.current_target_date
meta.save!
meta
end
...
end
class ProjectMeta
对我正在发送的项目对象以及我正在创建的新元对象中的数据进行的所有检查都表明数据存在。但是,当我在保存之前和之后执行meta.inspect时,它显示所有数据(除了project_id)都处于默认状态(零)。我还检查了meta.errors.nil?
,果然,保存后没有任何错误
最令人费解的是,如果我回过头来,得到一个带有该项目id的新元实例,并将数据放入其中,那么就不会给数据库带来任何问题
这让我很沮丧,因为我用ActiveRecord在Rails和Sinatra中构建了几个站点。这一问题让我完全困惑。谁能告诉我我做错了什么吗?属性访问器永远不会保存到数据库中。这些是实例中的内部变量。如果要保存值,必须创建实际列
进行迁移以声明列,然后重试。数据库字段和临时属性访问器声明的属性之间有一个重要的区别。如果已经声明了列,则不需要attr_访问器声明
请记住,数据应存储在模型的attributes属性中,以便正确保存,而不是作为单个实例变量保存
例如,要查看计划保存的内容,请执行以下操作:
class MyModel < ActiveRecord::Base
attr_accessor :not_saved
end
model = MyModel.new(:not_saved => 'foo')
puts model.attributes.inspect
下面是它的工作原理
在首次访问模型时,将检索相应数据库表中的列并将其存储在模型数据中。可以通过::class方法检索此信息
当您访问某个模型的属性时,Ruby在类中找不到相应的方法,并启动#method _missingmethod。该方法检查模型的::以检查对应的列是否存在。如果是这样,它将为该列创建一个访问器,以便下次访问该模型的属性时,将直接调用一个访问器方法,而无需调用#method_missing(后者速度较慢)
访问器如下所示:
def my_attribute
read_attribute(:my_attribute)
end
def my_attribute=(value)
write_attribute(:my_attribute, value)
end
对于#read_属性和#write_属性方法,有一个快捷方式:#和#。如果出于某种原因,您需要直接访问基础数据(例如,进行一些数据转换),您可以将它们写短:
def my_attribute
self[:my_attribute]
end
def my_attribute=(value)
self[:my_attribute] = value
end
模型有一个特殊的访问器--#--它返回一个“column_name=>value”散列
注意:每列的数据都存储在模型实例中的一个特殊哈希实例中,而不是“@column\u name”实例变量中。使用#attr_accessor定义访问器时,会阻止通过#method_missing定义属性访问器的常用方法。您的数据存储在实例变量中,而不是“”散列,因此它不会保存到数据库中
如果要向模型添加新属性,实际上需要向对应于该模型的数据库表中添加列,然后重新加载整个应用程序。忘了提到我已经尝试了我能想到的所有创建咒语:ProjectMeta.create(:project\u id=>project.id…,ProjectMeta.create do…end,等等…这正是我错过的。我发现修复方法是删除attr_访问器行,但我不明白为什么会这样。谢谢这是一个古老的答案,但。。。谢谢只是花了两个小时试图找出为什么一个模型不能保存。我在没有AR的情况下开发它,并且在那里有attr_访问器。
def my_attribute
self[:my_attribute]
end
def my_attribute=(value)
self[:my_attribute] = value
end