Double nested model forms - ruby-on-rails

I am still having problems with nested forms. Here is my form code:
<%= form_for #account do |f| %>
<%= f.label :account_type %><br />
<%= f.text_field :account_type %><br />
<%= f.fields_for :organizations do |builder| %>
<%= builder.label :name %><br />
<%= builder.text_field :name %><br />
<%= builder.label :website %><br />
<%= builder.text_field :website %><br />
<%= f.fields_for :locations do |builder| %>
<%= builder.label :phone %><br />
<%= builder.text_field :phone %><br />
<%= builder.label :toll_free_phone %><br />
<%= builder.text_field :toll_free_phone %><br />
<%= builder.label :fax %><br />
<%= builder.text_field :fax %><br />
<% end %>
<% end %>
<%= f.submit "Add account" %>
<% end %>
The Account model:
class Account < ActiveRecord::Base
has_many :organizations
accepts_nested_attributes_for :organizations
end
The Organization model:
class Organization < ActiveRecord::Base
belongs_to :account
has_many :locations
accepts_nested_attributes_for :locations
end
And the Location model:
class Location < ActiveRecord::Base
belongs_to :organization
end
And lastly, the Accounts Controller:
class AccountsController < ApplicationController
def new
#account = Account.new
organization = #account.organizations.build
organization.locations.build
#header = "Create account"
end
def create
#account = Account.new(params[:account])
if #account.save
#handle success
else
render 'new'
end
end
end
Here is the error I am getting:
ActiveRecord::UnknownAttributeError in AccountsController#create
unknown attribute: locations
Rails.root: C:/Documents and Settings/Corey Quillen/My
Documents/rails_projects/shop_manager
Application Trace | Framework Trace | Full Trace
app/controllers/accounts_controller.rb:12:in `new'
app/controllers/accounts_controller.rb:12:in `create'
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"xuZLSP+PSjdra3v51nIkJYZeXRM0X88iF135hPlp4sc=",
"account"=>{"account_type"=>"Company",
"organizations_attributes"=>{"0"=>{"name"=>"Atlas",
"website"=>"www.atlas.com"}},
"locations"=>{"phone"=>"555-555-5555",
"toll_free_phone"=>"800-555-5555",
"fax"=>"512-555-5555"}},
"commit"=>"Add account"}
Any help with this will be greatly appreciated. I have been looking at this now for a couple of hours.

You should use new builder in nested form for nested nested form :)) :
<%= form_for #account do |f| %>
<%= f.label :account_type %><br />
<%= f.text_field :account_type %><br />
<%= f.fields_for :organizations do |builder| %>
<%= builder.label :name %><br />
<%= builder.text_field :name %><br />
<%= builder.label :website %><br />
<%= builder.text_field :website %><br />
<%= builder.fields_for :locations do |lb| %>
<%= lb.label :phone %><br />
<%= lb.text_field :phone %><br />
<%= lb.label :toll_free_phone %><br />
<%= lb.text_field :toll_free_phone %><br />
<%= lb.label :fax %><br />
<%= lb.text_field :fax %><br />
<% end %>
<% end %>
<%= f.submit "Add account" %>
<% end %>

