【问题标题】:Rails belongs_to has_many with db conditionsRails belongs_to has_many 与 db 条件
【发布时间】:2014-04-24 12:36:33
【问题描述】:

我有两个模型,比如说:

Post:
  blog_id: integer
  external_id: integer

Comment:
  blog_id: integer
  external_reference_id: integer

并且在我的数据库中有一些项目:

Post.create external_id: 10, title: "Test 1", blog_id: 1
Post.create external_id: 10, title: "Test 2", blog_id: 2
Post.create external_id: 10, title: "Test 3", blog_id: 3

Comment.create external_reference_id: 10, title: "Comment 1.1", blog_id: 1
Comment.create external_reference_id: 10, title: "Comment 1.2", blog_id: 1

Comment.create external_reference_id: 10, title: "Comment 2.1", blog_id: 2
Comment.create external_reference_id: 10, title: "Comment 2.2", blog_id: 2

我需要使用external_ 引用来关联帖子和cmets,即:

class Post < ActiveRecord::Base
    has_many :comments, foreign_key: :external_reference_id, primary_key: :external_id
end

class Comments < ActiveRecord::Base
    belongs_to :post, foreign_key: :external_reference_id, primary_key: :external_id
end

我需要将 blog_id 上两者之间的关系“限定”为相同。

我的意思是我在不同的服务器/数据库上有不同的博客,并且我在主服务器中收集所有数据。我无法保留原始 ID,因此我将 id 存储为 external_id。这意味着带有external_id: 1blog_id: 4 的帖子将包含所有带有external_reference_id: 1blog_id: 4 的评论。

我可能有很多具有相同 external_id 的 cmets,但只有具有相同 blog_id 的 cmets 真正匹配。

上网,我发现了一些提示,最流行的意见是这样的:

class Post < ActiveRecord::Base
  has_many :comments, -> (object){ where("comments.blog_id = #{object.blog_id}") }, foreign_key: :external_reference_id, primary_key: :external_id
end

此解决方案在执行Post.first.comments 时正确生成查询:

SELECT COUNT(*) FROM "cmets" WHERE "cmets"."external_reference_id" = ? AND (cmets.blog_id = 1) [["external_reference_id", 10]]

但是当尝试像Post.joins(:comments).count 给予这样更深奥的东西时,它会惨遭失败:

NoMethodError: undefined method `blog_id' for #<ActiveRecord::Associations::JoinDependency::JoinAssociation

到目前为止,我的解决方案是:

class Post < ActiveRecord::Base
  has_many :comments, -> (object){ where(object.respond_to?(:blog_id) ? "comments.blog_id = #{object.blog_id}" : 'comments.blog_id = posts.blog_id') }, foreign_key: :external_reference_id, primary_key: :external_id
end

这很好用,但在我看来有点过于复杂了。有没有更好的方法来实现这一点?

【问题讨论】:

  • 你能解释更多关于What I need is to "scope" the relation between the two on blog_id to be the same.的信息吗?比如和什么一样?
  • 我的意思是,只有与 blog_id 字段匹配的评论才属于帖子。假设我在不同的服务器/数据库中有不同的博客,并且我正在将所有数据导入到我的主服务器中。我无法保留 id,所以我将原始 id 保存在 external_id 中用于帖子,并将原始 post_id 保存在 external_reference_id 中用于内容。因此,评论帖子是具有与 external_reference_id 匹配的 external_id 并且具有相同 blog_id 的帖子。我知道这可能不是更好的实现,但这是我现在的数据。
  • 啊,你应该把它添加到 OP 中,因为它是有用的信息。
  • 我遇到了同样的问题,在这里找到了回复:stackoverflow.com/questions/13893429/…

标签: ruby-on-rails activerecord relationship rails-activerecord


【解决方案1】:

你可以给has_many和belongs_to添加:conditions,例如

class Post < ActiveRecord::Base
  has_many :comments, foreign_key: :external_reference_id, primary_key: :external_id, :conditions => ["comments.blog_id = posts.blog_id"]
end

class Comments < ActiveRecord::Base
  belongs_to :post, foreign_key: :external_reference_id, primary_key: :external_id, :conditions => ["comments.blog_id = posts.blog_id"]
end 

我还没有测试过,但是试一试。

【讨论】:

  • 这是我尝试过的方法之一,但是在调用关系时它不起作用:Comment.first.post 仅在 post 表中进行查询,因此尝试使用 comments.blog_id = posts.blog_id 会破坏查询: SELECT "posts".* FROM "posts" WHERE "posts"."external_id" = ? AND (comments.blog_id = posts.blog_id) ORDER BY "posts"."id" ASC LIMIT 1 [["external_id", 10]]
猜你喜欢
  • 2011-12-20
  • 1970-01-01
  • 1970-01-01
  • 2015-07-22
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多