public
Created

  • Download Gist
Controller.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
# 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
Models.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
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
PersonController.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
# 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
_fields.html.erb
HTML+ERB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
<%= 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 %>
stack_overflow_12772318_testbed.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
# 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 => 'hsmith@gmail.com',
: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 => 'hsmith@gmail.com',
: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 => 'hsmith@gmail.com',
: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 => 'hsmith@gmail.com'
}
 
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 => 'hsmith@gmail.com',
:address_attributes => {
:line1 => '122 N Lane St',
:line2 => 'Apt 35'
}
}
 
p5 = Person.create(person_with_partial_address_attrs)
print_validation(p5)

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.