0

I have model User contain column role.

class CreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users do |t|
      t.string :name
      t.string :email
      t.string :address
      t.integer :role
      t.timestamps
    end
  end
end

role is shop if User.role = 1 , role is shipper User.role = 0

Routes.rb

resources :users

And url for action show (profile): http://localhost:3000/users/1

I want change it with :role. For example: http://localhost:3000/shops/1 (if User.role = 1) or .../shippers/1 (if User.role = 0).

i don't know how to do that. Help me pls, Thank you!

Quyen ND
  • 1
  • 1
  • 1
    Possible duplicate of [Rails Routes based on condition](http://stackoverflow.com/questions/11230130/rails-routes-based-on-condition) – Pavan Nov 11 '16 at 10:14
  • http://bjedrocha.com/rails/2015/03/18/role-based-routing-in-rails/ Please try this i think this can help you – Tushar Pal Nov 11 '16 at 13:17

2 Answers2

1

Firstly, you'd be better using an enum in your model. This way, you can assign actual roles to the User.role attribute (not just integers):

#app/models/user.rb
class User < ActiveRecord::Base
  enum role: [:shipper, :shop]
end

This will still keep the integer in the database, but assign an actual name to the role in ActiveRecord. For example, you'll get user.shipper? and user.shop?.


Since I was interested to see a resolution, I looked online and found this.

It explains what I had thought - you'll need to use a constraint to validate the role of the user and redirect accordingly. This way, you can send use a single route helper, and have the user sent to different routes depending on their role.

As per this answer, I'd try something like:

# lib/role_constraint.rb
class RoleConstraint
  def initialize(*roles)
    @roles = roles
    @role  = request.env['warden'].user.try(:role)
  end

  def matches?(request)
    params = request.path_parameters
    @roles.include?(@role) && @role == params[:role]
  end
end


#config/routes.rb
resources :users, path: "", except: :show do
  get ":role/:id", action: :show, on: :collection, constraints: RoleConstraint.new([:shipper, :shop])
end

This isn't exactly what I'd want but it should create a single route, which is only accessible by the User with a role either as shipper or shop.

Community
  • 1
  • 1
Richard Peck
  • 76,116
  • 9
  • 93
  • 147
-1

If you just want to map that route you can do

match '/shops/1', to: 'users#show'
match '/shippers/1', to: 'users#show'

This way you are processing that route with the show controller under the User structure. Then, the html of /shops/1 should still be under views/users/show as rails will look for the view with the same name as the controller to render the page.

[UPDATE]

Then, in your controller you can say

<% if User.role == 1 %>
    <%redirect_to show_user_path%>
Vlad Balanescu
  • 664
  • 5
  • 27