【问题标题】:Ownership conditional in a belongs_to associationbelongs_to 关联中的所有权条件
【发布时间】:2016-02-23 02:23:10
【问题描述】:

我有两个模型: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

【问题讨论】:

  • 我不明白这句话:我想确保一个所有者永远不属于一个帖子你的意思是你不希望一个帖子的所有者成为另一个帖子的参与者发布?
  • 关闭但没有。对于一个特定的帖子,我不希望 owner 也成为 participant
  • 哦,知道了,给我 5 分钟

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


【解决方案1】:

要实现这一点,我认为您需要第三个模型。如果您按以下方式进行设置,它应该可以工作:

用户模型:

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

【讨论】:

  • 在您的回答中,您仍然允许用户与所有者一起创建 user_post,它对关联 :user_posts 不可见,但仍会在数据库中创建。
  • :-) 我刚刚在你的回答@Oxynum 上说了同样的话。两种方法基本上可以达到相同的结果
  • 无论如何都赞成,了解差异很有用
  • 谢谢!我投了你的票,还编辑了我的答案,因为我认为你的验证使它更完整。
【解决方案2】:

首先,您的关联可能存在错误,因为您似乎需要一个用于参与者关系的连接表。 您可能应该使用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

【讨论】:

  • 你的模型和我的回答基本一样。但我没有使用验证(这可能是最简单的事情)。我试图回答belongs_to 的条件问题。我的 lambda 将从参与者中过滤掉所有所有者。
  • 是的,我是在你回答的同时写的。但我认为验证更合适,因为您不保存所有者在数据库中的参与。我认为他不想从参与者中过滤所有者,但不想在参与者中拥有任何所有者。不确定我是否清楚...
猜你喜欢
  • 2011-01-10
  • 2012-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多