2

在我的应用程序中,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 模型是正确的方法,还是您会推荐一些不同的方法?

4

3 回答 3

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

有关关联扩展的更多信息,请查看文档

遵守 demeter 定律的最好方法是或多或少地做你正在做的事情,因为通过在 上添加你的方法Photo,这意味着与 交互的方法Photo也不需要了解LandUse类,只需那张照片有一个方法可以返回土地用途名称的字符串。

于 2011-08-21T20:33:16.473 回答
0

您可以使用 :

class LandUse
  def self.list_for_photo(id)
    LandUse.find_by_photo_id(id).join(', ')
  end

  def to_s
    self.name
  end
end

希望能帮助到你 !

于 2011-08-21T16:13:31.387 回答
0

我不在 Rails 应用程序前,但我相信

photo.land_uses

LandUse返回一个对象数组

因此,您只需要将地图向下移动到该数组,例如:

photo.land_uses.map(&:name).join(', ')

这是您最初拥有的 - 只是在您的其他模型中。我认为您可能是对的,这意味着Photo知道太多,LandUse因此我会将其移出。

于 2011-08-21T16:16:02.857 回答