Nathan
Nathan

Reputation: 1984

Validating field's presence fails even though the field is not blank

I'm trying to fill out an array with values from checkboxes. It works just fine when creating a record, but fails validation when editing. The params look right, which is what really confuses me:

"record"=>{... "type_array"=>["accounting"], ...}

It looks the same as the params from creating a new record. The fields in New.html.erb and Edit.html.erb also use the same markup.

Edit.html.erb

<div class="field">
  <%= f.label :type_array, "What type of record?" %><br />
  <% ["accounting", "agriculture", "automotive"].each do |type| %>
    <%= check_box_tag 'record[type_array][]', type, (true if @record.type_list.include? type),
                      :id => type %>
    <%= label_tag type, type.titleize, :class => type %><br />
  <% end %>
</div>

Parts of Record.rb

validates :type_array, :presence => true
attr_accessor :type_array
attr_accessible :type_array
before_validation :set_type_list

private

def set_type_list
  self.type_list = type_array.join ',' if type_array.present?
end

Am I missing something? When I remove the type_array validation and fill out the form, it acts like type_array is empty. Somewhere along the line, it must be lost or something.

I appreciate any help.

(Sidenote: if anyone has a better way to do the list of checkboxes, let me know)

Upvotes: 1

Views: 1140

Answers (1)

Luke
Luke

Reputation: 4925

Delete the line attr_accessor :type_array.

This creates accessor methods to a new instance variable, not to the model attribute type_array, which means that @record.type_array now refers to that instance variable instead of the attribute.

You almost never use attr_accessor or it's siblings attr_reader and attr_writer in Rails because you want to deal with model attributes, not instance variables.

Edit: You're using type_array as a virtual attribute.

class Record < ActiveRecord::Base
  validates :type_array, :presence => true
  attr_accessible :type_array

  def type_array=(val)
    self.type_list = val.join ','
  end

  def type_array
    self.type_list.split ','
  end

  def type_array_before_type_cast
    type_array
  end
end

For the reason why you need that last function definition, see this question.

Upvotes: 5

Related Questions