I'm fairly new to Rails so bear with me.
I have a post resource and a comment resource. I can access the following routes:
domain.com/post/new
Or
domain.com/post/2
Or
domain.com/post/2/edit
I can access the exact same routes for comments too.
The question is, how can I make a route for adding a comment to a post directly? Like such:
domain.com/post/2/comment/new
This route should just render the existing comment form but already have the post ID. Is there an easy way to achieve this?
You want to read up on has_many associations, nested routes and accepts_nested_attributes_for. Your route will be
resources :posts do
resources :comments
end
Related
I have a blog with root
root 'posts#index'
And works best with example.com/ to example.com/posts
But what I want is something like this:
example.com/blog/posts/1.
I've tried creating blog Controller and add
resources :blog do
resources :posts
end
But this is making my routes to blog/:id/posts/:id
If you don't have the relationship between the post and the blog as you mentioned, rails gives you the freedom to declare routes as our own.
so, to make the route example.com/posts/1 to, example.com/blog/posts/1, just add a custom route at the last.
get '/blog/posts/:id', to: :show, controller: 'posts'
what this does is over rides the previous route and make this route final.
Now type rake routes and it will give the last route for you as,
GET /blog/posts/:id(.:format) posts#show
Now you can access using,
example.com/blog/posts/1
Reference for rails routing
Just to expand upon #Sravan answer. If you have multiple routes that will start with /blog/ you might want to check Rails guide on routing.
You can add something along the lines of
scope '/blog' do
resources :posts
resources :users
resources :images
end
Which will create corresponding routes under /blog/.
namespace :blog do
resources :posts
resources :users
resources :images
end
And your controller with namespace will look like this: Blog::PostsController
I am trying to setup a rails blog at the "website.com/blog" url
I already have my models and controller setup to work to where going to
website.com/posts
Gives me all my posts and going to
website.com/posts/1/
Shows me that post, etc, etc. What I want to happen is that when I go to
website.com/blog/
I should see the posts index (and the original URL should no longer work). Similarly I want to go to
website.com/blog/posts/1/
To see that post and so on and so forth.
Right now this is my routes file:
Rails.application.routes.draw do
namespace :blog do
resources :posts do
resources :comments
end
end
get "/blog", to: "posts#index"
end
When I go to "/blog/" I get a Routing Error saying "uninitialized constant Blog". Do I need to create a blog model and controller and migrate to complete this? I'd rather not since it's really just running the posts requests from that new URL. Am I going about this the wrong way?
I ended up finding the answer to my own question here: http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing
Using this seems to work just fine:
scope '/blog' do
resources :posts do
resources :comments
end
end
get "/blog", to: "posts#index"
The answer ended up being found here: http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing
As usual the solution was incredibly simple and made me feel like an idiot for not knowing what to do immediately:
scope '/blog' do
resources :posts do
resources :comments
end
end
get "/blog", to: "posts#index"
I am new to learning Rails and have just encountered nested routes. The example I am looking at involves blog articles and comments. I am trying to undestand what the benefit of nested routes are in Rails.
As far as I can tell all the information contained in a nested route for a comment such as /articles/:article_id/comments/:id(.:format) is all contained in the comment object itself so it does not communicating additional information to the Action.
Why not just have unnested routes such as /comments/:id(.:format)?
There is obviously a very good reason for using nested routes but I havent been able to work it out. The only benefit I can see so far is it gives a better illustration of the relation between articles and comments when reading the URL but all this information is contained in the comment object anyway.
Could someone explain this?
In your model you would have setup this association
class Article< ActiveRecord::Base
has_many :comments
end
class Comment< ActiveRecord::Base
belongs_to :article
end
So each comment is associated with an article and you need some logic to find corresponding article for a comment
This is where nested route comes in and lets you find article for that comment in your controller action. If you look at that route again
/articles/:article_id/comments/:id(.:format)
This is the comment controllers show action and this route allows you to find both article and your comment inside show action
def show
#article = Article.find(params[:article_id])
#comment = Comment.find(params[:id])
# if you are not using nested routes then you can find out associated article by
#article = #comment.article # but you'll have to query your database to get it which you can simply find if you are using nested route
end
More than the show action(where you can use some other logic to find article associated with that comment) you need nested route for your new action where you have to find that article and then build a comment for that article by something like
def new
#article = Article.new
#comment = #article.comments.build
end
As #August pointed out you can separate out actions for which you want your route to be nested by using shallow nesting, you can do:
resources :articles do
resources :comments, shallow: true
end
Checkout nested routes for more information
Correct, having the article in the path is redundant when dealing with a preexisting comment (because you can get the article from the comment). To avoid this, you can use shallow routes:
#routes.rb
resources :articles, shallow: true do
resources :comments
end
# or use a `shallow` block
shallow do
resources :articles
resources :comments
end
end
I am learning rails and routing has me wanting to jump off the roof.
I am confused on how to go about routing my activation at this point.
I have the following currently in my user routing:
resources :users, only: [:new,:create,:show]. Now I want a route to Users#activate like this www.app.com/users/activate/:a_long_token. Now I know I can just simply do a match '/activate/:auth_token', to: 'users#activate but I am not sure whether this is convention. I was reading this guide on user authentication but it seems its routing is rails 2. Can I do something to add the route mentioned above by simply adding something to the resource itself. By that I mean doing something like (I know this won't work)
resource :users do
member do
get :activate
end
end
rails3 guide
http://guides.rubyonrails.org/
http://guides.rubyonrails.org/routing.html
resources :users do
collection do
get "activate/:a_long_token" => "users#activate", as: :activate
end
end
rake routes outputs this
activate_users GET /users/activate/:a_long_token(.:format) users#activate
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!