使用委托使用has_many在Rails中?

时间:2013-12-28 15:08:27

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

我们有两个型号&连接模型:

#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关联

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


问题

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

我们目前有这个:

#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值?

1 个答案:

答案 0 :(得分:6)

delegate只是一种速记作为等效实例方法。对所有人来说,这不是一个解决方案,甚至还有一些争论不是那么明确。

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

<德尔>     def image_message_caption       image_messages.class.caption     结束

我审核并发现这种情况不需要任何关联。 ImageMes​​sage的类方法标题更像是常量,您可以直接引用它。

def image_message_caption
  ImageMessage.caption
end