【问题标题】:Rails 4 - change URL from /user/:id to /:usernameRails 4 - 将 URL 从 /user/:id 更改为 /:username
【发布时间】:2016-01-05 03:44:04
【问题描述】:

我有一个控制器 pages#dashboard,我已将其设置为 routes.rb

中的 user_root
devise_for :users, controllers: { registrations: 'registrations' }
devise_scope :user do
  get "/signup" => "devise/registrations#new"
  get "/login" => "devise/sessions#new"
  get "/logout" => "devise/sessions#destroy"
  get "/:id" => "users#dashboard", :as => "user_root", :id => :username
end

我希望 URL 为 http://my_app.com/current_user_username

我已将 user.rb 模型中的 to_param 设置为:

def to_param
  username
end

当我有如下链接时,这可以正常工作:

<%= link_to "MY ACCOUNT", user_root_path(current_user) %>

但在初始登录时,URL 是:http://my_app.com/username(明确表示“用户名”)而不是 http://my_app.com/current_user_username

我尝试将我的 to_param 设置为:

def to_param
  "#{username}"
end    

并且还尝试将我的 route.rb 设置为:

get "/:id" => "users#dashboard", :as => "user_root", :id => :username, :via => :get

这些都没有解决问题。

环境:Rails 4.2.5、Ruby 2.3.0、Devise gem 3.5.3

任何帮助将不胜感激。

【问题讨论】:

  • 在你的控制器中,而不是使用User.find(params[:id]),你现在需要使用User.find_by_username(params[:id])。您也可以结帐friendly_id gem

标签: ruby-on-rails ruby ruby-on-rails-4 devise


【解决方案1】:

您可以简单地在您的 routes.rb 中的所有内容之上添加另一条路线:

get "/:username" => "users#dashboard", :as => "user_root"
devise_for :users, controllers: { registrations: 'registrations' }
devise_scope :user do
  get "/signup" => "devise/registrations#new"
  get "/login" => "devise/sessions#new"
  get "/logout" => "devise/sessions#destroy"
  get "/:id" => "users#dashboard", :as => "user_root", :id => :username
end

然后你需要通过这样的方式找到用户:

    @user = User.find_by(username: params[:username])

【讨论】:

    【解决方案2】:

    只需使用friendly_id:

    #Gemfile
    gem 'friendly_id', '~> 5.1'
    
    $ rails generate friendly_id #-> generates initializer
    $ rails generate scaffold user name:string slug:string:uniq #-> adds slug column
    $ rake db:migrate
    
    #app/models/user.rb
    class User < ActiveRecord::Base
       extend FriendlyId
       friendly_id :username, use: [:slugged, :finders]
    end
    

    这将允许您使用 slug / username 代替主键:

    <%= link_to current_user.username, user_path(current_user) #-> <a href="/users/john_jones" %>
    

    您无需更改控制器代码等即可使其正常工作。

    --

    您的路线可以简化:

    #config/routes.rb
    resource :user, path: "", only: :show #-> url.com/:id to users#show
    devise_for :users, controllers: { registrations: 'registrations' }, path_names: { sign_in: "login", password: "forgot", confirmation: "confirm", unlock: "unblock", sign_up: "", registration: "signup", sign_out: "logout" }
    

    虽然我不知道你是否可以在你的路线中使用current_user(我相信你可以,但我没有测试过),你可能希望像这样使用/profile

    resource :profile, controller: :users, only: :show
    

    这会将url.com/profile 发送到users#show 操作:

    #app/controllers/users_controller.rb
    class UsersController < ApplicationController
       def show
          current_user...
       end
    end
    

    【讨论】:

      【解决方案3】:

      我通过将其添加到 application_controller.rb

      解决了这个问题
      def after_sign_in_path_for(resource)
        user_root_path(current_user)
      end
      

      ** 这是一个设计特定的答案。

      感谢所有花时间回答的人:)

      【讨论】:

        【解决方案4】:

        我遇到了类似的问题,并对路线进行了一些更改,它在这里工作是要做的设置:

        1. 在 User.rb 模型下 def to_param 用户名 结束

        2. 路线: 资源 :users, :path => '/' 做 结束

        3. 控制器 @user=User.find_by_username(params[:id])

        4. 观看次数 链接到@user.username,@user.username。 避免使用 user_path,因为它会将您重定向到 www.example.com/users/david 而是跟进我在上面提到的 它将www.example.com/david 这比第一个要好。

        希望有人能得到帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多