2

私のアプリでは、Photo has_and_belong_to_many :land_uses

Photoモデルに次のヘルパー メソッドがあります。

def land_use_list
  land_uses.map(&:name).join(', ')
end

これはコードの匂い (デメテル) のように感じますが、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

まず、これがデメテルの法則自体に違反しているとは思いません。属性の 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を確認してください。

デメテルの法則に準拠する最善の方法は、多かれ少なかれあなたがしていることを行うことです。なぜなら、あなたのメソッドを に追加することによって、Photoと相互作用するメソッドがクラスPhotoについて知る必要がないことを意味するからです。LandUseその写真には、土地利用の名前の文字列を返すメソッドがあります。

于 2011-08-21T20:33:16.473 に答える
0

私はレールアプリの前にいませんが、私は信じています

photo.land_uses

LandUseオブジェクトの配列を返す

したがって、次のようにマップをその配列に移動するだけです。

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

これはあなたがもともと持っていたものです - あなたの他のモデルだけです。私はあなたが正しいかもしれないと思いPhotoますLandUse.

于 2011-08-21T16:16:02.857 に答える
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 に答える