所有权在belongs_to关联中有条件

时间:2015-11-20 14:40:24

标签: ruby-on-rails ruby activerecord associations conditional-statements

我有两个模型:UsersPosts。我设置东西的方式,帖子属于所有者(即用户),并且还有许多参与者(即用户)。在我的用户模型中,我希望确保owner永远不属于post。我在前端完成了这项工作,但发现了比需要更多的代码。

这让我相信使用conditions将是一个理想的解决方案。我已经看到了以这种方式使用的SQL条件,但并不确切知道为所有权方案完成此操作的最佳方法。建议?

class User < ActiveRecord::Base
  has_many :posts
  # belongs_to :posts, conditions: ...
end

class Post
  has_many :participants, class_name: "User", foreign_key: "user_id"
  belongs_to :owner, class_name: "User", foreign_key: "user_id"
end

2 个答案:

答案 0 :(得分:2)

为了实现这一目标,我认为你需要第三种模式。如果按照以下方式进行设置,则应该有效:

用户模型:

class User < ActiveRecord::Base
  has_many :posts  # This is the other side of your owner association
  has_many :user_posts  # This is your link table for participants
  has_many :participations, through: :user_posts, source: :user # These are the posts the user is a participant in
end

发布模型:

class Post < ActiveRecord::Base
  has_many :user_posts, ->(p) { where.not(user_id: p.user_id) } # Here is your condition for the participants
  has_many :participants, through: :user_posts, source: :user
  belongs_to :owner, class_name: "User", foreign_key: "user_id"
end

UserPost模型:

class UserPost < ActiveRecord::Base
  belongs_to :user
  belongs_to :post
end

正如@ Oxynum的答案所表明的那样,您还应该考虑在UserPost模型中进行验证,以防止参与者如果他也是所有者而被保存:

validate :participant_cannot_be_owner

  def participant_cannot_be_owner
    if user == post.try(:owner)
      errors.add(:user_id, "can't be the owner of the post")
    end
  end

答案 1 :(得分:1)

首先,您的关联中可能存在错误,因为您似乎需要参与者关系的连接表。 您应该使用http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association has_many通过协会。

这样的事情:

class User < ActiveRecord::Base
  has_one :owned_post, class_name: "Post", foreign_key: :owner_id
  has_many :participations
  has_many :posts, through: :participations
end

class Participation < ActiveRecord::Base
  belongs_to :post
  belongs_to :participant, class_name: "User"
end

class Post < ActiveRecord::Base
  belongs_to :owner, class_name: "User"
  has_many :participants, through: :participations
end

如果您拥有此模型,则可以对参与模型使用验证,以防止所有者成为参与者。使用自定义验证:http://guides.rubyonrails.org/active_record_validations.html#performing-custom-validations

class Participation < ActiveRecord::Base
  belongs_to :post
  belongs_to :participant, class_name: "User"
  validate :participant_is_not_the_owner

  def participant_is_not_the_owner
    if participant == post.owner
      errors.add(:participant, "can't be the owner")
    end
  end
end