Namespace nested resources - ruby-on-rails

I have the following routes on my project:
namespace :teacher do
resources job_applications do
resources :job_application_addresses
end
My form has the folling code
<%= simple_form_for [:teacher, #job_application_address] do |form|
<% end %>
And my controller has the following:
def new
#job_application_address = JobApplicationAddress.new
end
def create
#job_application_address = JobApplicationAddress.new(job_application_address_params)
#job_application_address.job_application = #job_application
if #job_application_address.save
flash[:success] = 'Successfully created'
end
end
Finally I'm getting this error:
undefined method `teacher_job_application_addresses_path' for #<#<Class:0x00007fda0c4191d0>:0x00007fda143d1af8>
Did you mean? teacher_job_application_path
teacher_job_applications_path
Extracted source (around line #3):
<%= simple_form_for [:teacher, #job_application_address] do |form| %>
This are my routes for this view:
teacher_job_application_job_application_addresses GET /teacher/job_applications/:job_application_id/job_application_addresses(.:format) teacher/job_application_addresses#index
POST /teacher/job_applications/:job_application_id/job_application_addresses(.:format) teacher/job_application_addresses#create
new_teacher_job_application_job_application_address GET /teacher/job_applications/:job_application_id/job_application_addresses/new(.:format) teacher/job_application_addresses#new
edit_teacher_job_application_job_application_address GET /teacher/job_applications/:job_application_id/job_application_addresses/:id/edit(.:format) teacher/job_application_addresses#edit
teacher_job_application_job_application_address GET /teacher/job_applications/:job_application_id/job_application_addresses/:id(.:format) teacher/job_application_addresses#show
PATCH /teacher/job_applications/:job_application_id/job_application_addresses/:id(.:format) teacher/job_application_addresses#update
PUT /teacher/job_applications/:job_application_id/job_application_addresses/:id(.:format) teacher/job_application_addresses#update
DELETE /teacher/job_applications/:job_application_id/job_application_addresses/:id(.:format) teacher/job_application_addresses#destroy
What should I do? I'll apprecciate your help.

Your job_application_addresses is nested resource of job_application. But i dont see it in your form.
You can do it by 2 ways:
Your can add job_application object in the simple_form_for url builder like this
<%= simple_form_for [:teacher, #job_application, #job_application_address] do |form|
<% end %>
You can add an url option in the form
<%= simple_form_for [#job_application, #job_application_address], url: teacher_job_application_job_application_addresses_path do |form|
<% end %>`
In both cases you need to have #job_application object in new action in controller.
Hope it helps

Related

Ruby on Rails - Render new on show

I have nested resources and I'm trying to show the new layout for the nested resource on the show of the parent.
resources :discussions do
resources :comments
end
discussions\show.html.erb
<%= #discussion.title %>
<%= ... render the discussion %>
<%= ... render the existing comments %>
<% render 'comments/new' %> <--- trying something like this
comments/new throws an error because it's missing the partial.
comments/form works to get past that, but throws an error saying my #comment is nil.
comments/_form.html.erb
undefined method discussion for nil:NilClass
<%= bootstrap_form_for([ #comment.discussion, #comment] ) do |f| %>
Do I have to change something in the controller, or am I going about this incorrectly?
Thanks for your help!
try this
discussions\show.html.erb
<%= render 'comments/form', comment: #discussion.comments.build %>
comments/_form.html.erb
<%= bootstrap_form_for([ comment.discussion, comment] ) do |f| %>
Hope this will work.

undefined method `new' for Driver:Module Ruby

So, the set up is very simple. In my controller I have
class DriverController < ApplicationController
def index
end
def new
#driver = Driver.new
end
end
And the new.html.erb is
<h1>Driver#new</h1>
<%= form_for #driver do |f| %>
<%= f.submit %>
<% end %>
When I try to acess that new page it says: "undefined method `new' for Driver:Module"
When I change def new in my controller to def create for an example, this error goes away and it says that First argument in form cannot contain nil or be empty. What is the problem?
<h1>Driver#new</h1>
<%= form_for :driver, :url: drivers_path do |f| %>
<%= f.submit %>
<% end %>
In routes.rb
resourse :drivers
And further I would suggested you yo Visit Guide Ruby on Rails the-first-form
Hope this help you !!!
I don't know where the problem was, but I just did everything all over again, and it worked.

The path was messed up after nested routing

I really have no clue why it happen.
this is my routes
resources :users do
resources :bookmarks
end
Controller
# bookmarks_controller
def edit
# this returns perfectly data in the edit view
#bookmark = current_user.bookmarks.find(params[:id])
end
This is the view
<%= form_for #bookmark do |b| %>
<% end %>
Since everything messed up when I nested the bookmarks resources inside users it causes the error
undefined method `bookmark_path'
Then I change the form to
<%= form_for user_bookmark_path(current_user, #bookmark) do |b| %>
The error is gone but there is no such data in the text field form, and the form action is /users/[user_id]/bookmarks/[bookmark_id]/edit
rake routes info
user_bookmarks GET /users/:user_id/bookmarks(.:format) bookmarks#index
POST /users/:user_id/bookmarks(.:format) bookmarks#create
new_user_bookmark GET /users/:user_id/bookmarks/new(.:format) bookmarks#new
edit_user_bookmark GET /users/:user_id/bookmarks/:id/edit(.:format) bookmarks#edit
user_bookmark GET /users/:user_id/bookmarks/:id(.:format) bookmarks#show
PUT /users/:user_id/bookmarks/:id(.:format) bookmarks#update
DELETE /users/:user_id/bookmarks/:id(.:format) bookmarks#destroy
Any idea how to fix it ? Thanks
Try something like:
<%= form_for [current_user, #bookmark] do |b| %>
<% end %>

Rails, STI and 'becomes' - f.object.errors not showing in view

My question is: why doesn't .becomes pass errors over to the new object? Isn't this the expected behaviour?
I have the following single table inheritance classes in a rails app:
class Document < ActiveRecord::Base
validates :title, :presence => true
end
class LegalDocument < Document
end
class MarketingDocument < Document
end
I want to use the same controller and set of views to edit both LegalDocuments and MarketingDocuments, so I am using DocumentsController < ApplicationController with the following edit and update actions:
def edit
#document = Document.find(params[:id])
end
def update
#document = Document.find(params[:id])
if #document.update_attributes(params[:document])
redirect_to documents_path, :notice => "#{t(:Document)} was successfully updated."
else
render :action => "edit"
end
end
and the following in my edit view:
<%= form_for #document.becomes(Document) do |f| %>
<% if f.object.errors.present? %>
<div class="error_message">
<h4><%= pluralize(f.object.errors.count, 'error') %> occurred</h4>
</div>
<% end %>
<div>
<%= f.label :title %>
<%= f.text_field :title, :class => "inputText" %>
</div>
<%= f.submit %>
<% end %>
If title is filled in, the documents update correctly.
If title is left blank, I am returned to the edit view BUT the error is not shown.
From debugging, I know it's not showing because f.object.errors is nil. However, from debugging, I also know #document.errors is NOT nil, as expected.
My question is: why doesn't .becomes pass errors over to the new object? Isn't this the expected behaviour?
Yes, I noticed that too.
Just change f.object.errors.present? by #document.errors.any? ( or #document.errors.present?).
If you really want to use f.object.errors.present?, write becomes in the controller (both edit and update actions) instead of in the view:
def edit
#document = Document.find(params[:id]).becomes(Document)
end
def update
#document = Document.find(params[:id]).becomes(Document)
# ....
end
And then in the view:
<%= form_for #document do |f| %>
<% if f.object.errors.present? %>
<p>Errrorsss....</p>
<% end %>
#.....
It happens because the url of the form is build according to #document.becomes(Document) (=> PUT document/:id) but #document is created according to its "true" class (a subclass of Document).
If you have pry (highly recommended), write:
def update
#document = Document.find(params[:id])
binding.pry
# ...
end
And then inspect #document. You will see that #document is an instance of LegalDocument or the other subclass even though you called #document.becomes(Document) in your form.
So in final f.object and #document are not the same.
This explains why you can't see f.object.errors when validation fails.
Edit
The 'best way' to deal with STI and form is NOT to use becomes:
<= form_for #document, url: { controller: 'documents', action: 'update' }, as: :document do |f| %>
<% if #document.errors.any? %>
# or if f.object.errors.any?
# handle validation errors
<% end %>
# your form...
<% end %>
This enables you:
to have only one controller (documents_controller)
to have only one resource (resources :documents)
it keeps trace of your subclasses: a LegalDocument will be store as a LegalDocument. No conversion: You don't have to store its class before the conversion to Document and then reassign it later.
Plus, your subclass is available in your form, so you can (let's imagine) build a select for the type.
your controller looks cleaner: #document = Document.find params[:id] nothing more. Just like a classic resource.
If you want to share this form across different actions(typically edit and new):
<%= form_for #document, url: { controller: 'media_files', action: action }, as: :media_file do |f| %>%>
# edit.html.erb
<%= render 'form', action: 'update' %>
# new.html.erb
<%= render 'form', action: 'create' %>
Pretty much it is a bug and it should work as you initially expected. The following patch to address the issue looks like it was pulled back in October
https://github.com/lazyatom/rails/commit/73cb0f98289923c8fa0287bf1cc8857664078d43

Ruby on Rails -Problem using subdirectories

I have tried to set up a separate section of my app using a subdirectory called controlpanel to manage various parts of the site.
I've set up the namespace in my routes.rb
map.namespace :controlpanel do |submap|
submap.resources :pages
# other controllers
end
And placed the controller and views into the relevant subdirectories.
Controlpanel::PagesController
def new
#page = Page.new
end
def create
if #page = Page.create_with_author(current_user, params[:page])
flash[:notice] = 'Page was successfully created.'
redirect_to ([:controlpanel, #page])
else
render :action => 'new'
end
end
Using this mixed in class method
def create_with_author(author, params)
created = new(params)
created.author = author
if created.save
created
end
end
And the view (controlpanel/pages/new.html.erb renders a partial called _form
<%= render :partial => 'form' %>
Which is as follows:
<% semantic_form_for([:controlpanel, #page]) do |form| %>
<% form.inputs do %>
<%= form.input :title %>
<%= form.input :body %>
<% end %>
<%= form.buttons %>
<% end %>
If I fill in the form correctly, it works as expected, redirecting me to the new page, however, if I leave fields blank, violating the validation constraints, I get the following error:
RuntimeError in Controlpanel/pages#create
Showing app/views/controlpanel/pages/_form.html.erb where line #1 raised:
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
Can anyone see what is going wrong?
I'm using the formtastic plugin to create the form, but it still happens if I use a regular form.
Any advice greatly appreciated.
Thanks.
Given that the create action is called and new is rendered, Page.create must evaluate to nil.
You probably want to pass params[:page] to create.

Resources