Rails - 从另一个模型中创建模型的实例

时间:2016-01-18 22:23:05

标签: ruby-on-rails ruby

我正在构建一个应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。

汽车模型

class Car < ActiveRecord::Base
  has_many :tires

  after_create :make_tires

  def make_tires
    4.times { Tire.create(car: self.id) }
  end
end

轮胎模型

class Tire < ActiveRecord::Base
  belongs_to :car
end

然而,在make_tires内部,如果我尝试使用Tire,则会出现错误,即没有用于create或new的activerecord方法。当我检查轮胎时,它没有那些方法。

我该如何解决这个问题?

错误是:undefined method 'create' for ActiveRecord::AttributeMethods::Serialization::Tire::Module

我测试了两种环境:测试和开发,它们都因同一错误而失败。

2 个答案:

答案 0 :(得分:6)

这是名称冲突。在我解释的时候坐下来放松一下。

解释说明:

在Ruby类中只是类Class的实例(它是类Module的子类)。 Module的实例(包括Class的实例)是非常奇怪的对象,特别奇怪的是它们与ruby常量的连接。您可以使用标准ruby表示法随时创建一个新类:

my_class = Class.new { attr_accessor :a }
instance = my_class.new
instance.a = 3
insatnce.a   #=>
instance.class.name #=> nil

好吧,我们班没有名字。这只是一个匿名课程。班级如何获得他们的名字?通过将其分配给常量(第一次):

MyClass = my_class
my_class.name   #=> 'MyClass'

使用class关键字定义类时:

class MyClass
  ...
end

您只需创建一个新的Class实例并将其分配给常量。因此,看到常量的Ruby编译器不知道它是一个类还是一个数字 - 它必须对该常量进行全面搜索。

找到常量的逻辑非常复杂,取决于当前的嵌套。你的情况非常简单(因为没有嵌套),因此ruby将首先尝试在你的类中找到Tire类,当它失败时它的子类和包含的模块。

你的问题是你的类继承自ActiveRecord :: Base(这是正确的),其中包括ActiveRecord::AttributeMethods::Serialization模块,它已经定义了Tire常量。因此,ruby将使用此常量,因为这是在给定上下文中该名称的最佳匹配。

要修复它,你必须告诉编译器不要在当前类中查看,而是直接在&#34; top命名空间&#34; (在ruby中是Object。请认真地尝试Object.constants) - 您可以使用::在常量前面执行此操作,例如::Tire

注意:即使它有效,但这个问题首先警告您代码开始闻到。你应该照顾这个ActiveRecord::AttributeMethods::Serialization::Tire::Module这件事,因为你将来会不止一次地遇到它。

其他东西:

您可以稍微简化一下方法:

def make_tires
  4.times { tires.create }
end

此时您可能会遇到最初的错误。如果你这样做,那么请查看Tire::Module事件发生了什么。如果你不在乎气味:

has_many :tires, class_name: '::Tire'

答案 1 :(得分:0)

我不确定是什么导致你看到的异常,但是你有很多问题。首先,您需要传递汽车实例而不是make_tires中的ID。像这样:

def make_tires
  4.times { Tire.create(car: self) }
end

您还需要在轮胎模型中使用attr_accessible :car。像这样:

class Tire < ActiveRecord::Base
  belongs_to :car
  attr_accessible :car
end