dlu
dlu

Reputation: 791

Setting parameters on the root route in Ruby on Rails

I'm building a shared blog using the Rails 5.0.0.beta2. I'd like to have the root route for unprivileged users resolve to users/:user_id/posts, which will display all of users posts. As things are currently configured the route is defined as:

root to: 'posts#index'

Which returns all of the posts (for all users).

I tried:

root 'users/:user_id/posts' => 'posts#index', controller: 'posts', action: 'index'

Which results in:

root_path GET / posts#index {"users/:user_id/posts"=>"posts#index"}

At rails/info/routes (or rails routes). But which doesn't seem to be using the :user_id component of the route – all of the published posts are shown. As far as I can tell, there is no route that should do that… (both from inspecting the route table and also from manually entering the route).

I also tried:

get 'users/:user_id/posts' => 'posts#index', :as => :root

Which results in:

root_path GET /users/:user_id/posts(.:format) posts#index

But the actual page that is served is the "Yay, you're on Rails!" page.

Is it possible to do this? How would I go about it?

Upvotes: 3

Views: 1554

Answers (1)

Richard Peck
Richard Peck

Reputation: 76774

All users are authenticated

So what you're asking is how to scope the "homepage" @posts to those of the current_user.

There are two ways to do it (Controller and Devise):


Controller

#config/routes.rb
root "posts#index" #-> url.com

#app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def index
     @posts = user_signed_in? ? current_user.posts : Post.all
  end
end

#app/views/posts/index.html.erb
<% @posts.each do |post| %>
  <%= post.title %>
<% end %>

This is the simplest way to pull it off.

The routes don't matter -- if your user is signed in, you can scope the data around their current_user object.

In both cases, you wish to access url.com, so you'd match this with routing that to the posts#index. The @posts variable can then be scoped to whichever setup works best for you.


Devise

#config/routes.rb
authenticate :user do
  root "posts#user", as: :authenticated_root #-> url.com
end

unauthenticated :user do
  root 'posts#index', as: :root #-> url.com
end

Devise has the authenticated && unauthenticated route helpers to give you different sets of routes, depending on whether the user is logged in.

There are 3 helpers in total:

  • authenticate - if user is logged in
  • authenticated - only if the user is logged in (hidden other times)
  • unauthenticated - if user is not logged in

You could use the above to access the following:

#app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def index
    @posts = Post.all
  end

  def user
    @posts = current_user.posts
    render :index
  end
end

This is not much different than the above method; the reason you'd use it is if you had a marked difference in the flow. IE you set data in posts#index which was completely different to posts#user.

In my example, both methods use index.html.erb; you could easily split them...

#app/views/posts/index.html.erb
<% @posts.each do |post| %>
  ....
<% end %>

Upvotes: 3

Related Questions