嵌套Rails 4表单访问数组

时间:2014-12-16 04:24:06

标签: ruby-on-rails simple-form nested-forms nested-attributes

我有一个嵌套的表单,有3个字段重复7次。我想检查一下,如果第一个字段组为空,那么它将停止该过程并返回一个错误,要求用户填写这些字段。

我已经检查过它会从控制器中的“创建”操作中删除所有空字段组,即" reject_if:=> :all_blank"模型的一部分。但是,它删除了第一个条目,我宁愿进行检查。这段代码不起作用,除了尝试优化check_attendee_form方法之外,我不知道从哪里开始。任何帮助将在那里得到赞赏。

以下是相关型号:

class Registration < ActiveRecord::Base

# Database Relationships
belongs_to :event
belongs_to :user
has_many :attendees

# Form relationships
accepts_nested_attributes_for :attendees,
            :allow_destroy => true,
            :reject_if => :all_blank

class Attendee < ActiveRecord::Base

# Database relationships
belongs_to :event
belongs_to :user

delegate :event, :event_id, to: :registration

# Validations
validates :first_name, :last_name, presence: true

控制器创建和新操作和方法

def new
@registration = @event.registrations.new
7.times { @registration.attendees.build }
end

def create
 @registration = @event.registrations.new(registration_params)
 @registration.user = current_user
 check_attendee_form

respond_to do |format|
  if @registration.save
    format.html { redirect_to event_path(@event), notice: 'You are now registered.' }
    format.json { render :show, status: :created, location: @registration }
  else
    format.html { render :new }
    format.json { render json: @registration.errors, status: :unprocessable_entity }
  end
end
end

def check_registration
@check = Registration.find_by event_id: @event, user_id: current_user
if @check.nil?
 @registration = @event.registrations.new
 @registration.user = current_user
else
 redirect_to event_path(@event),
             notice: "You're already registered!"
end
end

def check_attendee_form

  @attendees_check = @registration.find_by(attendees_attributes: params[:first_name])

  if @attendees_check.first.nil?
  render :new, notice: "You need to put in your name at least!"
  else
  end
end

最后,基本形式信息:

<%= simple_form_for [@event, @registration], :html => { :class => 'form-horizontal' } do |f| %>

<%= render 'shared/errors', object: @registration %>

<%= f.simple_fields_for :attendees, defaults: { input_html: { class: 'form-horizontal' } }  do |a| %>

<div>

<%= a.label :first_name %>:
<%= a.text_field :first_name %>
<%= error_span([:first_name]) %>
<%= a.label :last_name %>:
<%= a.text_field :last_name %>
<%= error_span([:last_name]) %>
<%= a.label :fundraising_goal %>:
<%= a.number_field :fundraising_goal, placeholder: 'No Commas' %>
<%= error_span([:fundraising_goal]) %>

以下是提交的参数:

{"utf8"=>"✓",
"authenticity_token"=>"dNR5QCBFplsAG0wzy87+hzaKuG6h2Mlb6xpmKEM0Kko=",
"registration"=>{"attendees_attributes"=>{"0"=>{"first_name"=>"",
"last_name"=>"",
"fundraising_goal"=>""},
"1"=>{"first_name"=>"",
"last_name"=>"",
"fundraising_goal"=>""},
"2"=>{"first_name"=>"",
"last_name"=>"",
"fundraising_goal"=>""},
"3"=>{"first_name"=>"",
"last_name"=>"",
"fundraising_goal"=>""},
"4"=>{"first_name"=>"",
"last_name"=>"",
"fundraising_goal"=>""},
"5"=>{"first_name"=>"",
"last_name"=>"",
"fundraising_goal"=>""},
"6"=>{"first_name"=>"",
"last_name"=>"",
"fundraising_goal"=>""}}},
"commit"=>"Create Registration",
"event_id"=>"5"}

如何在此表单提交中使用ID [0]的attendees_attributes访问第一个数组对象?

3 个答案:

答案 0 :(得分:0)

您的表单属性是嵌套哈希,您可以使用id,0等访问与会者

即params [registration] [与会者] [0]

答案 1 :(得分:0)

如果您想确保为注册输入至少一位参加者,我相信您可以放弃check_attendee_form方法并将以下验证添加到registration.rb:

validate :check_minimum_attendees

def check_minimum_attendees
    errors.add(:attendees, 'must be entered') if attendees.size == 0
end

答案 2 :(得分:0)

如果我是正确的,问题在于:reject_if条件。 您可以使用Proc(或lambda)来拒绝&#39;任何不合适的嵌套属性。

:reject_if => lambda { |e| e[:last_name].blank? && (e[:_destroy].blank? || e[:_destroy] == 'false') }

使用验证为@keyzee建议:

validate :check_attendees

def check_attendees
  errors.add(:attendees, 'must be entered') unless attendees.count
  attendees.each do |a|
    errors.add(:attendees, 'error message here') if condition_here
  end
end

或者在lib文件夹中创建自定义验证器(lib / check_attendees_validator.rb):

class CheckAttendeesValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    record.errors[attribute] << 'error_message' if condition_here
  end
end

然后在模型中使用它:

validates :attendees, check_attendees: true