An even DRYer solution:
1) in your Gemfile, list nested_form as a dependency.
2) in your models do this:
class Account < ActiveRecord::Base
accepts_nested_attributes_for :organizations
end
class Organization < ActiveRecord::Base
accepts_nested_attributes_for :locations
end
3) create regular forms for Organization under ./app/view/organizations/
and for Location under./app/view/locations/`
4) in your Account form, do this: (it gets pretty short this way!)
<%= nested_form_for #account do |f| %>
<%= f.label :account_type %><br />
<%= f.text_field :account_type %><br />
<%= f.fields_for :organizations %>
<%= f.submit "Add account" %>
<% end %>
5) in your Organization form, do this: (also pretty short)
<%= nested_form_for #organization do |f| %>
<%= f.label :name %><br />
<%= f.text_field :name %><br />
<%= f.label :website %><br />
<%= f.text_field :website %><br />
<%= f.fields_for :locations %>
<%= f.submit "Add Organization" %>
<% end %>
Check these RailsCasts:
http://railscasts.com/episodes/196-nested-model-form-part-1
http://railscasts.com/episodes/197-nested-model-form-part-2

Related

Rails nested form creation

I have an app in which i want create nested form
my models:
class Abonent < ActiveRecord::Base
belongs_to :town
has_many :numbers, :dependent => :destroy
accepts_nested_attributes_for :numbers
end
class Number < ActiveRecord::Base
belongs_to :abonent
end
Abonents controller:
class AbonentsController < ApplicationController
def new
#abonent = Abonent.new
end
def create
#abonent = Abonent.new abonents_params
if #abonent.save
redirect_to :towns
else
render action: "new"
end
end
private
def abonents_params
params.require(:abonents).permit( :fullname, :work_position, :department, :email, :town_id, numbers_attributes: [ :phone ] )
end
end
And abonents view
<hr><br>
<%= form_for :abonents, url: abonents_path do |f| %>
<%= f.label :fullname %>:
<%= f.text_field :fullname %><br /> <br />
<%= f.label :work_position %>:
<%= f.text_field :work_position %><br /><br />
<%= f.label :department %>:
<%= f.text_field :department %><br /><br />
<%= f.label :email %>:
<%= f.text_field :email %><br /><br />
<%= f.label :town_id %>:
<%= f.select :town_id, Town.all.collect { |p| [ p.ru_name, p.id ] } %><br /><br />
<%= f.fields_for :numbers do |phones|%>
<%= phones.label :phone %>:
<%= phones.text_field :phone %><br /><br />
<% end %>
<%= f.submit %>
<% end %>
The problem is when i submit form, it creates abonent, but doesn't create number for this abonent.
I saw many different manuals and couldn't find the error in my code.
Please help.
Thank you.
UPD I added a repo on github for this problem.
You need to build the associated records
def new
#abonent = Abonent.new
#abonent.numbers.build
end

Can't verify CSRF token authenticity

Hi sir in rails 4 while using form_for also getting above error in google i read about this and follow that but even also i am getting same error
if i disable in application controller and added protect_from_forgery with: :null_session it is working but when i submit the form_for form i am getting params missing or params should not empty .
i refered this link i refered linkeven also not working
Error in the log file
Processing by UsersController#create as HTML
Can't verify CSRF token authenticity
code view
<%= form_for #user do |f| %>
<p>
<%= f.label :first_name %><br />
<%= f.text_field :first_name %>
</p>
<p>
<%= f.label :last_name %><br />
<%= f.text_field :last_name %>
</p>
<p>
<%= f.label :gender %><br />
<%= f.text_field :gender %>
</p>
= f.fields_for :address do |p| %>
<p>
<%= p.label :city %><br />
<%= p.text_field :city %>
</p>
<p>
<%= p.label :state %><br />
<%= p.text_field :state %>
</p>
<p>
<%= p.label :country %><br />
<%= p.text_field :country %>
</p>
<p>
<%= p.label :postal_code %><br />
<%= p.text_field :postal_code %>
</p>
<% end %>
<p><%= f.submit %></p>
<% end %>
if set protect_from_forgery with: :null_session and if submit the form
than i will getting one more error
param is missing or the value is empty:
userActionController::ParameterMissing (param is missing or the value is empty: user):

How to display data from two tables into one form

I use Ruby v 3. I want to display data from 2 tables into one form.
My models:
class Address < ActiveRecord::Base
attr_accessible :city, :number, :street
validates :city, :presence => true
validates :number, :presence => true
validates :street, :presence => true
has_many :users
end
class User < ActiveRecord::Base
belongs_to :address
attr_accessible :name, :phone, :surname, :address_attributes
accepts_nested_attributes_for :address
end
My form looks alike:
<%= form_for(#user) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :surname %><br />
<%= f.text_field :surname %>
</div>
<div class="field">
<%= f.label :phone %><br />
<%= f.text_field :phone %>
</div>
<%= f.fields_for :address_attributes do |p| %>
<div class="field">
<%= p.label :city %><br />
<%= p.text_field :city %>
</div>
<div class="field">
<%= p.label :street %><br />
<%= p.text_field :street %>
</div>
<div class="field">
<%= p.label :number %><br />
<%= p.text_field :number %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
As you can see I use fields_for method. And my controller is here:
def edit
#user = User.find(params[:id])
#user.address_attributes = #user.address
end
It does not working and I totally don't know why. When I click edit on address list i've got an error:
undefined method `with_indifferent_access'
Anyone can help me figure it out?
Check out Episodes 196 and 197 on RailsCasts:
http://railscasts.com/episodes/196-nested-model-form-part-1
http://railscasts.com/episodes/197-nested-model-form-part-2
There is a revised episode for 196, for which you will need to subscribe to RailsCasts.
I would highly recommend subscribing to learning sites like RailsCasts and CodeSchool, to lear RoR faster and in the right way.
Try to do:
def edit
#user = User.find(parmas[:id])
end
and on your view:
<%= f.fields_for :address do |p| %>
and see if it works, you don't have to add the attributes

