Nested attributes are not updating in rails - ruby-on-rails

I have 3 models:
class DropShipOrderLineItem < ActiveRecord::Base
belongs_to :drop_ship_order
belongs_to :line_item
validates_associated :drop_ship_order
validates_associated :line_item
validates :drop_ship_order_id, :presence => true
validates :line_item_id, :presence => true
attr_accessible :missing
end
class DropShipOrder < ActiveRecord::Base
attr_accessible :line_items, :line_items_attributes, :orders, :order_attributes
belongs_to :retailer
belongs_to :order
belongs_to :shipping_method
has_many :drop_ship_order_line_items
has_many :line_items, :through => :drop_ship_order_line_items
has_many :shipments, :dependent => :destroy
accepts_nested_attributes_for :line_items
accepts_nested_attributes_for :order
accepts_nested_attributes_for :drop_ship_order_line_items
before_create :generate_order_number
scope :by_number, lambda {|number| where("drop_ship_orders.number = ?", number)}
scope :between, lambda {|*dates| where("drop_ship_orders.created_at between ? and ?", dates.first.to_date, dates.last.to_date)}
scope :by_customer, lambda {|customer| joins(:order).joins(:user).where("users.email =?", customer)}
scope :by_state, lambda {|state| where("state = ?", state)}
scope :complete, where("drop_ship_orders.completed_at IS NOT NULL")
scope :incomplete, where("drop+ship_orders.orders.completed_at IS NULL")
make_permalink :field => :number
validates_associated :order
validates_associated :retailer
end
LineItem.class_eval do
has_one :drop_ship_order_line_item, :dependent => :destroy
has_one :drop_ship_order, :through => :drop_ship_order_line_items
accepts_nested_attributes_for :drop_ship_order_line_item
attr_accessible :drop_ship_order_line_item
# def missing
# self.drop_ship_order_line_item.missing
# end
end
View #1:
<div data-hook="admin_order_edit_form">
<div id="order-form-wrapper">
<%= render :partial => 'form', :locals => {:drop_ship_order => #drop_ship_order} %>
</div>
</div>
View form:
<%= form_for(#drop_ship_order, :url => admin_drop_ship_order_path(#drop_ship_order), :html => { :method => :put}) do |f| %>
<%= f.hidden_field :number %>
<table class="index">
<tbody id='line-items'>
<tr data-hook="admin_order_form_line_items_headers">
<th><%= t('item_description') %></th>
<th class="price"><%= t('price') %></th>
<th class="qty"><%= t('qty') %></th>
<th class="total"><span><%= t('total') %></span></th>
<th class="orders-actions" data-hook="admin_order_form_line_items_header_actions"></th>
</tr>
<%= f.fields_for :line_items do |li_form| %>
<%= render :partial => "admin/drop_ship_orders/line_item", :locals => { :f => li_form } %>
<% end %>
</tbody>
<tbody id='subtotal' data-hook="admin_order_form_subtotal">
<tr id="subtotal-row">
<td colspan="3"><b><%= t('subtotal') %>:</b></td>
<td class="total"><span><%= number_to_currency #drop_ship_order.item_total %></span></td>
<td></td>
</tr>
</tbody>
view line_item:
<tr id="<%= dom_id(f.object) %>" data-hook="admin_order_form_line_item_row">
<td width="300"><%=f.object.variant.product.name%> <%= "(" + variant_options(f.object.variant) + ")" unless f.object.variant.option_values.empty? %></td>
<td valign="top" class="price"><%= number_to_currency f.object.price %></td>
<td valign="top" class="qty"><strong><%= f.object.quantity %></strong></td>
<td valign="top" class="total"><%= number_to_currency (f.object.price * f.object.quantity)%></td>
<td data-hook="admin_order_form_line_item_actions">
<!--<input type="checkbox" name="apple" id="apples"/>-->
<%#= f.object.drop_ship_order_line_item.missing %>
<%= f.fields_for :drop_ship_order_line_item do |build|%>
<%= build.check_box :missing, :type => "checkbox" %>
<% end %>
</td>
</tr>
The :missing attribute is not being updated, and I just can't figure out why! Although the checkboxe is correctly being ticked if I manually change the values in my SQL table.
p.s: I just posted the relevant parts of my code.

In your LineItem model change attr_accessible :drop_ship_order_line_item to attr_accessible :drop_ship_order_line_item_attributes.

What is the :type => "checkbox" for in the following code:
<%= build.check_box :missing, :type => "checkbox" %>
The second parameter for the check_box form helper should be the method. I think if you change to the following code, it should work:
<%= build.check_box :missing %>

Related

Using cocoon, my has_many through association doesn't get updated or deleted

Using cocoon to build my nested form for a has_many through association. The association gets created, however it doesn't update or remove the associations. The following is my nested form:
edit.html.erb:
<div class="case_contacts-edit-container">
<%= link_to_add_association 'ADD CONTACT', f, :case_contacts, :"data-association-insertion-node" => "tbody#case_contacts_", :"data-association-insertion-method" => "append", class: 'action-button insure pull-right' %>
<table id="info-table3">
<tbody id="case_contacts_">
<tr>
<td class="right">
<strong>Name</strong>
</td>
<td class="right">
<strong>Role</strong>
</td>
<td class="right">
<strong>Note</strong>
</td>
<td>
</td>
</tr>
<%= f.simple_fields_for :case_contacts do |case_contact| %>
<%= render 'case_contact_fields', :f => case_contact %>
<% end %>
</tbody>
</table>
_case_contact_fields.html.erb:
<tr class="nested-fields">
<td>
<%= f.association :contact, :collection => (Contact.all.select(:first_name, :last_name, :email, :company_name, :id).map { |contact| [contact.name_with_company, contact.id] }), :prompt => "Add Contact", :class => 'table-input', :label => false %>
</td>
<td>
<%= f.input :role, collection: Contact::TYPES, :prompt => "Add Role", :class => 'table-input', :label => false %>
</td>
<td>
<%= f.input :note, :prompt => "Add Note", :class => 'table-input', :label => false %>
</td>
<%= f.hidden_field :firm_id, :value => #firm.id %>
<td class="insurance-icon" style="text-align: center;">
<%= link_to_remove_association f, class: 'dark-small remove_case_contacts' do %><span id="remove" class="glyphicon glyphicon-trash" original-title="Remove Contact"></span><% end %>
</td>
</tr>
cases_controller.rb (update method):
#case.assign_attributes(case_params)
#case.save
cases_controller.rb (permitted parms):
def case_params
params.require(:case).permit(:name, :case_number, :docket_number, :description, :case_type, :subtype,
:court, :county, :corporation, :status, :hearing_date, :filed_suit_date, :fee_agreement,
:case_contacts_attributes => [:id, :case_id, :updated_at, :created_at, :firm_id, :role, :contact_id, :note, :_destroy])
end
case.rb (model):
has_many :case_contacts, :dependent => :destroy
has_many :contacts, :through => :case_contacts
accepts_nested_attributes_for :case_contacts, :reject_if => :all_blank, :allow_destroy => :true
contact.rb (model):
has_many :case_contacts, :dependent => :destroy
has_and_belongs_to_many :cases, :join_table => 'case_contacts'
case_contact.rb (joiner model):
belongs_to :affair, class_name: 'Case', :foreign_key => 'case_id'
belongs_to :contact

Associations access column values rails

I have a Customer and Invoice Model. A customer has many invoices and an invoice belongs_to a customer. An invoice has many invoice items and Invoice items belong to an invoice
class Customer < ActiveRecord::Base
attr_accessible :billing_address, :customer_currency, :email, :first_name, :last_name, :mobile, :name, :payment_terms, :phase_type, :pays_vat
validates_presence_of :first_name, :last_name, :mobile, :billing_address, :payment_terms, :phase_type, :customer_currency
has_many :invoices
validates :email,
:presence => true,
:uniqueness => true,
:email_format => true
validates :name, :mobile, :presence => true, :uniqueness => true
end
Invoice Model
class Invoice < ActiveRecord::Base
belongs_to :customer
attr_accessible :approved_by, :due_date, :invoice_date, :terms, :customer_id, :customer
validates :invoice_date, presence: true
validates :due_date, presence: true
validates :customer, presence: true
has_many :invoice_items
accepts_nested_attributes_for :invoice_items
end
Invoice Items model
class InvoiceItem < ActiveRecord::Base
belongs_to :invoice
attr_accessible :amount, :description, :rate, :tax_amount
end
I have created an index page for Invoices where I want to list all invoices with their corresponding items however, the challenge I am having is how to access the amount in invoice items and display it in the index page
app/views/index.html.erb
<div class="row">
<div class="span12">
<table class="table table-striped">
<thead>
<tr>
<th>Invoice ID </th>
<th>Customer Name </th>
<th>Invoice Date </th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<% #invoices.each do |invoice| %>
<tr>
<td><%= link_to invoice.id, invoice_path(invoice) %></td>
<td><%= invoice.customer.name %></td>
<td><%= invoice.invoice_date %></td>
<td><%= invoice.invoice_items.amount %></td>
</tr>
<% end %>
</tbody>
</table>
<div class="form actions">
<p>
<%= link_to t('.new', :default => t("helpers.links.new")),
new_invoice_path, :class => 'btn btn-primary' %>
</p>
</div>
</div>
</div>
invoice.invoice_items.amount does not return that amount from Invoice_items for that invoice. Any ideas?
Below is my Invoices_controller index method
class InvoicesController < ApplicationController
before_filter :authenticate_user!
def index
#invoices = Invoice.includes(:customer, :invoice_items).all
end
end
You can get amount of any elements using
invoice.invoice_items.count
or
invoice.invoice_items.size
invoice.invoice_items.first.amount
iterate on invoice_items too, inside #invoices iterator
<% #invoices.each do |invoice| %>
<tr>
<td><%= link_to invoice.id, invoice_path(invoice) %></td>
<td><%= invoice.customer.name %></td>
<td><%= invoice.invoice_date %></td>
<% invoice.invoice_items.each do |invoice_item| %>
<td><%= invoice_item.rate %></td>
<td><%= invoice_item.amount %></td>
</tr>
<% end %>
adjust the table

How to set a value of a model to f.label

I'm using rails 3.2.
I have many to many type of models.
Is there a way to set a "value" of a model to field_for.label?
Here's what I want to do.
Client model
class Client < ActiveRecord::Base
attr_accessible :name, :renewal_month1, :renewal_month10, :renewal_month11, :renewal_month12, :renewal_month2, :renewal_month3, :renewal_month4, :renewal_month5, :renewal_month6, :renewal_month7, :renewal_month8, :renewal_month9, :sales_person_id, :usable, :user_id, :licenses_attributes
has_many :licenses, :dependent => :destroy
has_many :systems, :through => :licenses
accepts_nested_attributes_for :licenses
end
License model
class License < ActiveRecord::Base
attr_accessible :amount, :client_id, :system_id
belongs_to :client
belongs_to :system
def system_name
self.system.name
end
end
System model
class System < ActiveRecord::Base
attr_accessible :name, :sort
has_many :clients
has_many :licenses
has_many :clients, :through => :licenses
end
In client controller I built license object for all system.
def new
#client = Client.new
#title = "New Client"
System.all.each do |system|
#client.licenses.build(:system_id => system.id)
end
respond_to do |format|
format.html # new.html.erb
format.json { render json: #client }
end
end
In _form.html.erb I use fieds_for for licenses
<%= f.fields_for :licenses do |ff| %>
<tr>
<td><%= ff.label :system_id %></td>
</td>
<td> <%= ff.number_field :amount %>
<%= ff.hidden_field :system_id %>
<%= ff.hidden_field :system_name %>
</td>
</tr>
<% end %>
Result I get is this
<tr>
<td><label for="client_licenses_attributes_0_system_id">System</label></td>
</td>
<td> <input id="client_licenses_attributes_0_amount" name="client[licenses_attributes][0][amount]" type="number" value="10" />
<input id="client_licenses_attributes_0_system_id" name="client[licenses_attributes][0][system_id]" type="hidden" value="1" />
<input id="client_licenses_attributes_0_system_name" name="client[licenses_attributes][0][system_name]" type="hidden" value="SYSTEMNAME" />
</td>
</tr>
I want the label to look like this.
<td><label for="client_licenses_attributes_0_system_id">SYSTEMNAME</label></td>
SYSTEMNAME is the value of the model SYSTEM.
I have a virtual attribute in LICENSE model defined as system_name.
I was able to get SYSTEMNAME in hidden_field so I think models and controllers are fine.
I just couldn't find out how to set the value of a model to label.
Why can't you use the following?
<%= ff.label :system_name %>
I think the next code should work as well
<%= ff.label :amount, ff.object.system_name %>
I can't test this, but I hope it will generate
<label for="client_licenses_attributes_0_amount">SYSTEMNAME</label>
Note, that it creates a label for amount field, so that when the user click on it, amount field will be focused.
Have you tried adding system_name to the label
<%= f.fields_for :licenses do |ff| %>
<tr>
<td><%= ff.label :system_id, :system_name %></td>
<td> <%= ff.number_field :amount %>
<%= ff.hidden_field :system_id %>
<%= ff.hidden_field :system_name %>
</td>
</tr>
<% end %>

Complex Multi Model Rails From

How can I fill in the hidden fields in app/views/rounds/shot_fields.html.erb?
app/models/player.rb
class Player < ActiveRecord::Base
has_many :shots, :dependent => :destroy
belongs_to :team
belongs_to :user
has_many :games
has_and_belongs_to_many :home_games, :class_name => "Game"
has_and_belongs_to_many :away_games, :class_name => "Game"
end
app/models/round.rb
class Round < ActiveRecord::Base
belongs_to :game, :counter_cache => true
has_many :shots, :dependent => :destroy
accepts_nested_attributes_for :shots, :allow_destroy => true
validates_presence_of :number
validates_numericality_of :number
end
app/models/shot.rb
class Shot < ActiveRecord::Base
belongs_to :player, :counter_cache => true
belongs_to :game
belongs_to :round
belongs_to :team
end
app/models/game.rb
class Game < ActiveRecord::Base
has_many :shots, :dependent => :destroy
has_many :rounds, :order => 'number', :dependent => :destroy
accepts_nested_attributes_for :shots
belongs_to :away, :class_name => 'Team'
belongs_to :home, :class_name => 'Team'
has_and_belongs_to_many :home_players, :class_name => 'Player', :association_foreign_key => "home_player_id"
has_and_belongs_to_many :away_players, :class_name => 'Player', :association_foreign_key => "away_player_id"
accepts_nested_attributes_for :rounds, :allow_destroy => true
end
app/controllers/rounds_controller.rb
def new
#game = Game.find(params[:game_id])
#round = #game.rounds.build
#round.number = #game.rounds.count > 1 ? #game.rounds.count + 1 : 1
end
app/views/rounds/_form.html.erb
<% if #round.errors.any? %>
<div class="error">
<% #round.errors.full_messages.each do |msg| %>
<%= msg %><br/>
<% end %>
</div>
<% end %>
<%= form_for #game do |f| %>
<%= field_set_tag "Rounds" do %>
<table class="sortable">
<thead>
<tr>
<th>Number</th>
<th><%= #game.away_players[0].name %></th>
<th><%= #game.away_players[1].name %></th>
<th><%= #game.away_players[2].name %></th>
<th><%= #game.home_players[0].name %></th>
<th><%= #game.home_players[1].name %></th>
<th><%= #game.home_players[2].name %></th>
<th>Remove</th>
</tr>
</thead>
<tbody>
<%= f.fields_for :rounds do |round_form| %>
<%= render 'round_fields', :f => round_form %>
<% end -%>
</tbody>
</table>
<p>
<%= link_to_add_fields "Add Round", f, :rounds %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
<% end %>
app/views/rounds/round_fields.html.erb
<% 6.times { f.object.shots.build } if f.object.new_record? -%>
<tr>
<td>
<%= f.text_field :number, :size => 3 %>
</td>
<%= f.fields_for :shots do |shot_form| %>
<%= render 'shot_fields', :f => shot_form %>
<% end -%>
<td>
<%= f.check_box(:_destroy) %>
<%= f.hidden_field :id %>
</td>
</tr>
app/views/rounds/shot_fields.html.erb
<td>
<%= f.select :cup, [["Miss", 0], 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ["No Shot", ""], ["Suicide", 11]] %>
<%= f.hidden_field :id %>
<%= f.hidden_field :game_id, :value => params[:id] %>
<%# f.hidden_field :player_id, :value => player.id %>
<%# f.hidden_field :team_id, :value => team.id %>
</td>
Passing them in via locals should work.
<%= render 'shot_fields', :locals => { :f => shot_form, :player => some_player_you_dont_have_defined, :team => some_team_variable_i_dont_see } %>
I don't quite understand what you're trying to do (lots of code, not a lot of context), but this is how you pass information into partials.

Uninitialized constant Item::Types

I get this uninitialized constant error when i submit my nested forms.
order.rb
class Order < ActiveRecord::Base
has_many :items, :dependent => :destroy
has_many :types, :through => :items
accepts_nested_attributes_for :items
accepts_nested_attributes_for :types
validates_associated :items
validates_associated :types
end
item.rb
class Item < ActiveRecord::Base
has_one :types
belongs_to :order
accepts_nested_attributes_for :types
validates_associated :types
end
type.rb
class Type < ActiveRecord::Base
belongs_to :items
belongs_to :orders
end
new.erb.html
<% form_for #order do |f| %>
<%= f.error_messages %>
<% f.fields_for :items do |builder| %>
<table border="0">
<th>Type</th>
<th>Amount</th>
<th>Text</th>
<th>Price</th>
<tr>
<% f.fields_for :type do |m| %>
<td> <%= m.collection_select :type, Type.find(:all, :order => "created_at DESC"), :id, :name, {:prompt => "Select a Type" }, {:id => "selector", :onchange => "type_change(this)"} %> </td>
<% end %>
<td> <%= f.text_field :amount, :id => "amountField", :onchange => "change_total_price()" %> </td>
<td> <%= f.text_field :text, :id => "textField" %> </td>
<td> <%= f.text_field :price, :class => "priceField", :onChange => "change_total_price()" %> </td>
<td> <%= link_to_remove_fields "Remove Item", f %> </td>
</tr>
</table>
<% end %>
<p><%= link_to_add_fields "Add Item", f, :items %></p>
<p>
<%= f.label :total_price %><br />
<%= f.text_field :total_price, :class => "priceField", :id => "totalPrice" %>
</p>
<p><%= f.submit "Create"%></p>
<% end %>
<%= link_to 'Back', orders_path %>
create method in orders_controller.rb
def create
#order = Order.new(params[:order])
respond_to do |format|
if #order.save
flash[:notice] = 'Post was successfully created.'
format.html { redirect_to(#order) }
format.xml { render :xml => #order, :status => :created,
:location => #order }
else
format.html { render :action => "new" }
format.xml { render :xml => #order.errors,
:status => :unprocessable_entity }
end
end
end
Hopefully you can see what i cant
You need to pay careful attention to pluralization in Rails. In this case you're setting up a singular relationship to a plural thing, so it's presumed that you're actually calling a class named "Types" and not "Type".
has_one, belongs_to are singular
has_many is plural
Possible fixes:
class Item < ActiveRecord::Base
has_one :type
belongs_to :order
accepts_nested_attributes_for :type
validates_associated :type
end
class Type < ActiveRecord::Base
belongs_to :item
belongs_to :order
end
In rails, type is a reserved word. You have to rename your model to something else. Also you have to follow tadman's instruction about singular names for has_one association.
Reference
Reserved words in rails

Resources