Resource route in ruby and rails - ruby-on-rails

I have
resources :blog
declared in my routes.rb file but when I try to access blog_path in a controller or a html.erb file, I get the following error:
No route matches {:controller=>"blog", :action=>"show"} missing required keys: [:id]
I have created a controller called BlogController and defined the method show with a show.html.erb file in the views directory. If I define:
match '/blog', to: 'blog#show', via: 'get' instead, then blog_path works fine.
My understanding is resources: blog is just syntactic sugar for match '/blog', to: 'blog#show', via: 'get' and a bunch of other routes. Please help.

blog_path is for generating path to a blog, so you need id or a blog object, this helper generates path like /blogs/12 to blogs#show, and blogs#show is for showing an object. blogs_path generates /blogs to blogs#index (like to all blogs).
Look at 2 Resource Routing: the Rails Default
resources :photos
GET /photos index display a list of all photos
GET /photos/new new return an HTML form for creating a new photo
POST /photos create create a new photo
GET /photos/:id show display a specific photo
GET /photos/:id/edit edit return an HTML form for editing a photo
PATCH/PUT /photos/:id update update a specific photo
DELETE /photos/:id destroy delete a specific photo
You have used resources :blog without s. It generates
blog_index GET /blog(.:format) blog#index
POST /blog(.:format) blog#create
new_blog GET /blog/new(.:format) blog#new
edit_blog GET /blog/:id/edit(.:format) blog#edit
blog GET /blog/:id(.:format) blog#show
PUT /blog/:id(.:format) blog#update
DELETE /blog/:id(.:format) blog#destroy

Make resource plural like this
resource :blogs
And make controller name blogs_controller.rb and its class name BlogsController
This is rails standard

I'm recently starting to use Rails, but I noticed that when Rails generates a controller for me, it names it with an underscore between the name and the word controller.
Something like blog_controller.rb. A few days ago I replaced one with other without the underscore and get a similar error, not sure why.

Related

when does rails looks for Index method and when for show method in controller

I'm new to Rails and I have been following a tutorial.
I have been fiddling around with routes.rb and now in total confusion about when it looks for show method and when for index method if not explicitly mentioned?
Routes are simply like regexes on steroids. They have priority in the order they are defined and match the request method, URI and any other constraints that you have added.
get '/posts', to: 'posts#index'
get '/posts/:id', to: 'posts#show'
The key difference to the routes above is that the regular expression which the path of request uri must match is different. '/posts/:id' includes a named segment which would match:
GET /posts/11
GET /posts/gobligook
But not:
GET /posts
GET /posts/1/foo
GET /posts/foo/bar
The full conventional set of CRUD verbs are:
get '/posts', to: 'posts#index' # all posts
get '/posts/new', to: 'posts#new' # form to create a post
post '/posts', to: 'posts#create' # create a post from a form submission
get '/posts/:id', to: 'posts#show' # show a single post
get '/posts/:id/edit', to: 'posts#edit' # form to edit a post
put '/posts/:id', to: 'posts#update' # for legacy compatibility
patch '/posts/:id', to: 'posts#update' # update a post from a form submission
delete '/posts/:id', to: 'posts#destroy' # delete a post
In Rails flavor REST the action is implicitly derived from the path and method.
Only the new and edit methods which are used to render forms actually explicitly add the action in the path - which is because they act on a collection or a member of a collection.
Note that the '/posts/new' route must be declared before get '/posts/:id' or the show route would match the request first (routes have priority in the order they are defined). This does not apply to get '/posts/:id/edit' since the pattern is different.
Of course typing out all those routes is really tedious so rails provides the resources macro that does this for you:
resources :posts
Both index and show are GET method, but the difference is index is collection type and show is member type. Which means index does not expect any parameter in the url, but show expects id param in the url.
EX:
Index: /posts
Show: /posts/:id
Rails chose convention over configuration. That's why the actions are not explicitly named.
Here is the complete list of the expected actions for a given controller: http://edgeguides.rubyonrails.org/routing.html#crud-verbs-and-actions

Modify routes in rails

