Rails has many through not working - ruby-on-rails

I've got 3 models:
Vacancy
has_many :address_vacancies
has_many :addresses, through: :address_vacancies
Address
has_many :address_vacancies
has_many :vacancies, through: :address_vacancies
AddressVacancy
belongs_to :address
belongs_to :vacancy
and in my form I use the following code:
<%= f.collection_select :address_id, Address.order("CREATED_AT DESC"),:id,:title, include_blank: true %>
which throws an error: undefined method address_id', why is that and what am I doing wrong?
Edit
The full form looks like this:
<%= form_for(#vacancy) do |f| %>
<% if #vacancy.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#vacancy.errors.count, "error") %> prohibited this vacancy from being saved:</h2>
<ul>
<% #vacancy.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :address %>
<%= f.collection_select :address, Address.order("CREATED_AT DESC"),:id,:title, include_blank: true %>
</div>
<div class="field">
<%= f.label :signup_until %><br>
<%= f.date_select :signup_until %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>

This:
<div class="field">
<%= f.label :address %>
<%= f.collection_select :address, Address.order("CREATED_AT DESC"),:id,:title, include_blank: true %>
</div>
Isn't valid in the context of a Vacancy form (from the form_for #vacancy) since a Vacancy doesn't have a single address attribute. It has a collection of addresses through the has_many association. It would also be invalid to use :address_id for the same reason.
If you want to edit the various addresses for the one vacancy, you would need a subform. You'd use accepts_nested_attributes_for in the model, and fields_for in the view.
<%= form_for #vacancy do |f| %>
...
<%= f.fields_for :addresses do |af| %>
...
<!-- Here you'd render a partial or a set of inputs for this address %>
<%= af.input :street %> <!-- e.g., if there's a street attribute for Address -->
...
<% end %>
...
<% end %>

Related

How to create a view containing field of an associated model in rails?

In my project, I have an Organization model and an Address model. Here is the association beetween the models:
class Organization < ApplicationRecord
belongs_to :adresse
end
class Organization < ApplicationRecord
has_one :organization
end
I would like to know how to create a new form and include attributes from both model. For the moment, my organization/new.html.erb look like this:
<%= form_with(model: organization, local: true) do |form| %>
<% if organization.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(organization.errors.count, "error") %> prohibited this organization from being saved:</h2>
<ul>
<% organization.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :organizationName%>
<%= form.text_field :organizationName, id: :organization_organizationName %>
</div>
<div class="field">
<%= form.label :email %>
<%= form.text_field :email, id: :organization_email %>
</div>
<div class="field">
<%= form.label :website %>
<%= form.text_field :website, id: :organization_website %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
And I tried to add this to the form but address method is not recognized:
<div class="field">
<%= form.label :streetNumber %>
<%= form.text_field :organization.address.streetNumber%>
</div>
In controller, I have access to the address of the organization like:
#organization.address.streetNumber
PS: I'm new to Rails ;)
That's what fields_for is for.
<%= form_for #person do |person_form| %>
First name: <%= person_form.text_field :first_name %>
Last name : <%= person_form.text_field :last_name %>
<%= fields_for :permission, #person.permission do |permission_fields| %>
Admin? : <%= permission_fields.check_box :admin %>
<% end %>
<%= person_form.submit %>
<% end %>

Nested Resources in show template

I'm having trouble understanding nested resources. There is a Service scaffold, and there is Symptom model. I wanted to be able to add the symptom_item string to the service scaffold.
This is my current show template code:
<% if #service.symptoms.any? %>
<% #service.symptoms.each do |symptom| %>
<li><%= symptom.symptom_item %></li>
<% end %>
<% else %>
<p>
none
</p>
<% end %>
Here is my form code:
<%= form_for(#service) do |f| %>
<% if #service.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#service.errors.count, "error") %> prohibited this service from being saved:</h2>
<ul>
<% #service.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :s_text %><br>
<%= f.text_area :s_text %>
</div>
<div class="field">
<%= f.label :img_text %><br>
<%= f.text_field :img_text %>
</div>
<%= f.fields_for :symptoms do |builder| %>
<div class="field">
<%= builder.label :symptom_item %><br>
<%= builder.text_field :symptom_item, :rows => 3 %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Here is my controller code that allow the symptom_attributes:
def service_params
params.require(:service).permit(:name, :s_text, :img_text, symptom_attributes: [:id, :service_item])
end
I know the problem is in the show template. When I write something as simple as:
= #service.symptoms
it gives me something funky like this:
#<Symptom::ActiveRecord_Associations_CollectionProxy:0x000000095295c8>
Does anyone see what's wrong with my code in the show template or maybe some where else?
Here are my models just in case:
class Service < ActiveRecord::Base
has_many :symptoms
accepts_nested_attributes_for :symptoms, allow_destroy: true
end
class Symptom < ActiveRecord::Base
belongs_to :service
end
It should be symptoms_attributes instead of symptom_attributes and symptom_item instead of service_item in your strong parameters
def service_params
params.require(:service).permit(:name, :s_text, :img_text, symptoms_attributes: [:id, :symptom_item])
end

Nested forms rails field does not update

I am trying to do nested forms like mentioned here.
http://guides.rubyonrails.org/form_helpers.html#nested-forms
The goal is as follows: I have multiple colli with one checkbox which can be checked. The colli list can be deleted or modified but the checks and their information need to stay.
Model
class Colli < ActiveRecord::Base
has_one :check, foreign_key: "subcontainerid", primary_key: "colliid"
accepts_nested_attributes_for :check, allow_destroy: true
end
class Check < ActiveRecord::Base
belongs_to :colli
end
So every colli has one check. The colliid from the colli table created a link with the check table using the subcontainer id.
Controller
Within the colli controller I whitelist the check_attributes.
def colli_params
params.require(:colli).permit(:colliid, :collinaam, check_attributes: [:id, :checked])
end
Form
My form looks like this.
<%= form_for(#colli) do |f| %>
<% if #colli.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#colli.errors.count, "error") %> prohibited this colli from being saved:</h2>
<ul>
<% #colli.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.fields_for :checks do |checks_f| %>
<p>check start</p>
<div class="field">
<%= checks_f.label :checked %><br>
<%= checks_f.check_box :checked %>
</div>
<% end %>
<div class="field">
<%= f.label :colliid %><br>
<%= f.text_field :colliid %>
</div>
<div class="field">
<%= f.label :collinaam %><br>
<%= f.text_field :collinaam %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
If I do form_for :check I can't see the checkboxes. When I do form_for :checks I see a checkbox but it does not work. When clicking submit I see following error:
undefined method `checked' for nil:NilClass
<p>
<strong>Checked:</strong>
<%= #colli.check.checked %>
</p><p>
<strong>Collinaam:</strong>
<%= #colli.collinaam %>
Which means it did not get saved. Does anybody know how to fix this?
Try adding this to your form-
<%= f.fields_for :checks, #colli.check.build do |checks_f| %>
<p>check start</p>
<div class="field">
<%= checks_f.label :checked %><br>
<%= checks_f.check_box :checked %>
</div>
<% end %>

Why my textbox shows ActiveRecord_Associations_CollectionProxy in form

I'm building rails application and I use form_for to render the form. Everything works fine works fine except one text field has ActiveRecord_Associations_CollectionProxy inside the text which I'm not sure where it's coming from.
Here's my form
<%= form_for(#video, html: { class: "directUpload" }, multipart: true) do |f| %>
<% if #video.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#video.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #video.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :path %><br>
<%= f.file_field :path%>
</div>
<div class="field">
<%= f.label :tags %><br>
<%= f.text_field :tags %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And here's my Video model
class Video < ActiveRecord::Base
belongs_to :user
has_many :video_tags
has_many :tags, through: :video_tags
end
Here's the screenshot
You have multiple tags that you want show in form. Your controller could serve all tags for form where you could show them with http://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/options_from_collection_for_select for example.

Rails 4 - Nested Object Won't Save

Note: I've read a couple posts similar to this. But non of the solutions answer my question
I have two objects, Bid and Moz. When I build my Bid object, everything seems to save okay, except for the Moz objects.
Model
class Bid < ActiveRecord::Base
belongs_to :user
has_many :mozs, :dependent => :destroy
accepts_nested_attributes_for :mozs, :allow_destroy => true
end
class Moz < ActiveRecord::Base
belongs_to :bid
end
Bids::Build Controllers
class Bids::BuildController < ApplicationController
include Wicked::Wizard
steps :intro, :problems, :solutions, :pricing
def show
#bid = Bid.find(params[:bid_id])
render_wizard
end
def update
#bid = Bid.find(params[:bid_id])
#bid.attributes = build_params
4.times { #bid.mozs.build } if step == steps.second
render_wizard #bid
end
def new
#bid = Bid.new
redirect_to wizard_path(steps.first, :bid_id => #bid.id)
end
def build_params
params.require(:bid).permit(:client_name, :intro, :prob1, :prob2, :prob3, :site_feel, :search_phrase, :page_score, :total_links,
:internal_links, :external_links, :competition, :complete, :user_id, :us_company, :philosophy_1,
:philosophy_2, :website_conclusions, :is_onsite_seo, :onsite_seo, :is_ongoing_seo, :ongoing_seo,
:is_ppc, :ppc, :is_social_media, :social_media, :is_google_places, :google_places, :is_adwords_express,
:adwords_express, moz_attributes: [:url, :id, :_destroy]
)
end
private
def finish_wizard_path
root_url
end
end
solutions.html.erb
<%= form_for (#bid), url: wizard_path do |f| %>
<% if #bid.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#bid.errors.count, "error") %> prohibited this bid from being saved:</h2>
<ul>
<% #bid.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<% if #bid.is_onsite_seo? %>
<div class="field">
<%= f.label :onsite_seo %><br>
<%= f.text_area :onsite_seo %>
</div>
<% end %>
<% if #bid.is_ongoing_seo? %>
<div class="field">
<%= f.label :ongoing_seo %><br>
<%= f.text_area :onsite_seo %>
</div>
<% end %>
<div class="field">
<%= f.label :ppc %><br>
<%= f.text_area :ppc %>
</div>
<div class="field">
<%= f.label :social_media %><br>
<%= f.text_area :social_media %>
</div>
<div class="field">
<%= f.label :google_places %><br>
<%= f.text_area :google_places %>
</div>
<div class="field">
<%= f.label :adwords_express %><br>
<%= f.text_area :adwords_express %>
</div>
<%= f.fields_for :mozs do |builder| %>
<%= render partial: "moz_fields", locals: {f: builder} %>
<% end %>
<%= link_to_add_association "Add URL", f, :mozs %>
<div class="actions">
<%= f.submit %>
or <%= link_to "skip this step", next_wizard_path %>
</div>
<% end %>
_moz_fields.html.erb
<div class="field fields">
<%= f.label :url, "Comparative URL" %><br>
<%= f.text_field :url %>
<%= f.hidden_field :destroy %>
<%= link_to_function "remove", "remove_fields(this)"%>
</div>
I don't understand why they won't save. In addition, I noticed something odd -- when I don't use a partial for the nested object and use the f form builder for the #bid object (as opposed to 'builder'), I get an error no method or variable :url, but a Moz object is saved (although, not with any of the desired attributes).
My opinion that you misspelled with permit attrbibutes hash, try to change moz_attributes to mozs_attributes.
params.require(:bid).permit(..., :mozs_attributes: [:url, :id, :_destroy])
If you send the parameter _destroy: 1 through your hidden field
<%= f.hidden_field :destroy %>
you instruct Rails to destroy the child moz object, or in your case, prevent it from being created.
As for the second part of your question, if you inline the partial from this
<%= f.fields_for :mozs do |builder| %>
<%= render partial: "moz_fields", locals: {f: builder} %>
<% end %>
to this
<%= f.fields_for :mozs do |builder| %>
<div class="field fields">
<%= f.label :url, "Comparative URL" %><br>
<%= f.text_field :url %>
<%= link_to_function "remove", "remove_fields(this)"%>
</div>
<% end %>
it won't work, because the model object for the scope f is your #bid, not moz. Bids have no url attribute, hence the error.
With the input fields being created in the wrong form builder scope, you did not actually transmit any attributes for your moz object, and so it was created blank. As a side effect, this also meant not sending the _destroy parameter, so the object was saved.
Instead, inline the partial like this (I renamed builder to moz for clarity):
<%= f.fields_for :mozs do |moz| %>
<div class="field fields">
<%= moz.label :url, "Comparative URL" %><br>
<%= moz.text_field :url %>
<%= link_to_function "remove", "remove_fields(this)"%>
</div>
<% end %>

Resources