Nested routes URL path and params problems in rails - ruby-on-rails

I'm simply trying to link to categories#new which is nested inside guides. I'm linking to it from the guides show page
<%= link_to "Add new category", new_guide_category_path %>
Problem is that i get the error:
No route matches {:action=>"new", :controller=>"categories", :id=>"blah"} missing required keys: [:guide_id]
It is using :id instead of :guide_id. How can i fix this so stores the param it uses :guide_id.
Or is there a different way to link to the guides/:guide_id/categories/new page and other nested resources pages
route:
resources :guides do
resources :categories, only: [:new, :create, :edit, :update]
end
Still learning rails so this might be a noob problem where you don't even use the path to link to it.

For example you have model Guide and in your controller you got variable like
#guide = Guide.where(...)
In view you need to specify id of this model and simples way to do it just to pass this variable to url helper:
<%= link_to "Add new category", new_guide_category_path(#guide) %>
And this works with multiple nested resources too. For example:
route: /foo/:foo_id/bar/:bar_id/buz/:id
Just pass all these instance of models to helper like
show_buz_bar_foo_path(#foo, #bar, #buz)
And rails will get ids of this items by itself.

Try doing this
new_guide_category_path( #guide.id )
The form_for helper can get your nesting sorted in terms of submitting data but links to other paths are a different story.

Related

Trouble installing foreign key in child records in Rails

Problem is that Rails can't find the new route after i changed how the routes for indis (stands for individuals or 'contacts') are generated.
in my routes file as a result of this statement
resources :profiles do
resources :indis
end
these routes were generated among others:
profile_indis
GET /profiles/:profile_id/indis(.:format) indis#index
POST /profiles/:profile_id/indis(.:format) indis#create
profile is the company and indis are individuals that work at the company
so i'm sitting here looking at this which is new.html.erb for new contacts.
<h1>New Contact</h1>
<%= render 'form', indi: #indi %>
<%= link_to 'Back', :back %>
I have the following line at the top of routes to avoid the rails router using the basic create route.
resources :indis, :except => [:create]
in routes
i get
No route matches [POST] "/indis"
hint: i added the :except code because the old route wasn't valid after i made the change
resources :profiles do
resources :indis
end
now when i hit create it can't find the route and i don't know what code
<%= render 'form', indi: #indi %> generates
somehow i need to fixup the new contact code so that when they hit create it routes to the new route instead of the old one (but I don't have access to the code of the form referenced in the new contact code.

How to add params id in rails link_to

I have a Job model that contains a Company_id as a foreign key. On the company show page, I want to use a link_to tag that links to the Job new page so I can create a new job with the company_id using simple_form.
<%= link_to "Create Job", new_company_job_path %>
I get this error "No route matches {:action=>"new", :controller=>"jobs", :id=>"13"}, missing required keys: [:company_id]"
This is my nested route
resources :companies do
resources :jobs, only: [:new, :create, :update, :destroy]
end
From rails routes, this is the route to the job new page
new_company_job GET /companies/:company_id/jobs/new(.:format) jobs#new
This is the simple-form in the job_new page
<%= simple_form_for (#job) do |f| %> etc
I would like know how I can include the company_id in to the link_to tag in order to use simple_form in the job new_page to create a new job.
Rails routes can take arguments; if you ever want to explicitly pass a parameter to a route you can do so just like you would pass an argument to any other method:
<%= link_to "Create Job", new_company_job_path(company_id: #company.id) %>
*note: this assumes you have defined #company somewhere on this view.
In the case of general resource routes, Rails is smart enough to insert these params in the right place. It's worth noting though that if a param is not defined on the route in routes.rb Rails will tack on these passed parameters to the end of the route as query strings.
For example, if you have a route like
get 'landing_pages/page' => '#landing_pages#page'
and you called:
<%= link_to "Go to your landing page", landing_pages_page_path(brand: 'Apple') %>
The route will become /landing_page/page?brand=Apple
For further reference: http://guides.rubyonrails.org/routing.html

"Create" route path helper

I find the resource route method quite convenient, but I totally hate that it does not create create and destroy path helpers.
I understand that writing
<% form_for(#object) %>
is supposed to automatically get the route name, and that we can play with arrays or symbols to automatically get the namespace/prefixes when they exist, but I have many routes with complicated scope definitions, and not being able to get create_xxx helpers totally annoys me
Is there no simpler solution than to write ? (I am trying to keep the default RESTful URLs while generating the helpers)
complicated_scope do
resources :my_resources, except: [:create, :destroy] do
post '', on: :collection, action: :create, as: 'create' # plus this generates a pluralized version, not very intuitive `create_complicated_scope_my_resourceS_path`
delete '', on: :member, action: :destroy, as: 'destroy'
end
end
EDIT. My example of 'somewhat complicated scope'
# Company access routes under /company/
namespace :company do
# I need a company id for all nested controllers (this is NOT a resource strictly speaking, and using resources :companies, only: [] with 'on: :collection' doesn't generate appropriate urls)
scope ':company_id' do
# Company administrators
namespace :admin do
# There is a lot of stuff they can do, not just administration
namespace :administration do
# There are several parameters grouped in different controllers
resources :some_administrations do
... # finally RESTful actions and others here
end
end
end
end
end
Resourceful routing does create create and destroy helpers, but they're implied by the type of HTTP request being made (POST and DELETE respectively) so the routing helper methods should work fine with the code you've provided.
Suppose you have the following route definition:
complicated_scope do
resources :my_resources
end
end
As a simple example, in the case of delete, you could use a named route like so:
link_to "Delete [resource]", complicated_scope_resource_path(id: #my_resource.id), method: :delete
Since the HTTP verb disambiguates the controller action this helper method routes to the destroy method of the controller.
Alternatively, you should be able to use the array syntax as well.
link_to "Delete [resource]", [:complicated_scope, #my_resource], method: :delete
The same goes for forms:
<%= form_for [:complicated_scope, #my_resource] do |f| %>
If #my_resource is a new object (not persisted), as in the case of a new action this would be equivalent to sending a post request to /complicated_scope/my_resource with the form params going in the body of the request.
Alternatively if #my_resource exists, as in the case of an edit action, the above would be equivalent to sending a PUT/PATCH which will route to the update action of your controller with /complicated_scope/my_resource/:id/update.

No route matches [GET] on a resource declared in the routes file

When I click a link generated by the following code in a view:
<%= link_to "Colleague", collaborators_path(member2_id: user.id,), :method => :post %>
I get the following error message:
No route matches [GET] "/collaborators"
However, I have the following line in my routes file:
resources :collaborators, only: [:create, :destroy]
And I have the following definition written out in the collaborators_controller:
#collaboration = current_user.collaborations.build(:member2_id => params[:member2_id])
if #collaboration.save
flash[:notice] = "Added collaborator."
redirect_to root_url
else
flash[:error] = "Unable to add collaborator."
redirect_to root_url
end
So shouldn't the path for creating a collaboration be found by the router?
It's because you are using only: [:create, :destroy]. You'd need to include :index in that array for there to be a GET /collaborators route. See the Rails guide on Routing
And in order to use links with :method => :post, you'll need to be using Rails 3's unobtrusive Javascript feature.
Looks like the :method => :post is being ignored because you are using a link. POST method is commonly used when submiting forms. Actually, POST method is used to send data from the browser to the server in order to add new records to a database. See the Wikipedia article on HTTP methods for more info, and also Rails Guides on Routing.
If what you are trying to do is adding someone as a Colleague (just like Twitter's "follow" action, or Facebook's "Like") then you need to create an small form with the user's id in a hidden field.
TL;DR: use a form to create a relation, for a link won't work :)

Rails: restful resource routing with action_controller_path

I am putting a randomize def in my controller and would like to access it with a restful route. The route should be accessed with the following:
<%= link_to "Randomize", random_reader_path %>
But I cannot figure out how to get this route to appear in rake routes or configure it correctly in my routes.rb file.
The random method will do the same thing as index only provide a random page content #variable
Currently I have my reader Controller as
resources :reader
in my routes.rb
Add more RESTful actions!
resources :reader do
get 'random', on: :collection
end
The route will be random_readers_path, though.

Resources