创建ActiveRecord模型时出现问题:保存中缺少数据

loc*_*red 4 ruby activerecord model sinatra

我正在开发的Sinatra应用程序中使用ActiveRecord在数据库中创建新的模型行时遇到问题.正在创建的对象没有任何错误(使用save!,没有引发异常),但是我为保存指定的大多数数据都不存在.

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
Run Code Online (Sandbox Code Playgroud)

对我正在发送的项目对象的数据进行的所有检查以及我正在创建的新元对象都显示数据存在.但是当我meta.inspect在保存之前和之后执行操作时,它会显示所有数据(除了project_id)都处于默认状态(零).我也检查过meta.errors.nil?,保存后没有任何错误.

最令人费解的是,如果我转向并使用该project_id获取新的元实例并将数据放入其中,则可以为数据库节省任何问题.

这让我感到很沮丧,因为我已经使用ActiveRecord在Rails和Sinatra中构建了几个站点.这个问题让我感到困惑.谁能告诉我我做错了什么?

Max*_*kin 6

下面是它的工作原理

  1. 在第一次访问模型时,将检索相应数据库表中的列并将其存储在模型数据中.可以通过:: columns类方法检索此信息.

  2. 当您访问某个模型的属性时,Ruby在类中找不到相应的方法并启动#method_missing方法.该方法检查模型的:: 以检查相应的列是否存在.如果是这样,它会为该列创建一个访问器,以便下次访问该模型的属性时,将直接调用访问器方法,而无需调用#method_missing(后者更慢).

访问器看起来像这样:

def my_attribute
  read_attribute(:my_attribute)
end

def my_attribute=(value)
  write_attribute(:my_attribute, value)
end
Run Code Online (Sandbox Code Playgroud)

对于#read_attribute和#write_attribute方法,有一个快捷方式:#[]和#[] =.如果由于某种原因您需要直接访问底层数据(例如进行一些数据转换),您可以将它们写得很简短:

def my_attribute
  self[:my_attribute]
end

def my_attribute=(value)
  self[:my_attribute] = value
end
Run Code Online (Sandbox Code Playgroud)

Model有一个特殊的访问器 - #attributes - 返回一个"column_name => value"Hash.

注意:每列的数据存储在模型实例内的特殊Hash实例中,而不是"@column_name"实例变量中.使用#attr_accessor定义访问器时,会阻止通过#method_missing定义属性访问器的常用方法.您的数据存储在实例变量中而不是" 属性 "哈希中,因此它不会保存到数据库中.

如果要向模型添加新属性,实际上需要将列添加到与该模型对应的数据库表,然后重新加载整个应用程序.