Created
October 8, 2012 17:19
-
-
Save dresselm/3853702 to your computer and use it in GitHub Desktop.
Notes for http://stackoverflow.com/questions/10050797/rails-error-cant-mass-assign-protected-attributes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%= form_for(@person) do |f| %> | |
<fieldset> | |
<div class="left"> | |
<%= f.label :first_name %><br/> | |
<%= f.text_field :first_name %> | |
</div> | |
<div> | |
<%= f.label :last_name %><br/> | |
<%= f.text_field :last_name %> | |
</div> | |
<div> | |
<%= f.label :email %><br/> | |
<%= f.text_field :email %> | |
</div> | |
<div> | |
<%= f.label :organisation_id %><br/> | |
<% # You need to customize this so that it displays the names, but sends option values equal to the ids %> | |
<%= f.select(:organisation_id, Organisation.all.map(&:id), {:include_blank => "--- None ---"}, :id => 'organization_select') %> | |
</div> | |
</fieldset> | |
<%= f.fields_for :address do |address| %> | |
<%= render 'shared/address', :f => address %> | |
<% end %> | |
<%= f.submit %> | |
<% end %> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# I am assuming you have a User model with a | |
# has_many :people association? | |
def create | |
# Your params for Person creation are found on the params[:person] | |
# I do not understand what you are doing here. Basically, what's going | |
# on - if an organisation is selected, you are building the person off of | |
# the organisation relationship. Your form, however, revolves around people, not | |
# organisations. | |
# So, get rid of the complexity below | |
#if params[:organisation_id] | |
# @person = current_user.organisations.build_person(params[:person]) | |
#else | |
# @person = current_user.people.build(params[:person]) | |
#end | |
# Uncomment this to test the creation against a standalone Person object | |
# test_person = Person.new(params[:person]) | |
# puts test_person.valid? | |
# puts test_person.organisation | |
# puts test_person.address | |
puts 'testing @person:' | |
@person = current_user.people.build(params[:person]) | |
puts "valid? #{@person.valid?}" | |
puts "errors: #{@person.errors.inspect}" | |
if @person.save | |
flash[:success] = "Person created." | |
redirect_to people_path | |
else | |
render :action => "new" | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Organisation < ActiveRecord::Base | |
has_many :people | |
has_one :address, :as => :addressable, | |
:dependent => :destroy | |
accepts_nested_attributes_for :address, :allow_destroy => true | |
end | |
class Person < ActiveRecord::Base | |
belongs_to :organisation | |
has_one :address, :as => :addressable, | |
:dependent => :destroy | |
# The form sends the address attributes as blank values when they are not entered | |
# Without the reject, the address model gets populated with blank values and then blows up during validation | |
accepts_nested_attributes_for :address, :allow_destroy => true, :reject_if => lambda { |a| a[:line1].blank? && a[:line2].blank? && a[:city].blank? && a[:zip].blank? } | |
# Organization must be selected, unless Address details are added | |
validates_presence_of :organisation, :unless => "address.present?" | |
# The Address association must be validated, unless organization is selected | |
validates_associated :address, :unless => "organisation.present?" | |
end | |
class Address < ActiveRecord::Base | |
belongs_to :addressable, :polymorphic => true | |
# These validations are necessary for the validated_associated above | |
# If there are no validations, then missing organizations and address inputs will not trigger the proper validations | |
validates_presence_of :line1, :line2, :city, :zip | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# I excluded all User relationships | |
class PeopleController < ApplicationController | |
before_filter :print_params | |
def index | |
@people = Person.all | |
end | |
def new | |
# Add default values if you want them displayed | |
@person = Person.new | |
# Necessary to build out the blank address fields | |
@person.build_address | |
@title = "New person" | |
end | |
def edit | |
@person = Person.find(params[:id]) | |
@title = @person.name | |
end | |
def create | |
# This is the beauty of accepts_nested_attributes | |
@person = Person.new(params[:person]) | |
if @person.save | |
flash[:success] = "Person created." | |
redirect_to people_path | |
else | |
Rails.logger.info "==== errors: #{@person.errors.inspect}" | |
@person.build_address if @person.address.nil? | |
render :new | |
end | |
end | |
# Just for debugging purposes - remove once you've figured everything out | |
def print_params | |
Rails.logger.info "==== params: #{params.inspect}" | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Once your models are updated, open the console via `rails c` and enter the following tests | |
# Note: I am using organization vs organisation - you might want to do a search/replace | |
# I made an assumption that Organization has at least a name attribute | |
organization = Organization.create(:name => 'Org1') | |
# Simple method that prints validity and errors | |
def print_validation(obj) | |
puts "valid?: #{obj.valid?}" | |
puts obj.errors.inspect | |
end | |
# nested attrs containing a full person, org reference and full address | |
full_person_attrs = { | |
:first_name => 'Harry', | |
:last_name => 'Smith', | |
:email => '[email protected]', | |
:organization_id => organization.id, | |
:address_attributes => { | |
:line1 => '122 N Lane St', | |
:line2 => 'Apt 35', | |
:city => 'Chicago', | |
:zip => '60625' | |
} | |
} | |
p = Person.create(full_person_attrs) | |
print_validation(p) | |
# nested attrs containing a full person and full address | |
person_address_attrs = { | |
:first_name => 'Harry', | |
:last_name => 'Smith', | |
:email => '[email protected]', | |
:address_attributes => { | |
:line1 => '122 N Lane St', | |
:line2 => 'Apt 35', | |
:city => 'Chicago', | |
:zip => '60625' | |
} | |
} | |
p2 = Person.create(person_address_attrs) | |
print_validation(p2) | |
# nested attrs containing a full person and org reference | |
person_organization_attrs = { | |
:first_name => 'Harry', | |
:last_name => 'Smith', | |
:email => '[email protected]', | |
:organization_id => organization.id | |
} | |
p3 = Person.create(person_organization_attrs) | |
print_validation(p3) | |
# nested attrs containing a full person, but no org or address | |
person_without_organization_or_address_attrs = { | |
:first_name => 'Harry', | |
:last_name => 'Smith', | |
:email => '[email protected]' | |
} | |
p4 = Person.create(person_without_organization_or_address_attrs) | |
print_validation(p4) | |
# nested attrs containing a full person and partial address | |
# I added presence_of validations in Address for all the attributes | |
person_with_partial_address_attrs = { | |
:first_name => 'Harry', | |
:last_name => 'Smith', | |
:email => '[email protected]', | |
:address_attributes => { | |
:line1 => '122 N Lane St', | |
:line2 => 'Apt 35' | |
} | |
} | |
p5 = Person.create(person_with_partial_address_attrs) | |
print_validation(p5) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment