View
<%= form_for #product, :url => admin_products_path do |f| %>
<div>
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div>
<%= f.label :description %>
<%= f.text_area :description, :rows => 7 %>
</div>
<%= f.fields_for :address do |a| %>
<p><%= a.label "Address One" %><br />
<%= a.text_field :address_one %></p>
<p><%= a.label "Address Two" %><br />
<%= a.text_field :address_two %></p>
<p><%= a.label :city %><br />
<%= a.text_field :city %></p>
<p><%= a.label :postcode %><br />
<%= a.text_field :postcode %></p>
<p><%= a.label :country %><br />
<%= a.select :country_id, Country.active.collect {|p| [ p.printable_name, p.id ] } %></p>
<% end %>
<% end %>
Controller
def create
#product = Product.new(params[:product])
if #product.save
flash[:notice] = 'Product was successfully created.'
render 'show'
else
render 'new'
end
end
model
class Product < ActiveRecord::Base
has_one :address, :as => :addressable
end
but when save data it show issue:
Address(#93165130) expected,got ActiveSupport::HashWithIndifferentAccess(#79365750)
Please help me solved this problem
Try if adding accepts_nested_attributes_for :address solves this.
accepts_nested_attributes_for :address
if not work then try also adding along with accepts_nested_attributes_for :address
attr_accessor :address
Related
I have a BikeShops model:
class BikeShop < ActiveRecord::Base
has_one :user, :as => :profile, :dependent => :destroy
accepts_nested_attributes_for :user
end
And a Users model:
class User < ActiveRecord::Base
belongs_to :profile, :polymorphic => true
end
I am trying to create a nested form in the bike_shops/new view. Here is the code I have: in there:
<%= form_for(#bike_shop) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name, 'Shop Name' %>
<%= f.text_field :name %>
<%= f.label :street_address, 'Street Address' %>
<%= f.text_field :street_address %>
<%= f.label :city, 'City' %>
<%= f.text_field :city %>
<%= f.label :state, 'State' %>
<%= f.text_field :state %>
<%= f.label :zip_code, 'Zip Code' %>
<%= f.text_field :zip_code %>
<%= f.label :phone_number, 'Phone Number' %>
<%= f.text_field :phone_number %>
<%= f.label :website, 'Website' %>
<%= f.text_field :website %>
<% f.fields_for(:user) do |builder| %>
<%= builder.label :first_name, 'First Name:' %>
<%= builder.text_field :first_name %>
<%= builder.label :last_name, 'Last Name:' %>
<%= builder.text_field :last_name %>
<%= builder.label :email, 'Email:' %>
<%= builder.text_field :email %>
<%= builder.label :password, 'Password:' %>
<%= builder.password_field :password %>
<%= builder.label :password_confirmation, 'Password Confirmation:' %>
<%= builder.password_field :password_confirmation %>
<% end %>
<%= f.submit "Signup My Bike Shop", class: "btn btn-large btn-primary" %>
<% end %>
The fields for #bike_shop appear but the nested fields for the has_one #user do not appear. Here is the code in the BikeShops controller:
class BikeShopsController < ApplicationController
def new
#bike_shop = BikeShop.new
#user = #bike_shop.build_user
end
I was following this railscast but can't get pass getting the fields for the nested form to show. Any help is appreciated.
You need to use the <%= erb tag in order to render it instead of just <%
<%= f.fields_for(:user) do |builder| %>
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
I want to insert tags in new Place. giving that tags is in different model.
####### models ##########
class Tag < ActiveRecord::Base
belongs_to :place
attr_accessible :tag
end
class Place < ActiveRecord::Base
has_many :tags
end
how can I handle this in the new Place create form? and the create action in the places_controller? so that I can insert new place and mant tags then assign the product id to each tag.
####### place controller ##########
def create
#place = Place.new(params[:place])
#tag = Tag.new(params[:?????]) #this should be more than once
respond_to do |format|
if #place.save
format.html { redirect_to #place, notice: 'Place was successfully created.' }
format.json { render json: #place, status: :created, location: #place }
else
format.html { render action: "new" }
format.json { render json: #place.errors, status: :unprocessable_entity }
end
end
end
####### place new form ##########
<%= form_for #place do |f| %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :description %><br />
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :rank %><br />
<%= f.text_field :rank %>
</div>
<div class="field">
<%= f.label :lat %><br />
<%= f.text_field :lat %>
</div><div class="field">
<%= f.label :lng %><br />
<%= f.text_field :lng %>
</div>
<div class="field">
<%= f.label :address %><br />
<%= f.text_area :address %>
</div>
<div class="field">
<%= f.label :website %><br />
<%= f.text_field :website %>
</div>
<div class="field">
<%= f.label :phone %><br />
<%= f.text_field :phone %>
</div>
<div class="field">
<%= label_tag "tags" %>
<%= f.text_field :tag %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
If you want to do it on your own, you should look into accepts_nested_attributes_for, where there's a great 2 part tutorial by Ryan Bates at railscasts.com
If you don't want to do it on your own, there are several tag gems available, for instance:
ActsAsTaggableOn.
Add this in your form:
<%= f.fields_for :tags do |t| %>
<%= t.label :name %>
<%= t.text_field :name %>
<% end %>
And in your Place model:
accepts_nested_attributes_for :tags
And in your controller, you wouldn't even have to worry about creating tags.
You should still try to read about fields_for and accepts_nested_attributes_for, they're often useful, since your problem is very common.
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.
I'm on Rails 3. I have a model called Client that has name, phone and email. My model file looks like this:
class Client < ActiveRecord::Base
belongs_to :salon
belongs_to :address
validates_presence_of :name
validates_presence_of :phone
validates_presence_of :email
accepts_nested_attributes_for :address
attr_accessible :address_attributes
end
As you can see, name, phone and email are all required. When I go to the form where I'm supposed to be able to create a new Client and submit it, all three validations fail, no matter what I put in the fields. Here is my form file:
<%= form_for(#client) do |f| %>
<% if #client.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#client.errors.count, "error") %> prohibited this client from being saved:</h2>
<ul>
<% #client.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.hidden_field :salon_id, :value => Salon.logged_in_salon.id %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :phone %><br />
<%= f.text_field :phone %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<%= f.fields_for :address do |address_form| %>
<div class="field">
<%= address_form.label :line1 %><br />
<%= address_form.text_field :line1 %>
</div>
<div class="field">
<%= address_form.label :line2 %><br />
<%= address_form.text_field :line2 %>
</div>
<div class="field">
<%= address_form.label :city %><br />
<%= address_form.text_field :city %>
</div>
<div class="field">
<%= address_form.label :state_id %><br />
<%= select("client[address]", "state_id", State.all.collect {|s| [ s.name, s.id ] }) %>
</div>
<div class="field">
<%= address_form.label :zip %><br />
<%= address_form.text_field :zip %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Here's my create action:
def create
#client = Client.new(params[:client])
respond_to do |format|
if #client.save
format.html { redirect_to(#client, :notice => 'Client was successfully created.') }
format.xml { render :xml => #client, :status => :created, :location => #client }
else
format.html { render :action => "new" }
format.xml { render :xml => #client.errors, :status => :unprocessable_entity }
end
end
end
Any idea why this is happening?
It's because you set :address_attributes as the only accessible attribute. Change
attr_accessible :address_attributes
to
attr_accessible :address_attributes, :name, :phone, :email
or don't use mass assignment.