使用delegate with has_many在Rails? [英] Using Delegate With has_many In Rails?

查看:145
本文介绍了使用delegate with has_many在Rails?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有2个模特&连接模型:

 #app / models / message.rb 
类消息< 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 ImageMes​​sage < ActiveRecord :: Base
belongs_to:image
belongs_to:message
end



< hr>

额外属性



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

  @ message.image_messages.first.caption# - >现在发生什么
@ message.images.first.caption# - >我们需要

我们已经使用 select 方法时声明的关联:

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






代表



我们刚刚发现 委托 方法,这正是这需要的。但是,它只适用于 has_one belongs_to 关联



我们只是使用一个单一的协会,但似乎它不工作的集合(只需要你到一个公共方法)






问题



你知道我们可以返回 .caption Image 模型从 ImageMes​​sage 连接模型中创建c $ c>属性?



我们目前有:

 #app / models / image.rb 
; 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 ImageMes​​sage< ActiveRecord :: Base
belongs_to:image
belongs_to:message

def self.caption# - >只有类方法
#我们在这里放吗?
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]%> # - >工作,但超粗略
<%end%>

任何重构的方式,特别是让每次 .caption 被调用,它返回该记录的 image_message.caption 值?

解决方案

委托只是等效实例方法的简写。这不是所有的解决方案,甚至有一些争论,它不是那么明确。



当简单委托不能使用时,可以使用实例方法。




def image_message_caption
image_messages.class caption
end


任何关联都是不必要的。 ImageMes​​sage的类方法caption更像一个常量,可以直接引用它。

  def image_message_caption 
ImageMes​​sage.caption
end


We've got 2 models & a join model:

#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


Extra Attributes

We're looking to extract the extra attributes from the join model (ImageMessage) and have them accessible in the Message model:

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

We've already achieved this using the select method when declaring the association:

#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

We've just found the delegate method, which does exactly what this needs. However, it only seems to work for has_one and belongs_to associations

We just got this working with a single association, but it seems it does not work for collections (just takes you to a public method)


Question

Do you know any way we could return the .caption attribute from the ImageMessage join model through the Image model?

We have this currently:

#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


Update

Thanks to Billy Chan (for the instance method idea), we have got it working very tentatively:

#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 %>

Any way to refactor, specifically to get it so that each time .caption is called, it returns the image_message.caption value for that particular record?

解决方案

delegate is just a shorthand as equivalent instance method. It's not a solution for all, and there are even some debate that it's not so explicit.

You can use an instance method when simple delegate can't fit.

def image_message_caption image_messages.class.caption end

I reviewed and found any association is unnecessary is this case. The ImageMessage's class method caption is more like a constant, you can refer it directly.

def image_message_caption
  ImageMessage.caption
end

这篇关于使用delegate with has_many在Rails?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