【问题标题】:Ruby on rails: Creating a model entry with a belongs_to associationRuby on rails:使用 belongs_to 关联创建模型条目
【发布时间】:2013-04-23 14:37:02
【问题描述】:

我正在尝试在我的数据库中为具有belongs_to 关系的模型添加一个新条目。我有 2 个模型,工作和客户。

很容易找到关于如何在这两者之间建立关联的教程(使用 has_many 和 belongs_to),但我似乎找不到任何实际使用关联的示例。

在我的代码中,我正在尝试为第一个客户创建一个新工作。作业模型有一个 client_id 属性,我知道我可以手动填充该属性,但必须有一些 ruby​​ 约定才能轻松完成此操作。

Job.create(:client_id => 1, :subject => "Test", :description => "This is a test")

我可以轻松地将其放入我的代码中,但我觉得 ruby​​ 有更好的方法来做到这一点。这是我的模型的设置方式

class Job < ActiveRecord::Base
  attr_accessible :actual_time, :assigned_at, :client_id, :completed_at, :estimated_time, :location, :responded_at, :runner_id, :status, :subject, :description
  belongs_to :client
end

class Client < User
    has_many :jobs
end

class User < ActiveRecord::Base
  attr_accessible :name, :cell, :email, :pref

end

【问题讨论】:

  • client = Client.new; Job.create(:client =&gt; client, :subject =&gt; "Test", :description =&gt; "This is a test")

标签: ruby-on-rails ruby ruby-on-rails-3 associations


【解决方案1】:

要创建新实例,您可以使用工厂。为此,您可以简单地使用 FactoryGirl https://github.com/thoughtbot/factory_girl

所以在你定义了你的工厂之后,像这样:

FactoryGirl.define 做 工厂:工作做 客户端 FactoryGirl.create(:client) 主题“测试” description '这是一个测试'

然后您可以调用 FactoryGirl.create(:job) 来生成这样的新作业。 您也可以调用 FactoryGirl.build(:job, client: aClientYouInstantiatedBefore, subject: 'AnotherTest') 并覆盖任何其他属性

如果您想创建许多在某些方面相似的对象,因素是很好的。

【讨论】:

  • 在他的问题中没有提到他想为规格做这件事。
  • 您可以在任何地方使用工厂,而不仅仅是在规格或测试中
  • 如果你使用工厂女孩进行开发,那你就错了。
  • @MentholBonbon 你说得对,Factories are good if you want to create many objects, that are similar in a certain way...这就是设计模式的定义。但是 FactoryGirl,尽管有这个名字,但它是用于测试的。
  • 您可以在group: development 中使用它,但仅用于在控制台中快速创建内容。它不应该在 gemfile 的生产组中,或者在你的模型/控制器/视图的任何部分中。
【解决方案2】:

只需在客户端的jobs 集合上调用create

c = Client.find(1)
c.jobs.create(:subject => "Test", :description => "This is a test")

【讨论】:

  • 不好,如果没有 id=1 的条目会引发 ActiveRecord::RecordNotFound .... 使用 Client.find(:first)Client.first
  • @MrYoshiji 引发异常通常是预期的行为,因为在 Rails 中 RecordNotFound 异常会在异常应用程序中转换为 404 请求。
【解决方案3】:

您可以将对象作为参数传递来创建作业:

client = Client.create
job = Job.create(client_id: client.id, subject: 'Test', description: 'blabla')

如果对象无法保存(如果您设置了强制名称等验证),create 方法将引发错误。

【讨论】:

  • 这只有在client被标记为attribute_accessible时才有效
【解决方案4】:

将对象本身作为参数传递,而不是传递其 ID。也就是说,不要传递:client_id =&gt; 1:client_id =&gt; client.id,而是传递:client =&gt; client

client = Client.find(1)
Job.create(:client => client, :subject => "Test", :description => "This is a test")

【讨论】:

    【解决方案5】:

    你可以这样使用create_job

    client = Client.create
    job = client.create_job!(subject: 'Test', description: 'blabla')
    

    当你声明一个belongs_to关联时,声明类会自动获得与该关联相关的五个方法:

    association
    association=(associate)
    build_association(attributes = {})
    create_association(attributes = {})
    create_association!(attributes = {})
    

    在所有这些方法中,关联都替换为作为第一个参数传递给belongs_to 的符号。

    更多:http://guides.rubyonrails.org/association_basics.html#belongs-to-association-reference

    【讨论】:

    • 如果关联是belongs_to 而不是has_many,这将起作用。很高兴知道,但这并不能解决问题。
    猜你喜欢
    • 1970-01-01
    • 2017-03-28
    • 1970-01-01
    • 2011-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多