【问题标题】:ActiveRecord: Access join table attribute through association using delegateActiveRecord:使用委托通过关联访问连接表属性
【发布时间】:2016-03-02 15:55:20
【问题描述】:

我的应用程序中有一个Post 模型,它有一个posts 属性,用于存储一个看起来像这样的JSON 对象:

Post.last.posts = {
    twitter: 'This is a tweet',
    facebook: 'This is a facebook post'
}

用户创建一个Post,然后将其发送到多个平台。这种架构对于最初的应用程序设计是有意义的。现在我想为用户提供隐藏他们在一个平台上发布的帖子而不影响到其他平台的帖子的能力。因为帖子是数据库中的单个模型,所以我需要找到一种解决方法。我不确定这是否是最好的方法,但我决定在我的User 模型和Post 模型之间创建一个连接表。请注意,帖子是由不同的用户模型 (Admin) 创建的,User 仅查看帖子。

这是我的模型:

class Post < ActiveRecord::Base
    has_many :post_users
    has_many :users, through: :post_users
end

class User < ActiveRecord::Base
    has_many :post_users
    has_many :posts, through: :post_users
end

class PostUser < ActiveRecord::Base
    belongs_to :post
    belongs_to :user
    delegate :hide_twitter, to: :post
    delegate :hide_facebook, to: :post

    def hide_twitter
        self.hide_twitter
    end
end

在我正在构建的视图中,每个 Post 都表示为一系列卡片 - 每个平台一张。因此,如果帖子在 Twitter 和 Facebook 上,它将显示为两张单独的卡片 - 每个平台一张。我想要做的是让User 能够隐藏其中一张牌而不影响其他牌。因为Post 属于许多用户,所以它必须是连接表的一个属性(例如PostUser)。

我想知道的是是否可以通过Post 模型访问连接表的这个属性?我想做类似以下的事情,但我不确定这是否可行,或者我是否通过在我的联接表中使用 delegate 来采取正确的方法。

current_user.posts.first.hide_twitter
=> false
current_user.posts.first.hide_facebook
=> true

当我使用上面的delegate 并尝试调用上面的代码行时,我收到以下错误:

Post Load (1.4ms)  SELECT  "posts".* FROM "posts" INNER JOIN "post_users" ON "posts"."id" = "post_users"."post_id" WHERE "post_users"."user_id" = $1  ORDER BY "posts"."id" ASC LIMIT 1  [["user_id", 90]]
NoMethodError: undefined method `hide_twitter' for #<Post:0x007fc27d383f50>
from /Users/ACIDSTEALTH/.gem/ruby/2.3.0/gems/activemodel-4.2.5.1/lib/active_model/attribute_methods.rb:433:in `method_missing'

我意识到我可以做一些非常迂回的事情,比如this answer,但我希望做一些更优雅/更传统的事情。

【问题讨论】:

  • 如何在Post 模型中定义hide_twitterhide_facebook
  • 目前在我的Post 模型中没有定义。我不确定我在这里使用delegate。我阅读了 APIdock 上的文档,但对我来说并不是很清楚。
  • 签到看看你是否得到了这个排序。
  • 不,我无法让您的解决方案发挥作用。我最终实现了一个非常迂回的解决方案,需要直接访问连接表来获取属性。这可以满足我的需要,但它并不漂亮。
  • 对不起,我帮不上忙。很想看到您的解决方案,它也可能有助于未来的信息搜索。无论如何,祝你好运!

标签: ruby-on-rails activerecord associations


【解决方案1】:

怎么样:

  class Post < ActiveRecord::Base
    has_many :post_users
    has_many :users, through: :post_users
  end

  class User < ActiveRecord::Base
    has_many :post_users
    has_many :posts, through: :post_users
  end

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

然后:

PostUser.where(post: current_user.posts.first).hide_twitter

【讨论】:

  • 是的。我尝试将hide_twitter 的包装方法添加到我的ContactPosts 模型中,但我得到了同样的错误。
猜你喜欢
  • 2019-09-08
  • 1970-01-01
  • 2011-03-18
  • 1970-01-01
  • 2015-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多