Пользовательские проверки Rails с многомодельными формами - PullRequest
0 голосов
/ 09 февраля 2010

У меня проблемы с пользовательскими проверками на рельсах.

  def validates_hsp_program(*attr_names)
    options = attr_names.extract_options!
    regex = '^('
    err = ''
    $CetConfig.program.each do |key, val|
      regex << val.to_s << '|'
      err << $CetConfig.program_prefix + " " + val.to_s + ", "
    end

    regex.chomp!('|')
    regex << ')$'
    regex = Regexp.new(regex)

    validates_each attr_names do | record, attr_name, value |
    exit 1
      unless value.nil? or value =~ regex
        record.errors.add(attr_name, 'must be one of ' + err.chomp(", "));
      end
    end

  end

Проблема в том, что для целей отладки я добавил выход 1, так как я не получал сообщение об ошибке для недопустимой даты для этого поля. Тем не менее, он никогда не выходит. Это то же самое, что я делаю во всех других пользовательских валидаторах. Единственное отличие, которое я вижу, состоит в том, что эта модель является второй моделью многомодельной формы, а все остальные относятся к первой модели ... Что я делаю не так?

Моя модель

class ProfileProgram < ActiveRecord::Base
  set_table_name "profile_program"
  set_primary_key "STUDENT_ID"
  belongs_to :profile_core, :primary_key => "STUDENT_ID", :foreign_key => "STUDENT_ID"

  validates_presence_of :program
  validates_hsp_program :program
end

Действие от моего контроллера

def create
  @pc = ProfileCore.new(params[:profile_core]) 
  @pp = ProfileProgram.new(params[:profile_program]) 

  @pc.student_type = $CetConfig.student_type.application
  @pc.AGENT_ID = current_agents_staff.AGENT_ID

  year = @pc.contract.to_s

  case @pp.program
    when 10 then
      sd = year + '-09-01'
      ed = year + '-06-30'
    when 51 then
      sd = year + '-08-15'
      ed = year + '-06-30'
    when 52 then
      sd = year + '-01-15'
      ed = year + '-06-30'
    when 12 then
      sd = year + '-01-15'
      ed = year + '-01-14'
    else
      sd = nil
      ed = nil
  end

  @pc.start_date = Date.parse(sd) unless sd.nil?
  @pc.end_date = Date.parse(ed) unless ed.nil?

  @pc.program_status = $CetConfig.student_status.apply

  if @pc.valid? and @pp.valid?
    ProfileCore.transaction do
      @pc.save!
      @pp.save!
    end
    redirect_to(students_path(@pc.STUDENT_ID))
  else
    render :action => 'new'
  end
end

Мое представление (element_block - это помощник, который просто вставляет метку и поле в правильные теги для dl)

<% form_for :profile_core, @pc, :url => { :controller => 'core', :action => 'create'}  do |f| %>
  <%= error_messages_for :object => [ @pc, @pp ]  %>
  <dl>
    <%= element_block f.label(:contract, 'Contract Year'), f.contract_year_select(:contract) %>
    <% fields_for :profile_program do |pp| %>
      <%= element_block pp.label(:program, 'Program'), pp.hsp_program_select(:program) %>
    <% end %>

    <%= element_block f.label(:passport_number, 'Passport Number'), f.text_field(:passport_number) %>
    <%= element_block f.label(:passport_country, "Country that issued the student's passport"), f.countries_select(:passport_country) %>
    <%= element_block f.label(:passport_expires, 'Passport Expiration Date'), f.text_field(:passport_expires, :class => 'datepicker') %>
    <%= element_block f.label(:last_name, 'Last Name (as on passport)'), f.text_field(:last_name) %>
    <%= element_block f.label(:first_name, 'First Name (as on passport)'), f.text_field(:first_name) %>
    <%= element_block f.label(:middle_name, 'Middle Name (as on passport)'), f.text_field(:middle_name) %>
    <%= element_block f.label(:other_names, 'Other Names'), f.text_field(:other_names) %>
    <%= element_block f.label(:residence_street_address, 'Street Address'), f.text_field(:residence_street_address) %>
    <%= element_block f.label(:residence_city, 'City'), f.text_field(:residence_city) %>
    <%= element_block f.label(:residence_province, 'Province'), f.text_field(:residence_province) %>
    <%= element_block f.label(:residence, 'Country'), f.text_field(:residence) %>
    <%= element_block f.label(:residence_postal_code, 'Postal Code'), f.text_field(:residence_postal_code) %>
    <%= element_block f.label(:birthdate, 'Date of Birth'), f.text_field(:birthdate, :class => 'datepicker', :id => "student_birth_date") %>
    <%= element_block f.label(:citizenship, 'Country of Citizenship'), f.countries_select(:citizenship) %>
    <%= element_block f.label(:birth_city, 'Birth City'), f.text_field(:birth_city) %>
    <%= element_block f.label(:nationality, 'Nationality'), f.countries_select(:nationality) %>
    <%= element_block f.label(:gender, 'Gender'), f.gender_select(:gender) %>
    <%= element_block f.label(:email, 'Email'), f.text_field(:email) %>
    <%= element_block f.label(:desires_esl, 'Does the student wish to participate in CLEP?'), f.bool_yes_no_select(:desires_esl) %>
    <%= element_block f.label(:may_pay_tuiton, 'Willing to pay tuition'), f.yes_no_select(:may_pay_tuition) %>
  </dl>
  <div class="submit"><%= submit_tag("Proceed to Step Two") %></div>
<% end %>

Ответы [ 2 ]

1 голос
/ 09 февраля 2010

Вот так я и позаботился об этом с accepts_nested_attributes_for

Основная модель. (Нерелевантный код заменен на эллипсы)

class ProfileCore < ActiveRecord::Base
  set_table_name "profile_core"
  set_primary_key "STUDENT_ID"
  belongs_to :agents_profile, :primary_key => "AGENT_ID", :foreign_key => "AGENT_ID"
  has_one :profile_program, :primary_key => "STUDENT_ID", :foreign_key => "STUDENT_ID"

  accepts_nested_attributes_for :profile_program
...
end

Вторичная модель

class ProfileProgram < ActiveRecord::Base
  set_table_name "profile_program"
  set_primary_key "STUDENT_ID"
  belongs_to :profile_core, :primary_key => "STUDENT_ID", :foreign_key => "STUDENT_ID"

  validates_presence_of :program
  validates_hsp_program :program
end

Новое действие в контроллере. (Создать было неактуально)

def new
  @pc = ProfileCore.new
  @pp = @pc.build_profile_program
end

View

<% form_for @pc, :url => { :controller => 'core', :action => 'create'}  do |f| %>
  <%= f.error_messages  %>
  <dl>
    <%= element_block  f.label(:contract, 'Contract Year'), f.contract_year_select(:contract) %>
    <% f.fields_for :profile_program do |pp| %>
      <%= element_block pp.label(:program, 'Program'), pp.hsp_program_select(:program) %>
    <% end %>
  <%= element_block f.label(:passport_number, 'Passport Number'), f.text_field(:passport_number) %>
...
<% end %>
0 голосов
/ 09 февраля 2010

Это неверная реализация пользовательской проверки, попробуйте что-то вроде этого: http://marklunds.com/articles/one/312 или http://chrisblunt.com/blog/2009/04/18/rails-writing-dry-custom-validators/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...