Ruby: UnknownAttributeError - ruby-on-rails

i have some Orders that can have several Items and these Items have an associated Kind. The Kind can belong to many Items. but i get a "unknown attribute: kinds" in my OrdersController when i hit the submit form button. I use nested forms btw.
Order.rb
class Order < ActiveRecord::Base
validates_presence_of :ref_nr, :total_price
has_many :items, :dependent => :destroy
has_many :kinds, :through => :items
accepts_nested_attributes_for :items
accepts_nested_attributes_for :kinds
validates_associated :items
validates_associated :kinds
end
Item.rb
class Item < ActiveRecord::Base
belongs_to :order
has_one :kind
accepts_nested_attributes_for :kind
validates_associated :kind
end
Kind.rb
class Kind < ActiveRecord::Base
belongs_to :items
end
OrdersController.rb:Create
def create
#order = Order.new(params[:order])
end
new.erb.html
<% form_for #order do |f| %>
<%= f.error_messages %>
<% f.fields_for :items do |builder| %>
<table>
<tr>
<% builder.fields_for :kinds do |m| %>
<td><%= m.collection_select :kind, Kind.find(:all, :order => "created_at DESC"), :id, :name, {:prompt => "Select a Type" }, {:id => "selector", :onchange => "kind_change(this)"} %></td>
<% end %>
<td><%= builder.text_field :amount, :id => "amountField", :onchange => "change_total_price()" %></td>
<td><%= builder.text_field :text, :id => "textField" %></td>
<td><%= builder.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><%= submit_tag %></p>
<% end %>
i cant see what im missing

You should remove accepts_nested_attributes_for :kinds in Order model and it should be in Item model (as in your code). Then change view here:
...
<% f.fields_for :items do |builder| %>
<table>
<tr>
<% builder.fields_for :kind do |m| %>
...
And I think that you have also mistake in following lines:
<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>
If fields amount, text and price are associated with Item model, then you should use builder instead of f:
<td><%= builder.text_field :amount, :id => "amountField", :onchange => "change_total_price()" %></td>
<td><%= builder.text_field :text, :id => "textField" %></td>
<td><%= builder.text_field :price, :class => "priceField", :onChange => "change_total_price()" %></td>
EDIT (to answer additional questions from comments):
You should have:
<% f.fields_for :items do |builder| %>
<table>
<tr>
<td><%= builder.collection_select :kind_id, Kind.find(:all, :order => "created_at DESC"), :id, :name, {:prompt => "Select a Type" }, {:id => "selector", :onchange => "kind_change(this)"} %></td>
<td><%= builder.text_field :amount, :id => "amountField", :onchange => "change_total_price()" %></td>
<td><%= builder.text_field :text, :id => "textField" %></td>
<td><%= builder.text_field :price, :class => "priceField", :onChange => "change_total_price()" %></td>
and so on...

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

Nested forms in ruby on rails using has_many through and belongs to associations