Trouble about nested attributes form

This is my first question. I hope you can help me. I have two models.
class Cliente < ActiveRecord::Base
attr_accessible :cedula, :direccion, :nombres, :telefono
validates :cedula, :direccion, :nombres, :telefono, :presence => true
validates :cedula, :uniqueness => { :message => "Cedula ya en uso" }
has_many :facturas
class Factura < ActiveRecord::Base
attr_accessible :cliente_attributes, :iva, :numero, :subtotal, :total, :created_at
belongs_to :cliente
accepts_nested_attributes_for :cliente
I want in the facturas#new view can create or edit Cliente. If exists update or if not exists create. I am using nested attributes. If exists I uses javascript to fill text fields. If not exists I fill text field and save when Factura save. This is facturas#new view.
<h1>Nueva Factura</h1>
<%= form_for #factura do |f| %>
<% if #factura.errors.any? %>
<h2>Errores:</h2>
<ul>
<% #factura.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
<% end %>
<p>
<div class = "contenedor_factura">
<%= f.label :numero %><br />
<%= f.number_field :numero %><br />
<%= f.label :fecha %><br />
<%= f.date_select :created_at %><br />
</div>
<div class = "contenedor_cliente">
<%= f.fields_for #cliente do |builder| %>
<%= builder.label :cedula, "Cédula" %>
<%= builder.text_field :cedula %>
<%= builder.label :nombres, "Nombres" %>
<%= builder.text_field :nombres %>
<%= builder.label :direccion, "Dirección" %><br />
<%= builder.text_field :direccion %>
<%= builder.label :telefono, "Teléfono" %><br />
<%= builder.text_field :telefono %>
<%= builder.hidden_field :id%>
<% end %>
</div>
<div class = "contenedor_productos">
</div>
<%= f.label :subtotal %><br />
<%= f.text_field :subtotal %>
<br />
<%= f.label :iva %><br />
<%= f.text_field :iva %>
</p>
<p>
<%= f.submit "Agregar Nueva Factura" %>
</p>
<% end %>
When the Cliente is new i have no problem, it saves, but if Cliente exists i have this message
ActiveRecord::RecordNotFound in FacturasController#create
Couldn't find Cliente with ID=6 for Factura with ID=
What is my problem?
EDIT:
This is my FacturasController
def new
#factura = Factura.new
#cliente = #factura.build_cliente
end
def create
#factura = Factura.new(params[:factura])
if #factura.save
redirect_to facturas_path, :notice => "Factura Guardada"
else
render "new"
end
end
I'm not sure if nested_attrubes handles already created models. So we can just not depend on it.
This should work
def create
cliente_attrs = params[:factura].delete :cliente
#cliente = cliente_attrs[:id].present? ? Cliente.find(cliente_attrs[:id]) : User.create(user_attrs)
#factura = cliente.facturas.build(params[:factura])
if #factura.save
redirect_to facturas_path, :notice => "Factura Guardada"
else
render "new"
end
end
You can now delete the line accepts_nested_attributes_for :cliente

Rails deep nested/non nested form

