Form_for generates resource path ending with '.1' - ruby-on-rails

I have a resource called :school and when I call form_for(#school) it generates the form action:
/school.1
I'm new to all this so any clues as to why it's doing that would be much appreciated. Sleep deprived and heading for a deadline in 3 hours, arrrggg!
Thanks :)
routes.rb:
resource:school
school.rb:
<%= form_for(#school, :url => school_path) do |f| %>
<% if #school.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#school.errors.count, "error") %> prohibited this school from being saved:</h2>
<ul>
<% #school.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :address1 %><br />
<%= f.text_field :address1 %>
</div>
<div class="field">
<%= f.label :address2 %><br />
<%= f.text_field :address2 %>
</div>
<div class="field">
<%= f.label :address3 %><br />
<%= f.text_field :address3 %>
</div>
<div class="field">
<%= f.label :town %><br />
<%= f.text_field :town %>
</div>
<div class="field">
<%= f.label :county %><br />
<%= f.text_field :county %>
</div>
<div class="field">
<%= f.label :postcode %><br />
<%= f.text_field :postcode %>
</div>
<div class="field">
<%= f.label :local_authority_id %><br />
<%= f.collection_select :local_authority_id, LocalAuthority.all, :id, :name %>
</div>
<% if current_user.person.primary_user? %>
<div class="field">
<%= f.label 'Are you happy for us to send you regular updates about VRH?' %><br />
<%= f.check_box :allow_contact %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>

by using the singular resource method you are telling rails that only one of these objects exist, in your routes file I think you need to change your resource :school to...
resources :schools
If however you do want only one school then I think you will need to add the url option to form_for...
<% form_for(#school, :url => school_path) %>
Proposed solution for follow up questions...
I think what you need will be something like this...
# routes.rb
resources :users do
resources :schools
end
resources :schools
# app/controllers/schools_controller.rb
class SchoolsController < ApplicationController
def new
#user = User.find(params[:user_id])
#school = #user.build_school
end
def create
#user = User.find(params[:user_id])
#school = #user.build_school(params[:school])
if #school.save
# success...
else
# fail...
end
end
def edit
#school = School.find(params[:id])
end
def update
#school = School.find(params[:id])
if #school.update_attributes(params[:school])
# success
else
# fail
end
end
end
# app/views/schools/new.html.erb
<%= form_for([#user, #school]) do |f| %>
<!-- fields go here -->
<% end %>
# app/views/schools/edit.html.erb
<%= form_for([#user, #school]) do |f| %>
<!-- fields go here -->
<% end %>

I just had a similar issue with a singular profile resource in my routes.rb file:
resource :profile
It took me a few hours to find a solution so I decided to share it to save someone else the trouble.
I had to remove the "(.:format)" part of the route (shown when running "rake routes"), by specifying a specific format:
constraints :format => "html" do
resource :profile
end
I also had to add the :url option to form_for tags:
<% form_for(#profile, :url => profile_path) %>
and that worked.

Related

Rails - Couldn't find Student with 'id'=

I'm getting the error above when I try to create a a 'mark' for a 'student'. I can't figure out how to pass the :student_id when I create a new mark.
Routes
Rails.application.routes.draw do
resources :students do
resources :marks
end
resources :marks
root 'students#index'
Marks Controller
class MarksController < ApplicationController
def create
#student = Student.find(params[:student_id])
#mark = #student.marks.create(params[:input1, :input2, :input3, :weight1, :weight2, :weight3, :mark1, :mark2, :mark3, :final_mark].permit(:input1, :input2, :input3, :weight1, :weight2, :weight3, :mark1, :mark2, :mark3, :final_mark))
#mark.save
if #mark.save
redirect_to student_path(#student)
else
render 'new'
end
end
def new
#mark = Mark.new
end
private
def set_mark
#mark = Mark.find(params[:id])
end
end
Students Show View
<p id="notice"><%= notice %></p>
<p>
<strong>Student Number</strong>
<%= #student.StudentNumber %>
</p>
<p>
<strong>Project Title</strong>
<%= #student.ProjectTitle %>
</p>
<p>
<strong>Project PDF</strong>
<%= #student.ProjectTitle %>
</p>
<p>
<strong>Reader 1</strong>
<%= #student.Reader1 %>
</p>
<p>
<strong>Reader 2</strong>
<%= #student.Reader2 %>
</p>
<h3> <%= link_to 'Add Mark', new_student_mark_path(#student), class:"btn btn-warning"%> </h3>
<p>
<strong>Reader 3</strong>
<%= #student.Reader3 %>
</p>
<%= link_to 'Edit', edit_student_path(#student) %> |
<%= link_to 'Back', students_path %>
Marks Form
<%= form_for #mark, html: {multipart: true} do |f| %>
<% if #mark.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#mark.errors.count, "error") %> prohibited this grading from being saved:</h2>
<ul>
<% #mark.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label 'Introduction' %><br>
<%= f.text_area :input1 %>
<%= f.number_field :weight1 %>
<%= f.number_field :mark1 %>
</div>
<div class="field">
<%= f.label 'Main' %><br>
<%= f.text_area :input2 %>
<%= f.number_field :weight2 %>
<%= f.number_field :mark2 %>
</div>
<div class="field">
<%= f.label 'Conclusion' %><br>
<%= f.text_area :input3 %>
<%= f.number_field :weight3 %>
<%= f.number_field :mark3 %>
</div>
<div class="actions">
<%= f.submit class:"btn-xs btn-success"%>
</div>
<% end %>
Mark model
class Mark < ActiveRecord::Base
belongs_to :student
end
Student Model
class Student < ActiveRecord::Base
has_many :marks
has_attached_file :document
validates_attachment :document, :content_type => { :content_type => %w(application/pdf) }
end
It's probably something really stupid but if anyone could explain the problem I'd be really grateful.
Thanks
I don't suggest you using hidden fields for this purpose.
You should pass student together with mark into form_for helper and rails will generate proper url for you which will look like: /students/:student_id/marks
In this case it will be possible to extract student_id from params in your action later.
form_for [#student, #mark], html: {multipart: true} do |f|
More information about nested resources:
http://guides.rubyonrails.org/routing.html#nested-resources
http://www.informit.com/articles/article.aspx?p=1671632&seqNum=7
https://gist.github.com/jhjguxin/3074080
UPDATE:
Forgot to mention that in order to make this work you need to pass student instance into your template at new action:
def new
#student = Student.find(params[:student_id])
#mark = #student.marks.build
end

Nested routes form_for partial not working for new and edit actions - Rails 4

I used the generator to scaffold categories and questions.
my routes.rb
resources :categories do
resources :questions do
resources :choices, only: [:index]
end
end
my problem occurs when i try to add or edit a question.
here is my partial form, before you ask the relationship works ok.
<%= form_for [#question.category, #question] do |f| %>
<% if #question.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#question.errors.count, "error") %> prohibited this question from being saved:</h2>
<ul>
<% #question.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :question_type %><br>
<%= f.text_field :question_type %>
</div>
<div class="field">
<%= f.label :explanation %><br>
<%= f.text_field :explanation %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_field :description %>
</div>
<div class="field">
<%= f.label :category_id %><br>
<%= f.text_field :category_id %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
what must i change for it to work? for now i get,
undefined method `questions_path'
Try this
UPDATE
Controller
#category = Category.find(params[:category_id])
#question = #category.questions.new
_form
<%= form_for([#category, #question]) do |f| %>
Reference
You should pass parent and then build child for same for new object.
<%= form_for [#category, #category.questions.build] do |f| %>
To edit:
<%= form_for [#category, #category.questions.first_or_your_object] do |f| %>
Like this :
<% if #category.new_record? %>
<%= form_for [#category, #category.questions.build] do |f| %>
<% else %>
<%= form_for [#category, #category.questions.first_or_your_object] do |f|
<% else %>
Also add in your category model:
accepts_nested_attributes_for :questions
Add this line to your category.rb model file:
accepts_nested_attributes_for :questions
Also, in your controller:
#category = Category.find(params[:category_id])
#question = Question.new(category: #category)
and form:
<%= form_for([#category, #question]) do |f| %>

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 %>

Ruby on Rails, instead of update make new entry to model

I made a simple demo site, with an model for the patients name (name:string) and another model with the treatment (content:text). I created this "project" to learn more about the accepts_nested_attribute for tag and the fields_for tag.
Now my problem is that on the patient show page i created an nested formula for the treatment , like you can see here:
<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
<%= #patient.name %>
</p>
<ol>
<% for treatment in #patient.treatments %>
<li><%= treatment.content %></li>
<% end %>
</ol>
<%= form_for(#patient) do |f| %>
<%= f.fields_for :treatments do |builder| %>
<div class="field">
<%= builder.label :content %><br />
<%= builder.text_field :content %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<%= link_to 'Edit', edit_patient_path(#patient) %> |
<%= link_to 'Back', patients_path %>
So my problem is that in the builder.text_field :content better called the input shows up the last saved treatment from <%= builder.content %>, but i want that he does not update it instead i want to add new treatments! Hopefully somebody understands me! Thanks
I would create separate controller for creating only the treatment, eg.
# treatments_controller.rb
class TreatmentsController < ApplicationController
def create
#patient = Patient.find(params[:patient_id])
#treatment = #patient.treatments.new(params[:treatment])
if #treatment.save
redirect_to #patient
else
# handle unsuccessful treatment save
end
end
end
# routes.rb:
resources :patients do
resources :treatments, only: :create
end
# form:
<%= form_for #patient, #treatment do |f| %>
<div class="field">
<%= f.label :content %><br />
<%= f.text_field :content %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
You should also set #treatment variable in the patient#show action, like this:
#treatment = #patient.treatments.new

ActiveRecord::RecordNotFound - Product without an ID

I am trying to create a review in my app however when I am doing the following in my controller:
def create
#product = Product.find(params[:product_id])
#review = #product.reviews.create(params[:review])
redirect_to product_path(product)
end
I get Couldn't find Product without an ID. I fill the form out and some where along the lines when it does the following line #product = Product.find(params[:product_id]) it cannot seem to find the product
routes
resources :products do
resource :reviews
end
products/show.html.erb
<%= form_for(#product.reviews.build) do |f| %>
<div class="field">
<%= f.label :title %>
<br/>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :author %>
<br/>
<%= f.text_field :author %>
</div>
<div class="field">
<%= f.label :content %>
<br/>
<%= f.text_area :content %>
</div>
<div class="field">
<%= f.label :rating %>
<br/>
<%= f.number_field :rating %>
</div
<div class="actions">
<%= f.submit %>
</div>
<% end %>
change your form_for to
form_for [#product, #product.reviews.build] do |f|
this changes the action to /products/#product.id/reviews to match your nested route

Resources