Why won't my has_one relationship work - ruby-on-rails

I have a few models Score ScoreAuthority ScoreColor and ScoreType. Score has_one authority, color, and type. Authority, color, and type each belong_to score. I am having trouble creating the form for Score.
I want users to create this relationship from Scores and everyone seems to handle only the reverse scenario creating from authorities, colors, types forms. What I mean specifically is for example:
Authorities
- foo
- bar
Colors
- red
- blue
I want the use to go into Score, chose to create a new score and then select foo from the drop down list, blue from the colors list, enter a score and submit. Authorities, colors and types will not change much and it would make any sense for the user to select Score from each of those.
When I currently do that I get the following error:
ScoreAuthority(#2248480380) expected, got String(#2155957040)
score/_form.html.erb
<%= form_for #score, :html => { :class => 'form-horizontal' } do |f| %>
<div class="control-group">
<%= f.label :product_id, "Products", :class => 'control-label' %>
<div class="controls">
<%= f.collection_select(:product_id, Product.order(:name), :id, :name) %>
</div>
</div>
<div class="control-group">
<%= f.label :score_authority, "Score Authority", :class => 'control-label' %>
<div class="controls">
<%= f.collection_select :score_authority, ScoreAuthority.order(:name), :id, :name, {}, {:class=>'chosen'} %>
</div>
</div>
<div class="control-group">
<%= f.label :score_type, "Score Types", :class => 'control-label' %>
<div class="controls">
<%#= f.collection_select(:score_type, ScoreType.order(:name), :id, :name) %>
<%= f.collection_select :score_type, ScoreType.order(:name), :id, :name, {}, {:class=>'chosen'} %>
</div>
</div>
<div class="control-group">
<%= f.label :score_color, "Score Types", :class => 'control-label' %>
<div class="controls">
<%= f.collection_select :score_color, ScoreColor.order(:name), :id, :name, {}, {:class=>'chosen'} %>
</div>
</div>
<div class="control-group">
<%= f.label :notation, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :notation, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :value, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :value, :class => 'text_field' %>
</div>
</div>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
scores_path, :class => 'btn' %>
</div>
<% end %>
score_authorities, score_colors, score_types tables all have score_id as a column. Each of these models also has belongs_to :score.
The score model
has_one :score_authority
has_one :score_type
has_one :score_color
Not sure what I am doing wrong here, any help would be appreciated. Thanks!

you should use :score_authority_id instead of :score_authority in form
<%= f.collection_select :score_authority_id, ScoreAuthority.order(:name), :id, :name, {}, {:class=>'chosen'} %>
<%= f.collection_select :score_color_id, ScoreColor.order(:name), :id, :name, {}, {:class=>'chosen'} %>
<%= f.collection_select :score_color_id, ScoreColor.order(:name), :id, :name, {}, {:class=>'chosen'} %>
see this How do I create the view for the has_one association? for more detail
or you can try
class Score
has_one :score_authority
accepts_nested_attributes_for :score_authority
end
<%= form_for #score ... do |f| %>
...
<%= f.fields_for :score_authority do |b| %>
<%= b.collection_select :id, ScoreAuthority.all, :id, :name %>
...
<% end %>
...
<% end %>

Related

How to set custom field name ?

I am trying to use a collection_select for state just to filter cities, but I don't want to save the state_id in db. My "college" model has only city and college field. That's why it's throwing while instantiating :state_id I believe, I am new to rails. I am not able to figure it out. :(
<%= form_for #college do |f| %>
<div class="form-group">
<%= f.label "Select city"%>
<%= f.collection_select(:state_id, State.all, :id, :state, {}, {class: "form-control"})%>
</div><br>
<div class="form-group">
<%= f.label :city_id, "Select city"%>
<%= f.collection_select(:city_id, City.all, :id, :city, {}, {class: "form-control"})%>
</div><br>
<div class="form-group">
<%= f.label :college, "college Name"%>
<%= f.text_field :college, class: "form-control", placeholder: "Enter city name", required: true%>
<br>
</div>
<div class="form-group">
<%= f.submit class: "btn btn-primary"%>
</div>
<% end %>
just define state_id attribute accessor in your college.rb model :
attr_accessor :state_id
inside your model you should define state_id as attr_accessor like :-
class College
attr_accessor :state_id
end

Triple nested attributes in ruby. Not sure if I am setting them up right or if they can be done. Ruby

I have a triple nested attributes that I am trying to capture all the information for in one form. In short I have an event that has many event_locations which have many event_dates which have many event_roles. I have the form in my event new. I think the issues is in my events model and I need to say that there is going other "accepts_nested_attributes_for" for event_dates and event_roles because right now in the event_params I do get the event and event_location information.
events controller
def create
#event = Event.new(event_params)
if #event.save
redirect_to #event, notice: 'Event was successfully created.'
else
render :new
end
end
private
def event_params
params.require(:event).permit(:name, :event_details, event_locations_attributes: [:label, :address, :zip, :state, :country, :notes], event_dates_attributes: [:event_date, :start_time, :end_time], event_roles_attributes: [:type, :hourly_rate, :quantity])
end
event.rb
class Event < ActiveRecord::Base
has_many :event_locations, :dependent => :destroy
has_many :event_dates, through: :event_locations
belongs_to :agency
accepts_nested_attributes_for :event_locations, :allow_destroy => true
end
event new
<h3> New Event </h3>
<%= form_for #event do |f| %>
<%= f.text_field :name, :required => true, placeholder: "Name", :maxlength => 200, class: "form-control title_input_field" %><br>
<%= f.text_area :event_details, :required => true, placeholder: "What are some of the event details", size: "100x10", class: "input_field2" %> <br>
<h3> Event Locations </h3>
<%= f.fields_for :event_locations do |builder| %>
<%= render "location_fields", :f => builder %>
<% end %>
<%= f.submit "Create!", :class => 'submit_button' %>
<% end %>
_location_fields.html.erb
<p>
<div class="row">
<div class="col-sm-5">
<%= f.text_field :label, :required => true, placeholder: "Label", :maxlength => 1000, class: "form-control title_input_field" %><br>
</div>
<div class="col-sm-5">
<%= f.text_area :notes, :required => true, placeholder: "Notes", :maxlength => 200, class: "form-control title_input_field" %><br>
</div>
</div>
<div class="row">
<div class="col-sm-5">
<%= f.text_field :address, :required => true, placeholder: "Address", :maxlength => 200, class: "form-control title_input_field" %><br>
</div>
<div class="col-sm-2">
<%= f.text_field :state, :required => true, placeholder: "State / Provience", :maxlength => 200, class: "form-control title_input_field" %><br>
</div>
<div class="col-sm-2">
<%= f.text_field :country, :required => true, placeholder: "Country", :maxlength => 200, class: "form-control title_input_field" %><br>
</div>
<div class="col-sm-2">
<%= f.text_field :zip, :required => true, placeholder: "Zip Code", :maxlength => 200, class: "form-control title_input_field" %><br>
</div>
</div>
<%= f.check_box :_destroy %>
<%= f.label :_destroy, "Remove Location" %>
</p>
<%= f.fields_for :event_date do |builder| %>
<%= render "event_date_fields", :f => builder %>
<% end %>
--
_event_date_fields.html.erb
<p>
<h3> Event Date </h3>
<div class="row">
<div class="col-sm-3">
<div class="form-group">
<div class='input-group date' id='datetimepicker1' />
<%= f.text_field :event_date, placeholder: "Select Event Date", class: "form-control", type:'text' %>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div> <!-- date -->
</div> <!-- form-group -->
</div>
<div id="datepairExample">
<div class="col-sm-4">
<%= f.text_field :start_time, placeholder: "Start Time", class: 'time start form-control' %>
</div>
<div class="col-sm-1">to</div>
<div class="col-sm-4">
<%= f.text_field :end_time, placeholder: "End Time", class: 'time end form-control' %>
</div>
</div>
</div>
<%= f.check_box :_destroy %>
<%= f.label :_destroy, "Remove Date" %>
</p>
<%= f.fields_for :event_role do |builder| %>
<%= render "event_role_fields", :f => builder %>
<% end %>
In short, you need to allow all the models to allow nested attributes for their direct associations, so:
class Event < ActiveRecord::Base
has_many :event_locations, :dependent => :destroy
accepts_nested_attributes_for :event_locations, :allow_destroy => true
class EventLocation < ActiveRecord::Base
has_one :event_date
accepts_nested_attributes_for :event_date, allow_destroy: true
class EventDate < ActiveRecord::Base
has_one :event_role
accepts_nested_attributes_for :event_role, allow_destroy: true
Then your strong params should look like this:
params.require(:event).permit(:name, :event_details,
event_locations_attributes: [:label, :address, :zip, :state, :country, :notes,
event_date_attributes: [:event_date, :start_time, :end_time,
event_role_attributes: [:type, :hourly_rate, :quantity]]])

Rails form_for select default option

I have a form_for select where the options are being defined from within the model. I am trying to get it to display a placeholder option but cannot figure out how to.
The Model:
class Factoid < ActiveRecord::Base
attr_accessible :description, :name, :title
validates_presence_of :description, :name, :title
validates_uniqueness_of :title
NAMES = "Angela", "Geordie", "Jared", "Jennifer", "Kevin", "Matthew", "Oscar", "Owen", "Regina", "Todd", "Vaibhavi", "Zack"
UNRANSACKABLE_ATTRIBUTES = ["id", "updated_at"]
def self.ransackable_attributes auth_object = nil
(column_names - UNRANSACKABLE_ATTRIBUTES) + _ransackers.keys
end
end
The Form:
<%= form_for #factoid, :html => { :class => 'form-horizontal' } do |f| %>
<div class="control-group">
<%= f.label :title, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :title, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :description, :class => 'control-label' %>
<div class="controls">
<%= f.text_area :description, :class => 'text_area' %>
</div>
</div>
<div class="control-group">
<%= f.label :name, :class => 'control-label' %>
<div class="controls">
<%= f.select :name, :collection => Factoid::NAMES %>
</div>
</div>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
factoids_path, :class => 'btn' %>
</div>
<% end %>
The second issue is that the dropdown menu is displaying the word "collection" at the top of it (See screenshot below). How do I get read of that. Ideally I want to have a dropdown menu with a placeholder of "Names" that is also displayed at the top when the dropdown menu is opened.
For your text field try something like:
<%= f.text_field :title, :class => 'text_field', value: 'my_default_value' %>
for your select try:
<%= f.select :name, Factoid::NAMES %>
See the docs for select and the rails guide for typical usage (I think the method I've shown you will not work upon submitting the form, see the guides linked for explanation, I'm not sure though).

Mass-assign protected attributes (Nested-form) Ruby/Rails

I'm trying to create a nested form but i got this error when trying to assign the parameters. I read a bunch of similar posts but cant figure out the problem. What could be wrong?
Can't mass-assign protected attributes: detalle_poliza
My models:
poliza_contable.rb
class PolizaContable < ActiveRecord::Base
has_many :detalle_polizas
accepts_nested_attributes_for :detalle_polizas
attr_accessible :concepto_poliza, :estatus, :fecha_aplicacion, :fecha_poliza, :no_poliza, :tipo, :tota_de_cargos, :total_de_abonos
end
detalle_poliza.rb
class DetallePoliza < ActiveRecord::Base
belongs_to :cuenta_contable
belongs_to :poliza_contable
attr_accessible :abono, :cargo,:cuenta_contable_id, :poliza_contable_id, :user_id, :id, :updated_at, :created_at
end
My form:
<%= form_for #poliza_contable, :html => { :class => 'form-horizontal' } do |f| %>
## OTHER FIELDS
<%= f.fields_for :detalle_poliza_attributes do |builder| %>
<% render :partial => "detalle_polizas/form", :locals => { :f => builder } %>
<% end %>
<% end %>
Rendered form:
<div class="control-group">
<%= f.label :cargo, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :cargo, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :abono, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :abono, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :poliza_contable_id, :class => 'control-label' %>
<div class="controls">
<%= f.number_field :poliza_contable_id, :class => 'number_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :cuenta_contable_id, :class => 'control-label' %>
<div class="controls">
<%= f.number_field :cuenta_contable_id, :class => 'number_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :user_id, :class => 'control-label' %>
<div class="controls">
<%= f.number_field :user_id, :class => 'number_field' %>
</div>
</div>
Request Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"mI23Nnj4oPX+IW3mCvvIV7Auij+pjX/a7bl/HsudEW8=",
"poliza_contable"=>{"tipo"=>"Diario",
"concepto_poliza"=>"",
"fecha_poliza"=>"2012-06-25",
"detalle_poliza"=>{"cargo"=>"34",
"abono"=>"34",
"poliza_contable_id"=>"34",
"cuenta_contable_id"=>"34",
"user_id"=>"1"}}
"commit"=>"Create Poliza contable"}`
I'll appreciate any comment to fix it.
With according to railscast 196 Nested Model Form Part 1 you need to allow DetallePoliza attributes to be saved with parent. To achieve this goal just add attr_accessible :detalle_polizas_attributes to PolizaContable model:
poliza_contable.rb
class PolizaContable < ActiveRecord::Base
has_many :detalle_polizas
accepts_nested_attributes_for :detalle_polizas
attr_accessible :concepto_poliza, :estatus, :fecha_aplicacion, :fecha_poliza, :no_poliza, :tipo, :tota_de_cargos, :total_de_abonos, :detalle_polizas_attributes
end
Just making some research, finally found the nestes_form gem
Its a very straight forward implementation!
Hope it helps someone.

Sqlite3 DB is only storing the ID and not anything else

ive got a problem with my database in that it only seems to be storing the id of new entries and displaying those in my form instead of the :name attribute that im asking for. If I view the entry either using my form or via a sqlite3 browser. Only the ID is showing.
Here's my migration file..
class CreateClients < ActiveRecord::Migration
def change
create_table :clients do |t|
t.string :name
t.string :detail
t.string :more_detail
t.string :more_details
t.timestamps
end
end
end
My form..
<%= form_for #client, :html => { :class => 'form-horizontal' } do |f| %>
<div class="control-group">
<%= f.label :name, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :name, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :detail, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :detail, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :more_detail, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :more_detail, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :more_details, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :more_details, :class => 'text_field' %>
</div>
</div>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
clients_path, :class => 'btn' %>
</div>
<% end %>
And my view..
...
<% #client.each do |client| %>
<tr>
<td><%= link_to client.name, client_path(client) %></td>
<td>
...
Instead of showing the name (eg foo) and then a link to that clients details. It's showing me /clients/3 and when I click on it, it's taking me to a page with empty name annd detail's fields even though they were specified when saving the entry.
If I use a sqlite3 browser. I can see the entrys have been saved but each has a null value for all columns except ID.
I think I know what your problem is. The latest Rails version has attribute protection from mass assignment by default, so you need to specify which attributes you want to be accessible from outside the model like this:
class Client < ActiveRecord::Base
attr_accessible :name, :detail, :more_detail
end
Read this section of the security guide.
P.S.: Did the console throw any errors when you are creating a new record?

Resources