1

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

这些是我的模型关系:

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

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

问题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   

*更新*

要解决问题 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)

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

4

2 回答 2

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。

于 2012-09-26T20:34:40.440 回答
2

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

class ItemsController < ApplicationController
  def create
    @set = current_user.sets.find(params[:set_id])
    @set.where(title: params[:item][:title]).first_or_create!
  end
end    
于 2012-09-26T20:18:26.450 回答