I'm trying to create a form handling 4 models at once with 2 nested pairs... Got an error: You have a nil object when you didn't expect it! You might have expected an instance of Array. The error occurred while evaluating nil.
Is there someone to guide me with this one? For your info I'm using rails 3.0. and I need to handle the 4 models in the same view... Thanks a lot for your help because this one is driving me nuts for days :)
Here is the controller's code:
def new
#pinvoice = Pinvoice.new
#journal = Journal.new
#compte = Compte.find(:all)
if Journal.last.nil?
then
#internal = 'Pinv1'
else
#internal = 'Pinv' + (Journal.last.id + 1).to_s
end
1.times {#pinvoice.pinvlines.build}
4.times {#journal.lignes.build}
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #pinvoice }
end
end
The models code:
class Pinvoice < ActiveRecord::Base
has_many :pinvlines, :dependent => :destroy
accepts_nested_attributes_for :pinvlines
end
class Pinvline < ActiveRecord::Base
belongs_to :pinvoice
belongs_to :compte
belongs_to :pinvoice
end
class Ligne < ActiveRecord::Base
belongs_to :journal
belongs_to :compte
attr_accessor :should_destroy
def should_destroy?
should_destroy.to_i == 1
end
end
class Journal < ActiveRecord::Base
has_many :lignes, :dependent => :destroy
accepts_nested_attributes_for :lignes, :reject_if => lambda { |a| a[:montant].to_s == "0"}
attr_accessor :taux
attr_accessor :compte_tva
validates_presence_of :date
validates_presence_of :texte
validates_presence_of :montant_HTVA
validates_presence_of :banque
validates_presence_of :compte
before_update :delete_lignes
def delete_lignes
#lignes.each do |l|
if l.new_record?
l.save
else
l.destroy
end
end
end
end
and the big one the form:
<%= javascript_include_tag 'javascript_pinvlines_fields_new' %>
<%= form_for #pinvoice do |f| %>
<% if #pinvoice.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#pinvoice.errors.count, "error") %> prohibited this pinvoice from being saved:</h2>
<ul>
<% #pinvoice.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :internal %>
<%= f.text_field :internal, :value => #internal %><br />
<%= f.label :contact %>
<%= f.text_field :contact, :id => 'test' %>
<%= f.label :date_facture %>
<%= f.date_select :date_facture %>
<%= f.label :montant_total %>
<%= f.text_field :montant_total %>
</p>
<h2>Details</h2>
<%= f.fields_for :pinvlines do |builder| %>
<%= render "pinvline_fields", :f => builder %>
<%end%>
<p><%= link_to_add_fields "Ajouter une ligne", f, :pinvlines%></p>
<h2>Jounal</h2>
<%= fields_for #journal do |j| %>
<%= j.label :date %><br />
<%= j.text_field :date, :size => 10 %> <i> au format YYYY-MM-DD </i><br />
<%= j.label :texte %><br />
<%= j.text_field :texte%><br />
<%= j.label :banque %><br />
<%= j.text_field :banque %><br />
<%= j.label :montant_hors_tva %><br />
<%= j.text_field :montant_HTVA%><br />
<%= j.label :tva_id %><br />
<%= j.text_field :tva_id %><br />
<%= j.label :taux %><br />
<%= j.text_field :taux %><br />
<%= j.label :compte_tva %><br />
<%= j.text_field :compte_tva %><br />
<%= j.label :montant_TVA %><br />
<%= j.text_field :montant_TVA%><br />
<%= j.label :montant %><br />
<%= j.text_field :montant %><br />
<%= j.label :compte %><br />
<%= j.text_field :compte %><br />
<%= j.label :internal %><br />
<%= j.text_field :internal, :value => #internal%><br />
<%= j.label :source %><br />
<%= j.text_field :source%>
<br />
<h2>Lignes</h2>
<div class='container'>
<div class="duplicate">
<%= j.fields_for :lignes do |j| %>
<%= j.label :date %>
<%= j.text_field :date, :size=> 8 %>
<%= j.label :compte_id %>
<%= j.text_field :compte_id, :size=> 8 %>
<%= j.label :montant %>
<%= j.text_field :montant, :size=> 8 %>
<%= j.label :debit %>
<%= j.text_field :debit, :size=> 8 %>
<%= j.label :credit %>
<%= j.text_field :credit, :size=> 8 %>
<br />
<% end %>
</div>
</div>
<%end%>
<p><%= f.submit %></p>
<% end %>
At the end I've found a way to handle this with a call back at the model level.

Resources