I'm a new user of rails so it's complicated to understand how the routes.rb works! So I try to modify a route, I got a path that look like this:
user/:id/edit but i want that the id not appear in the path.
I try to use this method :
get '/users/:id/edit', to: 'users#edit', as: 'users/edit'
but it changes nothing. In my routes.rb i got :
resources :users, only: [:create, :new, :show, :edit]
Someone know how to do this? I already take a look at this guide
If you already take a look at guides, do you read about singular resources?
Sometimes, you have a resource that clients always look up without
referencing an ID. For example, you would like /profile to always show
the profile of the currently logged in user. In this case, you can use
a singular resource to map /profile (rather than /profile/:id) to the
show action:
resource :geocoder
creates six different routes in your application, all mapping to the Geocoders controller:
GET /geocoder/new geocoders#new return an HTML form for creating the geocoder
POST /geocoder geocoders#create create the new geocoder
GET /geocoder geocoders#show display the one and only geocoder resource
GET /geocoder/edit geocoders#edit return an HTML form for editing the geocoder
PATCH/PUT /geocoder geocoders#update update the one and only geocoder resource
DELETE /geocoder geocoders#destroy delete the geocoder resource
If you have taken,
resources :users
Now change this route as follows,
get '/users/edit', to: 'users#edit', as: 'users_edit'
Now in your view file where you have edit link, change the link to,
<%= link_to 'Edit', users_edit_path(:id => user.id) %>
Now this links to the edit action of users controller with an id parameter.
Now, in the users controller file,
class UsersController < ApplicationController
def edit
// params[:id] will be the ID that you sent through the view file.
#user = User.find(params[:id])
end
end
Thats it, you are done with your custom route, now the route will be users/edit instead of users/:id/edit

Dynamic path helpers rails

What are the paths that is automatically added by Rails? Let say you have a Question resource you automatically get questions_path, question_path etc. Where do I see what they resolve to and what I get?
This section might be helpful http://guides.rubyonrails.org/routing.html#specifying-a-controller-to-use
Verb Path Action Helper
GET /photos index photos_path
GET /photos/new new new_photo_path
POST /photos create photos_path
GET /photos/:id show photo_path(:id)
GET /photos/:id/edit edit edit_photo_path(:id)
PUT /photos/:id update photo_path(:id)
DELETE /photos/:id destroy photo_path(:id)
If you want to create a helper for show action you can write
photo_path(#photo.id)
where #photo is your model object. Or you can pass #photo directly if it responds to id method.
photo_path(#photo)
edit_photo_path(#photo)
You can also load rails console (in terminal) and test routes using app like so app.photo_path(1) (it will show you the route for the photo with id equals 1)
Just use:
rake routes
This will list all routes defined. The first column is relevant for you path helpers.
If you have the following in your routes file:
resources :questions
Then Rails provides the following restful routes for you:
GET /questions index list of questions
GET /questions/new new show new question form
POST /questions create create a new question
GET /questions/:id show show a specific question
GET /questions/:id/edit edit show form to edit question
PUT /questions/:id update update a specific question
DELETE /questions/:id destroy delete a specific question
You can also run rake:routes to see what is being generated.

newbie: how to get dynamic links for current_user?

Im trying to figure out how to get a dynamic link for example
/users/user1/show
/users/user1/edit
or
/profiles/1/
How would I create a route that I could insert in my views like a view_profile_path and that would include the id or username of a user?
in config/routes.rb you need to add 1 simple line:
resources :users
and get all this stuff
HTTP Verb Path action named helper
GET /users index users_path
GET /users/new new new_user_path
POST /users create users_path
GET /users/:id show user_path(:id)
GET /users/:id/edit edit edit_user_path(:id)
PUT /users/:id update user_path(:id)
DELETE /users/:id destroy user_path(:id)
You can read about rails routes in the guides
Actually, I think you need something like this in config/routes.rb
resources :users do
resources :profiles
end
You can later check your REST-ful resource routes by issuing the command:
rake routes
This way you have a more natural approach to your routes in which your users will be bound to one or more profiles, therefore you may use something like:
user_profile_path(#user)
to create an appropriate link to a user's profile.

Rails routes for article/234 and article/index

I need to setup the following urls:
/article (article#index)
/articles/1234 ( article#show with id 1234)
/articles/new (article#new)
Can I define this using:
resources :article do
???
end
If we look very closely at your question, it appears that you want the index to be at /article instead of the default Rails REST convention, which is /articles
It doesn't make any apparent sense to model your routes that way, but if that is surely what you want to do, then you could add one more route line in addition to the call to resources
resources :articles
match '/article', :to => 'articles#index'
It sounds like you're just learning rails. I'd suggest generating an article scaffold. It will set up a route like so for you:
resources :article
And you'll get RESTful routes setup for you automagically by rails
GET /articles index display a list of all articles
GET /articles/new new return an HTML form for creating a new article
POST /articles create create a new article
GET /articles/:id show display a specific article
GET /articles/:id/edit edit return an HTML form for editing an article
PUT /articles/:id update update a specific article
DELETE /articles/:id destroy delete a specific article
You can then dig into this and learn how rails does things.
Here's the official rails routing guide.
If you want those URLs and nothing else, you should put the following in routes.rb:
resources :article, :only => [:index, :show, :new]
In case you haven't stumbled upon the official Rails 3 routing guide, you should definitely take a look at it!

Resources