0

DeviceState「アクティブ」、「オフライン」、「オンライン」などの状態を含むモデルがあります。

Devicewhich belongs_totoという別のモデルがありDeviceStateます。

@device.active?デバイス モデルでやなどのメソッドを使用する@device.offline?ために、動的メソッドを次のように定義しました。

  DeviceState.all.each do |method|
    define_method((method.name + "?").to_sym) do
        self.device_state.name == method.name
    end
  end

私の問題は、モデルでテストを作成しようとすると、テスト環境の起動中にモデルがデータベースに取り込まれていないDeviceため、動的メソッドが作成されないことです。DeviceStateだからファクトリーガールでデータを作ってDeviceStateからでは遅い。

DeviceState私が試した解決策の 1 つは、 inをシードすることですspec_helperが、これは最初のテストでは機能しましたが、データベース クリーナーがデータを削除したため、残りのすべてのテストでは機能しませんでした。

これらの動的に定義されたメソッドを克服する最善の方法は何でしょうか?

4

1 に答える 1

0

コメントで誰もが指摘したように、データベース テーブルに基づいて、状態のリストを動的ではなく静的にする必要があります。

このリストを静的にすることにした場合は、次のようにして、状態を追加するたびに新しいメソッドを作成する必要がないようにします。

app\models\devise.rb

class Devise < ActiveRecord::Base
  ...
  extend EnumFieldUtil
  enum_field :devise_state, %w[active offline online]
  ...
end

lib必要に応じて他のモデルで再利用できるように、フォルダーで定義できるユーティリティ メソッドを使用する

lib\enum_field_util.rb

module EnumFieldUtil
  def enum_field(field, allowed_values)
    allowed_values.each do |value|
      class_eval %Q{
        define_method("is_#{value}?") { self.#{field} == '#{value}' }
      }
    end

    class_eval %Q{
      validates_inclusion_of :#{field}, :in => #{allowed_values}, :message => "{{value}} must be in #{allowed_values.join ','}"
    }
  end
end

Ryan Bate の State Machine の Rail Casts に触発されました。

于 2013-09-16T06:37:51.460 に答える