Lets say I have three objects/models; years, cars, and parts. Now, I have cars belong_to parts. The thought on this was that a part may be part of many cars but a car has only one of that part at a given time. and years has_many cars through car_years. I have successfully nested the cars form in the years form. However, when I try to nest the parts form in the cars form and create a new year I get cannot mass assign protected: parts. But, I can create a new car and it will successfully create the new part. I would like to know if I am on the right track or should I be looking elsewhere to solve this. I got the idea from rails cast #196.
Year model
class Year < ActiveRecord::Base
attr_accessible :year, :cars_attributes
has_many :car_years
has_many :cars, :through => :machine_years
accepts_nested_attributes_for :car_years,
:reject_if => lambda { |a| a[:num_cars].blank? },
:allow_destroy => true
accepts_nested_attributes_for :cars,
:reject_if => lambda { |a| a[:doors].blank? },
:allow_destroy => true
end
Car model
class Machine < ActiveRecord::Base
attr_accessible ..., :part_id, :part_attributes
has_many :car_years
has_many :years, :through => :car_years
belongs_to :part
accepts_nested_attributes_for :car_years
accepts_nested_attributes_for :years
accepts_nested_attributes_for :part,
:reject_if => lambda { |a| a[:name].blank? }
end
Parts Model
class Part < ActiveRecord::Base
attr_accessible :desc, :name
has_many :machines
end
Year_form View
<%= form_for(#year) do |f| %>
<% if #year.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#year.errors.count, "error") %> prohibited this year from being saved:</h2>
<ul>
<% #year.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :year %><br />
<%= f.date_select :year, :start_year => 1940, :end_year => Time.now.year, :discard_day => true, :discard_mon th => true %>
</div>
<h3>Cars</h3>
<div>
<%= f.fields_for :cars do |builder| %>
<%= render 'car_fields', :f => builder %>
<% end %>
<p><%= link_to_add_fields "Add Car", f, :cars %></p>
</div>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Car_fields.html.erb
<div class="field">
<h3>New Car</h3>
<table>
<tbody>
<tr>
<th><%= f.label :name %></th>
<th><%= f.label :model %></th>
<th><%= f.label :part_id %></th>
</tr>
<tr>
<td><%= f.text_field :name %></td>
<td><%= f.text_field :model %></td>
<td>
<%= f.fields_for :part do |builder| %>
<%= render "cars/parts_fields", :f => builder %>
<% end %>
</td>
<td><%= f.number_field :memory_id %></td>
</tr>
<tr>
<th><%= f.label :install_dt, "Install Date" %></th>
<th></th>
<th><%= f.label :production_dt, "Production Date" %></th>
<th></th>
<th><%= f.label :remove_dt, "Remove Date" %></th>
</tr>
<tr>
<td><%= f.date_select :install_dt, :start_year => 1940, :end_year => Time.now.year %></td>
<td></td>
<td><%= f.date_select :production_dt, :start_year => 1940, :end_year => Time.now.year %></td>
<td></td>
<td><%= f.date_select :remove_dt, :start_year => 1940, :end_year => Time.now.year %></td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<th><%= f.label :history %></th>
<th></th>
<th><%= f.label :design %></th>
<th></th>
<th><%= f.label :notes %></th>
</tr>
<tr>
<td><%= f.text_area :history, :rows => 4 %></td>
<td></td>
<td><%= f.text_area :design, :rows => 4 %></td>
<td></td>
<td><%= f.text_area :notes, :rows => 4 %></td>
</tr>
</tbody>
</table>
<div style="padding: 2px;">
<%= f.label :image %><br />
<%= f.text_field :image %>
</div>
<%= link_to_function "remove", "remove_fields(this)" %>
</div>
cars/part_fields.html.erb
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %><br />
<%= f.label :desc %><br />
<%= f.text_area :desc, :rows => 3 %>
</div>
Hard to tell without seeing any of you code. However the following error cannot mass assign protected: parts means that you should add attr_accessible :parts to your model in order to be able to do something like this:
a_part = Part.new
another_part = Part.new
Car.new(parts: [a_part, another_part])
Otherwise, without it, you would have to do:
c = Car.new
c.parts << a_part
c.parts << another_part
OK, so the solution was in another post:
Getting fields_for and accepts_nested_attributes_for to work with a belongs_to relationship
In the car_fields form I needed to call
<%= f.fields_for :part_attributes do |builder| %>
not
<% =f.fields_for :parts do |builder| %>
However, now when I look at the year edit screen the part fields are empty, but the part_type does exist

How to change my boolean output to a string value in ruby

I have a form where my user enters a person in reply to a wedding invite. They enter a name, menu choice, and select: attending - Yes / No - I then have a count on the true and false amounts with labels so the user can see how many people are attending or not attending.
My problem is in the table itself. Where the RSVP column sits, i have at moment just got 'true' or 'false'. Is there anyway in Ruby i can change this to be a string value for my index.html.erb?
Index
<% #replies.each do |reply| %>
<tr>
<td><%= reply.name %></td>
<td><%= reply.menu %></td>
<td><%= reply.rsvp %></td>
<td><%= link_to 'Show', reply, class: "btn" %></td>
<td><%= link_to 'Edit', edit_reply_path(reply), class: "btn" %></td>
<td><%= link_to 'Delete', reply, method: :delete, data: { confirm: 'Are you sure?' }, class: "btn btn-danger" %></td>
<td><%= reply.user.full_name %></td>
</tr>
<% end %>
reply.rb
class Reply < ActiveRecord::Base
attr_accessible :menu, :name, :rsvp, :user_id
belongs_to :user
def self.find_attending
Reply.where(:rsvp => "true").count
end
def self.find_not_attending
Reply.where(:rsvp => "false").count
end
end
_form.html.erb
<%= f.input :user_id, collection: User.all, label_method: :full_name, :label => 'Added By' %>
<%= f.input :name, :label => 'Person(s) Name' %>
<%= f.input :menu, :label => 'Menu Choice' %>
<%= f.collection_radio_buttons :rsvp, [[true, 'Attending'] ,[false, 'Not Attending']], :first, :last %>
db
class CreateReplies < ActiveRecord::Migration
def change
create_table :replies do |t|
t.string :name
t.text :menu
t.boolean :rsvp, :default => false
t.timestamps
end
end
end
I'm very new to Ruby, any pointers would be appreciated. Many thanks.
How about "#{reply.rsvp}"? Seems to be cleaner, doesn't it?
Just use a ternary:
reply.rsvp ? "true" : "false"
Replace "true" and "false" by whatever strings you want to display.

Rails: Multi-model form won't write data to models

Ok this is driving me round the bend. I have three models [which are relevant to this quesiton]: Outfit, Outfit_relationship and Answer. Outfit is the parent model and the others are the childs. The Outfit model looks like this:
class Outfit < ActiveRecord::Base
attr_accessible :user_id, :outfit_origin_id, :outfit_parent_id, :outfitrelationship_id #review before going live
attr_accessible :item_id, :image_size_height, :image_size_width, :image_x_coord, :image_y_coord, :zindex, :outfit_id
attr_accessible :description, :question_id, :user_id, :outfit_id
has_many :answers
has_many :outfit_relationships
accepts_nested_attributes_for :outfit_relationships, :allow_destroy => :true
accepts_nested_attributes_for :answers
Note that the 2nd and 3rd attr_accessible are to access the attributes from the other models. I'm not sure this is absolutely necessary, some articles say it is, some say it isn't, so I put it in.
I've created a multi-model form for this data which I want to publish with one button. Here is the code:
<%= form_for(#outfit) do |post_outfit| %>
<%= post_outfit.fields_for #outfit.outfit_relationships do |build| %>
<table>
<tr>
<td>X Coord <%= build.text_area :image_x_coord, :size => '1x1' %></td>
<td>Y Coord <%= build.text_area :image_y_coord, :size => '1x1' %></td>
<td>Z Index <%= build.text_area :zindex, :size => '1x1' %></td>
<td>Height <%= build.text_area :image_size_height, :size => '1x1' %></td>
<td>Weight <%= build.text_area :image_size_width, :size => '1x1' %></td>
</tr>
</table>
<% end %>
<%= post_outfit.fields_for #outfit.answers do |build| %></br></br>
<%= image_tag current_user.fbprofileimage, :size => "40x40" %></br>
<%= current_user.name %></br>
Comment: <%= build.text_area :description, :size => '10x10' %>
<% end %>
<%= post_outfit.fields_for #outfit do |build| %> </br>
origin id: <%= build.text_area :outfit_origin_id, :size => '1x1' %></br>
parent id: <%= build.text_area :outfit_parent_id, :size => '1x1' %></br>
<% end %>
<div id="ss_QID_actions_container">
<%= post_outfit.submit "Submit checked", :class => "btn btn-small btn-primary" %>
</div>
<% end %>
And here are the relevant buts of the outfit controller:
def new
#outfit = Outfit.new
#outfit.save
#outfit.answers.build
#outfit.outfit_relationships.build
respond_to do |format|
format.html # new.html.erb
format.json { render json: #outfit }
end
end
def create
#outfit = Outfit.new(params[:id])
#comment = #outfit.answers.create(params[:answer])
#outfitrelationship = #outfit.outfit_relationships.create(params[:outfit_relationship])
redirect_to outfit_path(#outfit)
So the problem is nothing gets written into my database apart from the IDs. I'm sure I'm dong something stupid here, but can't figure out why.

Ruby on Rails : Updating Multiple Models from single view/controller

Using Ruby 1.8.6 & Rails 1.2.
Models: Job, JobExtraStop:
class JobExtraStop < ActiveRecord::Base
belongs_to :job
end
class Job < ActiveRecord::Base
belongs_to :lead, :foreign_key => :id
has_one :quote, :foreign_key => :id
has_many :credit_card
has_many :job_extra_stops
end
Code from View:
Main View
<%= render_partial 'jobs/job_address_stop_fields', "stop" => stop, "index"=> index %>
Partial that is called:
<span class="jasf" id="lead_form_adrr_fields">
<% fields_for "job_extra_stop[#{index}]", stop do |extra_stop_form| %>
<tr>
<td><%= extra_stop_form.text_field :st_num, :size => 2%></td>
<td><%= extra_stop_form.text_field :st_name, :size => 15%></td>
<td><%= extra_stop_form.text_field :apt_num, :size => 2%></td>
<td><%= extra_stop_form.text_field :city, :size => 9%></td>
<td><%= extra_stop_form.text_field :zip, :size => 5%></td>
<td><%= extra_stop_form.select(:state,( [[ "Select State", "" ]] + State::NAMES)) %>
</td>
<td><%= extra_stop_form.text_field :floor, :size => 2%></td>
<td> <%= extra_stop_form.text_field :elevator, :size => 1%></td>
<td> <%= extra_stop_form.text_field :action_type, :size => 5%></td>
<td> <%= extra_stop_form.select(:location_type, ([["pick-up"],["drop-off"],["extra_stop"]] )) %></td>
<td> <%= extra_stop_form.text_field :note, :size => 10%></td>
<td>^ / v</td>
<td> <%= link_to_function "Remove", "$(this).up('.jasf').remove()" %></td>
</tr>
<% end %>
</span>
Error:
Undefined Local Variable or method index
Don't know what I am doing wrong.
You are not using the correct syntax for passing local variables to your partial, check here for the correct syntax http://api.rubyonrails.org/classes/ActionView/PartialRenderer.html

Resources