0

Rails 3.2 フォームには、setter メソッドが添付された find_or_create フィールドがあり、現在 before_validate を実行しているメソッドがあります。setter メソッドの前に before_validate メソッドを実行する必要があります。これを実現するには、コードをどのように変更すればよいですか?

私のフォームには以下が含まれます:

<%= f.select(:country_id, Country.order(:name), :id, :name, include_blank:true) %>
<%= f.grouped_collection_select :state_id, Country.order(:name), :states, :name, :id, :name, include_blank: true %>
<%= f.text_field :new_state_name, placeholder: "..or enter a new state" %>
<%= f.input :city_name %>

私が持っているモデルでは

def city_name
 city.try(:name)
end

def city_name=(name)
  if name.present?
    set_city = City.find_or_initialize_by_name_and_state_id(name, self.state_id)
    if set_city.new_record?
      set_city.state_id = state_id
      set_city.save(:validate => false )
      self.city = set_city
    else
      self.city = set_city
    end
  end
end

before_validation :create_new_state

def create_new_state
  if new_state_name.present? && country_id.present?
    new_state = State.create( name: new_state_name, country_id: country_id )
    self.state = new_state.id
  end
end

アイデアは、ユーザーが国と州を選択し、名前と州に対して見つかった都市名を入力できるというものです。そのような都市が存在しない場合は、作成されます。

さらに、必要な州が選択フィールドに存在しない場合、ユーザーは代わりに new_state_name フィールドに新しい州を入力できます。保存すると、新しい州が作成され、新しい都市に関連付けられる必要があります (新しい州が入力された場合、都市は新しいものでなければなりません)。

私が抱えている問題は、city_name セッターがbefore_validationメソッドの前に実行されているように見えることです。そのため、状態選択で選択された値 (空白の場合を含む) を使用して、新しい都市が作成されます。

目的の結果を達成するためにコードを構造化するより良い方法は何ですか? ありがとう

4

1 に答える 1

0

これは私がそれを行う方法です。(モデルコードを少し変更してもかまわないことを願っています。)

delegate :name, to: :city, prefix: true
delegate :name, to: :state, prefix: true

attr_writer :city_name, :state_name
attr_accessible :city_name, :state_name

before_validate :find_or_create_city_and_state

validates :city, :state, presence: true

private

def find_or_create_city_and_state
  if state_name
    state = State.find_or_create_by_name_and_country_id(state_name, country.id)
    self.state = state

    if city_name # Nested since this doesn't make any sense without a state, presumably
      city = City.find_or_create_by_name_and_state_id(city_name, state.id)
      self.city = city
    end
  end
end

フォームで、フィールドcity_nameを呼び出して、準備state_nameができているはずです。

于 2012-06-30T15:37:24.067 に答える