【问题标题】:Rails: Has and belongs to many (HABTM) -- create association without creating other recordsRails:拥有并属于许多(HABTM)——创建关联而不创建其他记录
【发布时间】:2011-01-19 00:13:02
【问题描述】:

在 Google 上花了一整天,但找不到答案。 :\

我在用户和 Core_Values 之间有 HABTM 关系。

class CoreValue < ActiveRecord::Base
  has_and_belongs_to_many :users

class User < ActiveRecord::Base
  has_and_belongs_to_many :core_values

在我的控制器中,我需要做两件事:

  1. 如果 CoreValue 不存在,则创建一个新的并将其与给定的用户 ID 相关联,并且
  2. 假设我知道某个特定的 CoreValue 确实存在,创建关联而不创建任何新的 CoreValues 或用户

对于#1,我已经完成了这个工作:

User.find(current_user.id).core_values.create({:value => v, :created_by => current_user.id})

这将使用 :value 和 :created_by 创建一个新的 CoreValue 并创建关联。

对于#2,我尝试了一些方法,但似乎不能仅创建关联。

感谢您的帮助!

【问题讨论】:

    标签: ruby-on-rails activerecord has-and-belongs-to-many


    【解决方案1】:

    您可以使用非常有用的find_or_create 方法分两步执行此操作。 find_or_create 将首先尝试查找记录,如果不存在,则创建它。像这样的东西应该可以解决问题:

    core_value = CoreValue.find_or_create_by_value(v, :created_by => current_user.id)
    current_user.core_values << core_value
    

    一些注意事项:

    • 第一行将查找或创建值v。如果它不存在并被创建,它会将created_by 设置为current_user.id
    • 无需执行User.find(current_user.id),因为这将返回与current_user 相同的对象。
    • current_user.core_values 是一个数组,您可以使用 &lt;&lt; 轻松为其添加另一个值。

    为简洁起见,以下与上面的代码示例相同:

    current_user.core_values << CoreValue.find_or_create_by_value(v, :created_by => current_user.id)
    

    【讨论】:

    • 谢谢!不知道 core_values 是一个数组——当然也不知道添加到数组会创建一个 INSERT。甜的!如果记录不存在,有什么方法可以只创建关联?我会去看看数组方法,我猜?也许 current_user.core_values.include?​​span>
    • @jmccartie 这可能是一种方法,是的。为澄清起见,我觉得我应该补充一点 core_values 不是 always 数组——如您所知,您可以调用 core_values.create 这不是有效的数组方法。更好的定义是它“充当数组”。
    • 感谢您的跟进。包括?不会工作。试图弄清楚我是否可以在 current_user.core_values 中找到新的 core_value id ... hmmmm
    • @jmccartie 你也可以current_user.core_value_ids,它会返回一个ID数组。那么current_user.core_value_ids.include?(core_value.id) 肯定可以工作。
    【解决方案2】:

    在你的用户模型中添加一个方法:

    class User < ActiveRecord::Base
      def assign_core_value(v)
        core_values.find_by_name(v) || ( self.core_values << 
          CoreValue.find_or_create_by_name(:name => v, :created_by => self)).last 
      end
    end
    

    assign_core_value 方法满足要求 1,2 并返回分配给用户(使用给定名称)的核心值。

    现在您可以执行以下操作:

    current_user.assign_core_value(v)
    

    注 1

    方法逻辑如下:

    1) 检查 CoreValue 是否已经与用户关联。如果不采取任何行动,则返回核心值。

    2) 检查具有给定名称的 CoreValue 是否存在。如果不是,则创建 CoreValue。将核心价值(创建/发现)与用户相关联。

    【讨论】:

    • 谢谢!将其添加到用户模型中是个好主意。如果关联已经存在,这会创建关联吗?
    • 用一些解释更新了我的答案。看看吧。
    【解决方案3】:

    Active Record 已经为您提供了一种方法。在你的情况下,

    val = CoreValue.find_by_value(v)
    current_user.core_values << val
    

    您也可以通过这种方式传递多个对象。将创建所有关联

    查看this了解更多信息

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多