【问题标题】:Using Delegate With has_many In Rails?在 Rails 中使用带有 has_many 的委托?
【发布时间】:2013-12-28 15:08:27
【问题描述】:

我们有 2 个模型和一个连接模型:

#app/models/message.rb
Class Message < ActiveRecord::Base
    has_many :image_messages
    has_many :images, through: :image_messages
end

#app/models/image.rb
Class Image < ActiveRecord::Base
    has_many :image_messages
    has_many :messages, through: :image_messages
end

#app/models/image_message.rb
Class ImageMessage < ActiveRecord::Base
    belongs_to :image
    belongs_to :message
end

额外属性

我们希望从连接模型 (ImageMessage) 中提取额外属性,并在 Message 模型中访问它们:

@message.image_messages.first.caption # -> what happens now    
@message.images.first.caption #-> we want

我们已经在声明关联时使用select 方法实现了这一点:

#app/models/message.rb
has_many :images, -> { select("#{Image.table_name}.*", "#{ImageMessage.table_name}.caption AS caption") }, class_name: 'Image', through: :image_messages, dependent: :destroy

委托

我们刚刚找到了delegate 方法,它完全可以满足需要。但是,它似乎只适用于 has_onebelongs_to 关联

我们刚刚使用单个关联进行此操作,但它似乎不适用于集合(只是将您带到公共方法)


问题

您知道我们可以通过Image 模型从ImageMessage 连接模型返回.caption 属性吗?

我们目前有这个:

#app/models/image.rb
Class Message < ActiveRecord::Base
    has_many :image_messages
    has_many :messages, through: :image_messages

    delegate :caption, to: :image_messages, allow_nil: true
end

#app/models/image_message.rb
Class ImageMessage < ActiveRecord::Base
    belongs_to :image
    belongs_to :message

    def self.caption # -> only works with class method
        #what do we put here?
    end
end

更新

感谢 Billy Chan(对于实例方法的想法),我们已经让它非常暂时工作了:

#app/models/image.rb
Class Image < ActiveRecord::Base
    #Caption
    def caption
        self.image_messages.to_a
    end
end

#app/views/messages/show.html.erb
<%= @message.images.each_with_index do |i, index| %>
    <%= i.caption[index][:caption] %> #-> works, but super sketchy
<% end %>

有什么方法可以重构,特别是得到它,以便每次调用.caption 时,它都会返回该特定记录的image_message.caption 值?

【问题讨论】:

    标签: ruby-on-rails class ruby-on-rails-4 model rails-activerecord


    【解决方案1】:

    delegate 只是等效实例方法的简写。这不是一个适合所有人的解决方案,甚至有一些争论认为它并不那么明确。

    当简单的delegate 不适合时,您可以使用实例方法。

    def image_message_caption image_messages.class.caption 结尾

    我查看并发现在这种情况下没有任何关联。 ImageMes​​sage的类方法caption更像是一个常量,可以直接引用。

    def image_message_caption
      ImageMessage.caption
    end
    

    【讨论】:

    • 感谢您的提醒!我已将其放入 Image 模型中,但它返回 undefined method image_message'` 错误。我试过引用 self.image_message 但没有运气
    • @RichPeck,方法应该在消息模型中!用于替换delegate
    • 我更新了代码,应该是image_messages,复数。我的观点是,delegate 是简化和美化代码的简写,当事情变得非常规时,普通的实例方法会更好。
    • 感谢您的更新!我在Image 模型中有delegate 方法 - 看来您需要将该方法放入要调用该方法的模型中;对我们来说,这将是@message.images.first.caption,因此是Image。我会看看我能不能让它工作 - 非常感谢你到目前为止的帮助!
    • 对不起,我回答得太快了。我再次检查并发现在这种情况下不需要任何关联。最简单的方法吧def image_message_caption; ImageMessage.caption; end;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-25
    • 2014-05-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多