I'm trying to set up a many to many relationship using the has_many :through method and then use a multi-select field to setup the relationships. I'm following this tutorial:
http://asciicasts.com/episodes/185-formtastic-part-2
However for some reason the form displays a strange hex number and it changes each page refresh, I'm not exactly sure what I'm doing wrong. Below is my model/view code.
company.rb
has_many :classifications
has_many :sics, :through => :classifications
sic.rb
has_many :classifications
has_many :companies, :through => :classifications
classification.rb
belongs_to :company
belongs_to :sic
_form.html.erb
<% semantic_form_for #company do |f| %>
<% f.inputs do %>
<%= f.input :company %>
<%= f.input :sics %>
<% end %>
<%= f.buttons %>
<% end %>
Also here is the the form looks like it's showing the correct number of entries for the field but it is clearly not showing the correct name for the relationship.
SIC Multi-Select http://web9.twitpic.com/img/103694166-98ad71116216d3d1b12dd77690b36248.4bf6ca20-full.jpg
What you are seeing in the to_s method of an ActiveRecord::Base object. The hex number is the memory location which would be different each request.
After poking around the Formastic code, it looks for methods from a predefined list to find the text to display.
Make sure your Sic model has a field (or method) in this list to_label, display_name, full_name, name, title, username, login, value, to_s that returns the text you want.
Related
So I am making an edit page that can edit animals and the owners to that animal. There is a join table involved which contains what Animal belongs to what Owner.
More precisely, Say you have:
<% form_for :animal, url: animal_path(#edit_animal), method: :patch do |edit| %>
... animal labels and fields to edit go here ...
<%= edit.fields_for :owners do |owner| %>
<%= owner.label :name, "Name" %>
<%= owner.text_field :name %>
<%end%>
<%=edit.submit 'Submit'%>
<%end%>
Model Associations:
AnimalOwner < ApplicationRecord
belongs_to :animal
belongs_to :owner
Owner < ApplicationRecord
has_many :animal_owners
has_many :animals, :through => :animal_owners
Animal < ApplicationRecord
has_many :animal_owners
has_many :owners, :through => :animal_owners
Basically, I am not sure if I am doing the form correctly for join tables. I also wanted to be able to display the data currently saved in the database using :value, but what how I would do that for a join table?
<%= owner.text_field :name, :value => what_goes_here? %>
If you are doing the Rails way, you don't need to mention the value for existing database data.
<%= owner.text_field :name%>
This should populate the data to above given field. Also its always better to use a single for for both "new" and "edit" methods. And for "edit" you can also use "PUT" as method type.
To use the field_for tag, you will also need to tell your Animal model that it accepts_nested_attributes_for :owners. This will allow the nested params to be massed assigned to the Animal instance.
That title's a mouthful.
So I have something like this:
class Company < ActiveRecord::Base
has_many :company_partner_associations
has_many :partners, through: :company_partner_associations
end
class CompanyPartnerAssociation
belongs_to :company
belongs_to :partner
end
class Partner
has_many :company_partner_associations
has_many :companies, through: :company_partner_associations
end
And on a company form, i'm trying to make a list of all Partners with a checkbox next to them. If I check one, it creates association. If I uncheck it destroys.
<%= f.fields_for :company_partner_associations, Partner.all do |p| %>
<%= f.check_box :partner_id %>
<% end %>
fails because the object getting passed is a Partner, so getting undefined partner_id on Partner
I'm sure there's a nifty solution out there! Thank you!
Do this:
<%= f.collection_check_boxes :partner_ids, Partner.all, :id, :name %>
No fields_for.
This will have to be accompanied in the controller with the following params:
params.require(:company).permit(:company, :params, partner_ids: [])
This should set the partner_ids in your #company model.
With HABTM, you can declare associative data by populating the "collection_singular_ids" method; HMT has the same method appended with the has_many relation:
Although this will replace the current associated objects, it is much simpler than calling f.fields_for - especially for picking partners.
--
You can also use collection_check_boxes which is meant for this purpose :)
Not totally sure this is the problem here, but I think it could be that your controller is just not permitting the array of partner ids. So in your company_partner_params in your company controller needs to permit something like partner_attributes: [:id]. The syntax might not be perfectly correct there, but if that's something you're missing, you should look around for that.
This is what I think the form should look like:
<%= form_for #company do |f| %>
<%= f.fields_for :partners, Partner.all do |partner| %>
...
<% end %>
<% end %>
I'm trying to build a rather complex nested form in rails and am stuck.
Basically, I have three models - Applicant, DataPoint, ApplicantDataPointValue .
The user can create a new DataPoint, give it a name ("gender" etc.) select it's type ("string","integer" etc.). The type determines what column the data will eventually be saved in in the ApplicantDataPointValue table.
I then want the user, when they're creating a new Applicant, to be able to add a value for each DataPoint into the ApplicantDataPointValue table
My models look like the following:
Applicant:
class Applicant < ActiveRecord::Base
has_many :applicant_data_point_values, dependent: :destroy
has_many :data_points, :through => :applicant_data_point_values
accepts_nested_attributes_for :data_points
accepts_nested_attributes_for :applicant_data_point_values
attr_accessible :data_points_attributes, :applicant_data_point_values_attributes
end
DataPoint:
class DataPoint < ActiveRecord::Base
has_many :applicant_data_point_values
has_many :applicants, :through => :applicant_data_point_values
accepts_nested_attributes_for :applicant_data_point_values
end
ApplicantDataPointValue:
class ApplicantDataPointValue < ActiveRecord::Base
belongs_to :data_point
belongs_to :applicant
end
But I'm at a loss to what to do in the 'new' and 'create' sections of my controller or how to construct the form.
Any insight would be greatly appreciated.
From what I understand, the form for the User will also have multiple ApplicantDataPointValue fields. (but that form won't allow creating of new DataPoint fields, right?)
In the controller new action, you'll want to set up your model with associated data point values:
def new
#user = User.new
DataPoint.all.each do |data_point|
applicant_data_point_value = #user.applicant_data_point_values.build
applicant_data_point_value.data_point = data_point
end
end
And then, display a text box for each data point value.
<%= form_for #user do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<% #user.applicant_data_point_values.each do |data_point_value| %>
<%= f.fields_for :applicant_data_point_values, data_point_value do |fields| %>
<%= fields.label :value, data_point_value.data_point.type %>
<%= fields.text_field :value %>
<% end %>
<% end %>
Reference: http://railscasts.com/episodes/196-nested-model-form-part-1
I am not sure why my checkboxes for a has_many through are not saving. This is a rather complex form (An online application for a language summer program) so in addition to regular applicant information, I am collecting attributes of a LanguageBackgroundAndInterest model using a fields_for. Part of these attributes are the books that the applicant used to learn the language. The code looks like this:
<%= f.fields_for :language_background_and_interest do |builder| %>
<div class="field">
<%= hidden_field_tag "language_background_and_interest[book_ids][]" %>
<% Book.all.each do |book| %>
<br><%= check_box_tag "language_background_and_interest[book_ids][]", book.id %>
<%= book.name.humanize %>
<% end %>
</div>
<% end %>
Both the language_background_and_interest and books are joined together using a has_many_through like so:
class LanguageBackgroundAndInterest < ActiveRecord::Base
attr_accessible :book_ids
has_many :language_background_books
has_many :books, through: :language_background_books
end
class Book < ActiveRecord::Base
attr_accessible :name, :publisher
has_many :language_background_books
has_many :language_background_and_interests, through: :language_background_books
end
# Join Table
class LanguageBackgroundBook < ActiveRecord::Base
attr_accessible :language_background_and_interest_id, :book_id
belongs_to :language_background_and_interest
belongs_to :book
end
I am not sure why the books from the checkboxes don't get assigned to the appropriate background model. Any ideas?
PS: Granted, this design is rather ambiguous (Why not make books belong to an applicant?), but I currently want to put up a prototype and I am also constrained by a dubious requirement. So I need this working.
I ended up reviewing my model design and simplified it. I also switched to Simple Form to ease up working with my complex forms.
I thought that there should have been a simple solution to this, given that Rails 2.3 has this newfangled nested forms feature. Basically I want to create or update a user and assign them roles at the same time.
It seems like I'm doing everything right but I get the error WARNING: Can't mass-assign these protected attributes: roles_attrributes.
I even tried changing the view to user[permissions_attrributes][role_id] because I thought that maybe the join table was confusing Rails.
Anyways, any suggestions on how this should actually work?
Model
class User < ActiveRecord::Base
has_many :permissions
has_many :roles, :through => :permissions
accepts_nested_attributes_for :roles
accepts_nested_attributes_for :permissions
end
Excerpt from view (notice I tried and failed to get fields_for to generate what I want here, maybe that's my problem?)
<% for role in Role.all %>
<%= check_box_tag( "user[roles_attrributes][id]",role.id) %>
<%= role.rolename %>
<br/>
<% end %>
Params coming across seem to be right:
{"user"=>{"password_confirmation"=>"[FILTERED]",
"roles_attrributes"=>{"id"=>"2"}, ...
Solution A combination of me misspelling, not using attr_accessible, needing to access permissions_attributes, and the form being slightly off.
Model:
has_many :permissions, :dependent => :destroy
has_many :roles, :through => :permissions
accepts_nested_attributes_for :permissions
attr_accessible :permissions_attributes
View:
<% Role.all(:order => "rolename ASC").each_with_index do |role,idx| %>
<%= check_box_tag( "user[permissions_attributes][#{idx}][role_id]",role.id) %>
<%= role.rolename %>
<br/>
<% end %>
If you correct the spelling of attributes in your check_box_tag, it looks like it should work.
<% for role in Role.all %>
<%= check_box_tag( "user[roles_attributes][id]",role.id) %>
<%= role.rolename %>
<br/>
<% end %>
it sounds like this attribute isn't marked as safe for updating. You should be able to fix it by adding the following to your model class:
attr_accessible :roles
or possibly:
attr_accessible :roles_attributes
If you look, you may already have an attr_accessible call you can add this to. For more information this is documented here:
http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002226