【问题标题】:multiple has_many through relationships多个 has_man 通过关系
【发布时间】:2012-09-26 18:55:27
【问题描述】:

我正在建立一个协作写作平台。用户可以拥有项目集,其中任何项目都可以在任何集中并属于任何用户。但这会导致一些问题。

这些是我的模型关系:

class Association < ActiveRecord::Base
  belongs_to :user
  belongs_to :set
  belongs_to :item
end  

class Set < ActiveRecord::Base
  has_many :associations
  has_many :users, through: :associations
  has_many :items, through: :associations 
end

class Item < ActiveRecord::Base
  has_many :associations
  has_many :users, through: :associations
  has_many :sets, through: :associations 
end

我无法弄清楚正确处理此问题的“rails 方式”。

问题一:

创建新项目时,仅存储集合/项目关联,而不存储用户:

class ItemsController < ApplicationController
  def create
    @set = current_user.sets.find(params[:set_id])
    @set.where(title: params[:item][:title]).first_or_create!
  end
end   

*更新*

要解决问题 1,我能想到的最好办法是执行以下操作:

@set  = current_user.sets.find(params[:set_id])
@item = Item.where(name: params[:item][:title]).first_or_create!
Association.where(item_id: @item.id, set_id: @set.id, user_id: current_user.id).first_or_create!

感觉很不对劲!

问题 2:

假设关联表从问题 1 中正确填充,以下控制器将返回集合拥有的所有项目,但忽略用户所有权:

class SetsController < ApplicationController
  def index
    @sets = current_user.sets.includes(:items)
  end
end 

*更新*

仍然没有运气找到答案。 为了更好地解释这个问题:

以下将只返回属于当前用户的集合

@sets = current_user.sets.all

但是,以下将仅返回用户的集合,但将包括集合的所有项目,即使它们不属于当前用户。换句话说,用户范围被删除了。

@sets = current_user.sets.includes(:items)

我整天都在努力解决这个问题,但似乎找不到线索

【问题讨论】:

  • 将其分解为 1:Many's... 创建集合实例。

标签: ruby-on-rails ruby has-many-through named-scope nested-includes


【解决方案1】:

您的第一个问题是确保您的实例变量是相同的。一个是大写的。应该是这样的:

class ItemsController < ApplicationController
  def create
    @set = current_user.sets.find(params[:set_id])
    @set.where(title: params[:item][:title]).first_or_create!
  end
end    

【讨论】:

    【解决方案2】:

    这是你的意思吗? 一个用户可以拥有许多项目。 一个用户可以有多个集合。

    一个项目可以属于多个用户。 一个项目可以属于多个集合。

    如果是这种情况,您需要多个连接模型。

    Class UserItemAssociation < ActiveRecord::Base
      belongs_to :user
      belongs_to :item
    end
    
    Class SetItemAssociation < ActiveRecord::Base
      belongs_to :set
      belongs_to :item
    end
    
    Class Item < ActiveRecord::Base
      has_many :user_item_associations
      has_many :users, through: :user_item_associations
    
      has_many :set_item_associations
      has_many :sets, through :set_item_associations
    end
    
    Class Set < ActiveRecord::Base
      belongs_to :user
    end
    

    在控制器中:

    @set = current_user.sets.find_or_create_by(params[:set_id])
    @item = @set.items.where(title: params[:item][:title]).first_or_create!
    current_user.items << @item
    

    但是,这里有另一种看待它的方式。

    在用户模型中,添加这个方法。

      def items
        self.sets.collect{|set| set.items}.flatten
      end
    

    这样,您只需要关联模型将用户加入集合,但您现在仍然可以访问 user.items。

    【讨论】:

    • 对,这就是我想要解决的问题。查询真的与这种结构叠加。难道没有办法拥有一个跟踪所有关系的关联表吗?在 Rails 之外很容易做到。
    • 即便如此,对于每个关系使用不同的关联表,问题是相同的:当您选择当前用户的所有集合并包含项目时,集合的所有项目都将返回而不是作用域当前用户。
    • 见上面的编辑。我从未见过任何连接三个不同类的连接表,但永远不要说永远。
    猜你喜欢
    • 1970-01-01
    • 2016-05-08
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多