在我的应用中,Photo has_and_belong_to_many :land_uses
我在Photo
模型中有这个辅助方法:
def land_use_list
land_uses.map(&:name).join(', ')
end
这让我感觉像代码气味(demeter),但我无法弄清楚如何将它移动到LandUse模型。我想做的是:
class LandUse < ActiveRecord::Base
...
def self.list
self.map(&:name).join(', ')
end
...
end
因此,我可以致电photo.land_use_list
而不是致电photo.land_uses.list
。
但这不起作用,因为它是针对类调用的,而不是针对属于特定照片的作用域实例进行调用。
有没有办法做我正在考虑的事情?而且,更一般地说,您如何在应用中处理此类问题?将列表代码移动到LandUse模型是正确的方法,还是会推荐不同的东西?
答案 0 :(得分:1)
首先,我不认为这违反了得墨忒耳本身的规律。你有一个对象的方法,它在一个属性上调用一个方法来创建一个临时变量,然后对临时变量进行操作。
如果你是完全从另一个班级做这件事,那将违反得墨忒耳法。例如
class User
def names_of_lands_ive_known
photos.map(:land_uses).map(:name).join ', '
end
end
实际上,它只是隐藏着良好的信息。但是,如果您希望能够编写photo.land_uses.names
,则可以为关联添加扩展以执行您想要的操作。
class Photo
has_and_belong_to_many :land_uses do
def names_as_list_string
all.map(:name).join ', '
end
end
end
有关关联关联扩展的详细信息,请查看docs。
符合demeter法则的最佳方法是尽可能地做你正在做的事情,因为通过在Photo
上添加你的方法,这意味着与Photo
交互的方法,不需要知道LandUse
类,只是该照片有一个返回土地使用名称字符串的方法。
答案 1 :(得分:0)
您可以使用:
class LandUse
def self.list_for_photo(id)
LandUse.find_by_photo_id(id).join(', ')
end
def to_s
self.name
end
end
希望它有所帮助!
答案 2 :(得分:0)
我不在铁轨应用程序前面,但我相信
photo.land_uses
返回一个LandUse
个对象
所以你只需将地图向下移动到那个数组:
photo.land_uses.map(&:name).join(', ')
这是你原来的 - 只是在你的其他模型中。我认为你可能是对的,这意味着Photo
对LandUse
了解得太多,因此我会把它移出来。