Validation error reset my values why - ruby-on-rails-3

I have a modal "A" and it has a line_item model "B" with has_many association. That means B is associated with A. I have validation for B in A's model that
validates_presence_f :B
validates_associated :B
now in my form i have used "fields_for" to save values of B, if i submit a blank form than
validation fails and displays an error message for presence of line item B, but the fields of B's disabled, i have to reshow their fields. Can any one predict why this is happening.
here is my model :
Model A:
class Purchase < ActiveRecord::Base
has_many :purchase_line_items
accepts_nested_attributes_for :purchase_line_items, :reject_if => lambda {|a| a[:account_id].blank? }, :allow_destroy =>true
validates_presence_of :purchase_line_items
validates_associated :purchase_line_items
end
and Model B:
class PurchaseLineItem < ActiveRecord::Base
belongs_to :purchase
end
in my controller:
class PurchasesController < ApplicationController
def new
#purchase = Purchase.new
#purchase.purchase_line_items.build
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #purchase }
end
end
end
and in last my views :
<%= form_for #purchase, :html => {:multipart => true} do |f| %>
<%= render 'shared/form_error', :object => #purchase %>
<% #purchase.purchase_line_items.each_with_index do |purchase_line_item, index| %>
<%= render "purchase_line_items", :purchase_line_item => purchase_line_item, :index => index %>
<% end %>
<%= f.submit %>
<% end %>
And in line item partial i have:
<tr id="row<%= index %>" valign="top" >
<%= hidden_field_tag "purchase[purchase_line_items_attributes][#{index}][id]",purchase_line_item.id%>
<td valign="top">
<%= select_tag "purchase[purchase_line_items_attributes][#{index}][account_id]", options_from_collection_for_select(#to_accounts, :id, :name,:selected => purchase_line_item.account_id ), :include_blank => true, :class=>"full" %>
</td>
<td><%= text_field_tag "purchase[purchase_line_items_attributes][#{index}][amount]", purchase_line_item.amount, :class => 'full', :id => 'total', :readonly => 'readonly', :size => 5%></td>
<td><%= link_to image_tag("/images/black_icon/ic_cancel.png"),{:action => :remove_line_item, :index => index}, :remote => true unless index == 0 %></td>
</tr>

If I have correctly understood you, you have problems with nested form.
For what reason do you have readonly property for :amount field?
I do not know, why have you used approach without fields_for, but In this case you can not validate nested fields without it. So your code has to be something like this:
<%= form_for #purchase, :html => {:multipart => true} do |f| %>
<%= render 'shared/form_error', :object => #purchase %>
<%= f.fields_for :purchase_line_items do |pl| %>
<tr id="row<%= pl.object.id %>" valign="top" >
<%= pl.hidden_field :id %>
<td valign="top">
<%= pl.select :account_id, options_from_collection_for_select(#to_accounts, :id, :name, :selected => pl.object.account_id), :include_blank => true, :class=>"full" %>
</td>
<td><%= pl.text_field :amount, :class => 'full', :id => 'total', :readonly => 'readonly', :size => 5 %></td>
<td><%= link_to image_tag("/images/black_icon/ic_cancel.png"), {:action => :remove_line_item, :index => pl.object.id }, :remote => true unless index == 0 %></td>
</tr>
<% end %>
<%= f.submit %>
<% end %>
Add validation to your PurchaseLineItem model to prevent saving record without :account_id.
class PurchaseLineItem < ActiveRecord::Base
belongs_to :purchase
validates_presence_of :account_id
end
Actually if you will validate :account_id you do not have to use :reject_if.
class Purchase < ActiveRecord::Base
has_many :purchase_line_items
accepts_nested_attributes_for :purchase_line_items, :allow_destroy =>true
validates_presence_of :purchase_line_items
validates_associated :purchase_line_items
end
To be more clear, please, edit your question and add code of createaction.

Related

Multiple File Uploads With Paperclip

I watched http://www.emersonlackey.com/article/rails-paperclip-multiple-file-uploads and tried to apply it to my project. This is what I have:
property.rb
class Property < ActiveRecord::Base
attr_accessible :avatar, :agent_id, :address, :neighborhood, :price, :photos
belongs_to :agent
has_attached_file :avatar, :styles => { :large => "1500x1500>", :thumb => "100x100>" }
has_many :photos
accepts_nested_attributes_for :photos, :allow_destroy => true
end
photo.rb
class Photo < ActiveRecord::Base
attr_accessible :avatar, :property_id
belongs_to :property
has_attached_file :avatar, :styles => { :large => "1500x1500>"}
end
properties_controller.rb
def new
#property = Property.new
5.times { #property.photos.build }
end
def edit
#property = Property.find(params[:id])
5.times { #property.photos.build }
end
new.html.erb
<h1>Create New Listing</h1>
<%= form_for(:property, :url => {:action => 'create'}, :html => {:multipart => true})
do|f| %>
<%= f.file_field :avatar %>
<% f.fields_for :photo do |f| %>
<%= f.file_field :avatar, {:multiple => true} %>
<% end %>
<table>
<tr>
<th>Agent_ID</th>
<td><%= f.text_field(:agent_id) %></td>
</tr>
<tr>
<th>Address</th>
<td><%= f.text_field(:address) %></td>
</tr>
<tr>
<th>Neighborhood</th>
<td><%= f.text_field(:neighborhood) %></td>
</tr>
<tr>
<th>Price</th>
<td><%= f.text_field(:price) %></td>
</tr>
</table>
<%= submit_tag("Create Listing") %>
<%= link_to 'Return to list', 'list' %>
I was unable to get 5 different file fields as emerson does in his video. Does anyone know what is wrong with my code? I'm guessing that the problem is in the form page.
Any help on how to make it work is greatly appreciated.
Thanks
should:
<% f.fields_for :photo do |f| %>
not be:
<% f.fields_for :photos do |f| %>
Also I don't know if rails and paperclip support multiple on a file field out of the box: http://initializd.com/blog/2013/3/upload-multiple-files-with-html5-rails-mongoid-paperclip-and-google-cloud-storage

ActiveAdmin Form with 2 models (belongs_to and has_many) don't work

I have the following code form my passport_visas.rb model
ActiveAdmin.register PassportVisa do
menu :label => "Visas"
form :partial => "form"
index :title => "Visas"
end
And this is my code for the partial "form"
<%= semantic_form_for [:admin, #passport_visa] do |f| %>
<%= f.inputs "Main information" do %>
<%= f.input :country %>
<%= f.input :citizenship, :as => :radio, :collection => {"US Citizen" => 0, "Foreign National" => 1} %>
<%= f.input :visa_type, :as => :select, :collection => ["Tourist", "Business", "Official"] %>
<%= f.input :visa_required, :label => "Is Visa Required?", :as => :radio, :collection => {"Required" => 0, "Not Required" => 1} %>
<%= f.input :maximum_stay, :label => "Maximum Stay" %>
<% end %>
<fieldset class="actions">
<ol>
<li class="action input_action" id="passport_visa_add_new_entry">
<input name="new_entry" type="button" value="Add New Entry">
</li>
<li class="action input_action" id="passport_visa_remove_entry">
<input name="remove_entry" type="button" value="Remove Entry">
</li>
</ol>
</fieldset>
<!-- Problem -->
<%= f.inputs "Entries" do %>
<%= f.has_many :visa_entries do |entry| %>
<%= entry.input :type_of_entry, :as => :select, :collection => ["Testing"] %>
<% end %>
<% end %>
<%= f.actions %>
<% end %>
And I'm getting this error message: "undefined method `has_many' for #Formtastic::FormBuilder:0x10c234c38"
I'm trying the entire day to setup this form, here's my model's code:
passport_visa.rb
class PassportVisa < ActiveRecord::Base
has_many :visa_entries
accepts_nested_attributes_for :visa_entries
end
visa_entry.rb
class VisaEntry < ActiveRecord::Base
belongs_to :passport_visa
attr_accessible :type_of_entry, :maximum_validity, :embassy_fees, :service_fees, :processing_time
end
Finally I found a work around for that. So here's what I did to make it work:
First I got rid of the _form partial, because for some reason the "has_many" don't work inside there.
I modified my 2 models:
passport_visa.rb
class PassportVisa < ActiveRecord::Base
has_many :visa_entries
accepts_nested_attributes_for :visa_entries
attr_accessible :visa_entries_attributes, :country, :citizenship, :visa_type, :visa_required, :maximum_stay
validates_presence_of :country, :citizenship, :visa_type, :visa_required, :maximum_stay
end
visa_entry.rb
class VisaEntry < ActiveRecord::Base
belongs_to :passport_visa
attr_accessible :type_of_entry
validates_presence_of :type_of_entry
end
And the last part, the actual form:
form do |f|
f.inputs "Entries" do
f.has_many :visa_entries do |ff|
ff.input :type_of_entry, :as => :select, :collection => ["Testing"]
end
end
f.actions
end
Bye!

How do edit a line item associated with has_many relationship but uses a single class?

I have an invoice controller and two model invoice and invoice_line_items and create a tax_line_items using invoice_line_item class. Below is my code :
Here is my controller code :
class InvoicesController < ApplicationController
def new
#menu = 'Income'
#page_name = 'Create new invoice'
#invoice = Invoice.new
#invoice.invoice_line_items.build
#invoice.tax_line_items.build
respond_to do |format|
format.html
format.xml { render :xml => #invoice }
end
end
end
My model for invoice:
class Invoice < ActiveRecord::Base
has_many :invoice_line_items
has_many :tax_line_items, :class_name => "InvoiceLineItem",:dependent => :destroy
accepts_nested_attributes_for :invoice_line_items, :reject_if => lambda {|a| a[:account_id].blank? } , :allow_destroy => true
accepts_nested_attributes_for :tax_line_items, :reject_if => lambda {|a| a[:account_id].blank? } , :allow_destroy => true
end
and in my forms i used :
<%= form_for(#invoice) do |f| %>
<%= render 'shared/form_error', :object => #invoice %>
<% #invoice.invoice_line_items.each_with_index do |invoice_line_item, index| %>
<%= render "invoice_line_items", :invoice_line_item => invoice_line_item, :index => index %>
<% end %>
<% #invoice.tax_line_items.each_with_index do |tax_line_item, tax_index| %>
<%= render "tax_line_items", :tax_line_item => tax_line_item, :tax_index => tax_index %>
<% end %>
<%end%>
partials :
1) invoice_line_items:
<tr id="row<%= index %>" valign="top" >
<%= hidden_field_tag "invoice[invoice_line_items_attributes][#{index}][id]",invoice_line_item.id%>
<td valign="top">
<%= select_tag "invoice[invoice_line_items_attributes][#{index}][account_id]", options_from_collection_for_select(#from_accounts, :id, :name,:selected => invoice_line_item.account_id ), :include_blank => true, :class=>"full" %>
<!-- <a href="/accounts/new?account_head_id=10" > New item</a> -->
</td>
<td><%= text_area_tag "invoice[invoice_line_items_attributes][#{index}][description]",invoice_line_item.description, :class => "full", :cols => 10, :rows=>1 %></td>
<td><%= text_field_tag "invoice[invoice_line_items_attributes][#{index}][quantity]",invoice_line_item.quantity, :class => 'full', :id => 'quantity', :onkeydown => "return numbersOnly(event);", :size => 5, :maxlength => 25 %></td>
<td><%= text_field_tag "invoice[invoice_line_items_attributes][#{index}][unit_rate]",invoice_line_item.unit_rate, :class => 'full', :id => 'unit_cost', :onkeydown => "return numbersOnly(event);", :size => 5, :maxlength => 20 %></td><!--Jquery code is in application.js-->
<td><%= text_field_tag "invoice[invoice_line_items_attributes][#{index}][discount_percent]", invoice_line_item.discount_percent, :class => 'full', :id => 'discount', :onkeydown => "return numbersOnly(event);", :maxlength => 5, :size => 5%></td>
<td><%= text_field_tag "invoice[invoice_line_items_attributes][#{index}][amount]", invoice_line_item.amount, :class => 'full', :id => 'total', :readonly => 'readonly', :size => 5%></td>
<td><%= link_to image_tag("/images/black_icon/ic_cancel.png"),{:action => :remove_line_item, :index => index}, :remote => true unless index == 0 %></td>
</tr>
and 2) tax_line_items:
<tr id="tax_row<%= tax_index %>" valign="top" >
<%= hidden_field_tag "invoice[tax_line_items_attributes][#{tax_index}][id]",tax_line_item.id%>
<%= hidden_field_tag "invoice[tax_line_items_attributes][#{tax_index}][tax]", tax_line_item.tax, :value => 1 %>
<td style="background:#EDF4FF"></td>
<td class="ta-right" style="background:#EDF4FF" colspan="2"><label>Add Tax:</label></td>
<td class="ta-right" colspan="2" style="background:#EDF4FF">
<%= select_tag "invoice[tax_line_items_attributes][#{tax_index}][account_id]", options_from_collection_for_select(#tax_accounts, :id, :name,:selected => tax_line_item.account_id ), :include_blank => true, :class=>"full" %>
<!-- <a href="/accounts/new?account_head_id=10" > New item</a> -->
</td>
<td style="background:#EDF4FF"><%= text_field_tag "invoice[tax_line_items_attributes][#{tax_index}][amount]", tax_line_item.amount, :class => 'full', :id => 'tax', :onkeydown => "return numbersOnly(event);", :size => 5%></td>
<td style="background:#EDF4FF"><%= link_to image_tag("/images/black_icon/ic_cancel.png"),{:action => :remove_tax_item, :tax_index => tax_index}, :remote => true %></td>
</tr>
I can add new line item entry easily and edit it when their is no tax item. The problem is
when their is an tax item created in any entry and later try to edit this entry then my line items row appears multiple time for example suppose i have a tax item them a new row will appear for invoice line item ans an extra row for tax line items. i think this will happen because i have used a common table for both the line items. I did this because i have to save both line items entry in same table as both accounts came from same table.
I am very thankful if anyone have the right answer.Thanks a lot
As this answer suggests, you need to add a 'type' column to this table to distinguish between invoice and tax items. It will remove a lot of complications from your code as Rails will do the work of identifying which record belongs to which model class from the common table.

Updating unused field after initial creation does not work rails

For reference, this is using Rails 3.0.9.
I can't seem to figure out why, but I cannot update a field which was left blank at the initial creation of the object/row.
If my model looks like this:
name - string
date - date
message - string
If I put info in all of the fields upon initial creation, everything can be updated without a hitch later on. But if I do not put info in one of the fields, say the title, I cannot update that field after initial creation.
I'm not doing anything out of the ordinary, the form is pretty plain jane:
<%= form_for #event do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :date %><br />
<%= f.date_select :date %>
</p>
<p>
<%= f.label :message %><br />
<%= f.text_field :message %>
</p>
<p><%= f.submit %></p>
<% end %>
And my controller is equally as simple:
def update
if #event.update_attributes(params[:event])
redirect_to #event, :notice => "Successfully updated event."
else
render :action => 'edit'
end
end
And the model:
class Event < ActiveRecord::Base
has_many :races, :dependent => :destroy
has_many :price_groups, :dependent => :destroy
accepts_nested_attributes_for :races, :reject_if => lambda{ |a| a[:name].blank? }, :allow_destroy => true
accepts_nested_attributes_for :price_groups, :reject_if => lambda{ |a| a[:name].blank? }, :allow_destroy => true
attr_accessible :name, :date, :message, :races_attributes, :price_groups_attributes
end

Active record has_many association for one model having two types of values

i am facing a new situation. I know someone definitely had faced these type of situation:
I have an invoices table and an invoice_line_items table. Till now every thing is going well with has_many and belongs to association. Now i want to add tax accounts in invoice items, for that i don't want to create a separate table, hence i make below changes in my invoice model :
invoice.rb:
class Invoice < ActiveRecord::Base
has_many :invoice_line_items
has_many :tax_line_items, :class_name => "InvoiceLineItem", :dependent => :destroy
accepts_nested_attributes_for :invoice_line_items, :reject_if => lambda {|a|a[:account_id].blank? } , :allow_destroy => true
#validations
validates_presence_of :invoice_line_items
validates_associated :invoice_line_items
end
invoice_line_item.rb:
class InvoiceLineItem < ActiveRecord::Base
belongs_to :invoice
end
and in my controller i did:
class InvoicesController < ApplicationController
def new
#invoice = Invoice.new
#invoice.invoice_line_items.build
#invoice.tax_line_items.create
#from_accounts = TransactionType.fetch_from_accounts(current_company.id,'sales')
#to_accounts = TransactionType.fetch_to_accounts(current_company.id, 'sales')
#tax_accounts = TransactionType.fetch_from_accounts(current_company.id, 'tax')
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #invoice }
end
end
end
in my form i did:
for tax accounts
<% #invoice.invoice_line_items.each_with_index do |invoice_line_item, tax_index| %>
<%= render "tax_line_items", :invoice_line_item => invoice_line_item, :index => tax_index %>
<% end %>
and for invoice items:
<% #invoice.invoice_line_items.each_with_index do |invoice_line_item, index| %>
<%= render "invoice_line_items", :invoice_line_item => invoice_line_item, :index => index %>
<% end %>
and here are my partials:
1)_invoice_line_items.html.erb:
<tr id="row<%= index %>" valign="top" >
<%= hidden_field_tag "invoice[invoice_line_items_attributes][#{index}][id]",invoice_line_item.id%>
<td valign="top">
<%= select_tag "invoice[invoice_line_items_attributes][#{index}][account_id]", options_from_collection_for_select(#from_accounts, :id, :name,:selected => invoice_line_item.account_id ), :include_blank => true, :class=>"full" %>
<!-- <a href="/accounts/new?account_head_id=10" > New item</a> -->
</td>
<td><%= text_area_tag "invoice[invoice_line_items_attributes][#{index}][description]",invoice_line_item.description, :class => "full",:rows =>2 %></td>
<td><%= text_field_tag "invoice[invoice_line_items_attributes][#{index}][quantity]",invoice_line_item.quantity, :class => 'amount', :id => 'quantity', :onkeydown => "return numbersOnly(event);", :size => 8, :maxlength => 25 %></td>
<td><%= text_field_tag "invoice[invoice_line_items_attributes][#{index}][unit_rate]",invoice_line_item.unit_rate, :class => 'amount', :id => 'unit_cost', :onkeydown => "return numbersOnly(event);", :size => 8, :maxlength => 20 %></td><!--Jquery code is in application.js-->
<td><%= text_field_tag "invoice[invoice_line_items_attributes][#{index}][discount_percent]", invoice_line_item.discount_percent, :class => 'amount', :id => 'discount', :onkeydown => "return numbersOnly(event);", :maxlength => 5, :size => 8%></td>
<td><%= text_field_tag "invoice[invoice_line_items_attributes][#{index}][amount]", invoice_line_item.amount, :class => 'full', :id => 'total', :readonly => 'readonly', :size => 5%></td>
<td><%= link_to 'Remove',{:action => :remove_line_item, :index => index}, :remote => true unless index == 0 %></td>
</tr>
2) _tax_line_items.html.erb:
<tr id="tax_row<%= tax_index %>" valign="top" >
<%= hidden_field_tag "invoice[tax_line_items_attributes][#{tax_index}][id]",invoice_line_item.id%>
<td></td>
<td colspan="2" class="ta-right"><label>Add Tax:</label></td>
<td class="ta-right" colspan="2" style="background:#EDF4FF">
<%= select_tag "invoice[invoice_line_items_attributes][#{tax_index}][account_id]", options_from_collection_for_select(#tax_accounts, :id, :name,:selected => invoice_line_item.account_id ), :include_blank => true, :class=>"full" %>
<!-- <a href="/accounts/new?account_head_id=10" > New item</a> -->
</td>
<td style="background:#EDF4FF"><%= text_field_tag "invoice[invoice_line_items_attributes][#{tax_index}][amount]", invoice_line_item.amount, :class => 'full', :id => 'tax', :onkeydown => "return numbersOnly(event);", :size => 5%></td>
<td><%= link_to 'Remove',{:action => :remove_tax_item, :index => tax_index}, :remote => true %></td>
</tr>
My motto is to save both items accounts and tax accounts in invoice_line_items table's account_id column, i hope some buddy has the answer, thanks in advance
The issue you have is #invoice.invoice_line_items and #invoice.tax_line_items will return the same values since they both are using the same id to join.
Seems like you could use Single Table Inheritance (you will have to scroll down to find the section in the API). Using a type column in the invoice_line_items table, you can have model inheritance.
class InvoiceLineItem < ActiveRecord::Base
belongs_to :invoice
end
class TaxLineItem < InvoiceLineItem
belongs_to :invoice
end
then you can cleanup you associations in Invoice
class Invoice < ActiveRecord::Base
has_many :invoice_line_items
has_many :tax_line_items, :dependent => :destroy
end
i got the solution any how i did this:
<% #invoice.tax_line_items.each_with_index do |tax_line_item, tax_index| %>
<%= render "tax_line_items", :tax_line_item => tax_line_item, :index => tax_index %>
<% end %>
and in the partial of _tax_line_items :
<tr id="tax_row<%= tax_index %>" valign="top" >
<%= hidden_field_tag "invoice[tax_line_items_attributes][#{tax_index}][id]",invoice_line_item.id%>
<td></td>
<td colspan="2" class="ta-right"><label>Add Tax:</label></td>
<td class="ta-right" colspan="2" style="background:#EDF4FF">
<%= select_tag "invoice[tax_line_items_attributes][#{tax_index}][account_id]", options_from_collection_for_select(#tax_accounts, :id, :name,:selected => invoice_line_item.account_id ), :include_blank => true, :class=>"full" %>
</td>
<td style="background:#EDF4FF"><%= text_field_tag "invoice[tax_line_items_attributes][#{tax_index}][amount]", tax_line_item.amount, :class => 'full', :id => 'tax', :onkeydown => "return numbersOnly(event);", :size => 5%></td>
<td><%= link_to 'Remove',{:action => :remove_tax_item, :index => tax_index}, :remote => true %></td>
</tr>
and this is working for me....