如何使重定向包括名称而不是ID?

时间:2018-05-02 19:48:05

标签: ruby-on-rails redirect configuration routes

我正在使用Rails 5.1。在我的控制器中,我想重定向到我的“show”方法,如此

redirect_to(@organization)

但我希望网址显示为

/organization/organization_name

而不是

/organization/primary_key_id

如何设置?我的组织模型中已经有一个字段“name”。

编辑:根据要求,这是我PagesController的索引方法......

class PagesController < ApplicationController

  # Should be the home page
  def index
    worker_id = params[:worker_id]
    worker = Worker.find_by_id(worker_id)
    if worker && worker.organization
      redirect_to(worker.organization)
    else
      render :file => "#{Rails.root}/public/404", layout: false, status: 404
    end
  end

end

修改:我的config/routes.rb文件

  resources :organizations, :only => [:show] do
    post :update_work
    get :get_work
    get :mine
    get :poll
    post :submit
    get :home
    get :terms_of_use
  end

这是app/model/stratum_worker.rb文件

class StratumWorker < ApplicationRecord

  has_one :organization_worker
  has_one :organization, :through => :organization_worker

4 个答案:

答案 0 :(得分:3)

好的,如果你对使用任何宝石不感兴趣,那么你就可以没有宝石了

class Model < ApplicationRecord
   def to_param  # overridden
      organization_name
    end
end

在这种情况下,您需要确保organization_name名称是唯一的,唯一性organization_name您可以使用此类验证

validates_uniqueness_of :organization_name

然后模型看起来像这样

class Model < ApplicationRecord
    validates_uniqueness_of :organization_name

    def to_param  # overridden
      organization_name
    end
end

现在使用find_by_organization_name(params[:organization_name])代替find(params[:id])来控制器。

第二个选项

如果仅在模型

中使用,则无法对控制器进行任何更改
class Model < ApplicationRecord
    def to_param  # overridden
      organization_name
      "#{id} #{organization_name}".parameterize
    end
end

然后,网址看起来像/10-microsoft

请参阅此to_param方法。使用gem或没有gem Rails Friendly URLs

的完整参考

RailsCasts.com使用FriendlyId创建了一个漂亮网址的剧集,你可以查看它以获得这个想法。

来自评论

我不知道发生了什么,但确定这段关系出了问题,你能不能这样检查

redirect_to(worker.organizations.first)
#=> OR
redirect_to organization_path(worker.organizations.first.id)

<强>更新

我认为worker.organization以某种方式遗失了,你会尝试这样吗?

if worker && worker.organizations.present?
   redirect_to(worker.organizations.first)
....

present方法,确保worker.organizations不为空。

  

我不知道这段关系,你可以尝试这样,让我知道如果它不起作用会发生什么,那么我强烈建议发布关系概念的模型。

问题更新后更新2

首先,您不需要through关系,因为它使用过Many To Many关系。您的关系是One To One,那么您的模型将如下所示

class StratumWorker < ApplicationRecord

    has_one :organization_worker
....

has_one:organization,:through =&gt; :organization_worker

organization_worker.rb这样的文件

class OrganizationWorker < ApplicationRecord

    belongs_to :stratum_worker 

    #=> Add code what you need like for URL which was the actual motive in this post
....

然后动作看起来像这样

def index
    worker_id = params[:worker_id]
    worker = StratumWorker.find_by_id(worker_id)
    if worker && worker.organization_worker.present?
      #redirect_to(worker.organization_worker)
      redirect_to organization_path(worker.organization_worker)
    else
      render :file => "#{Rails.root}/public/404", layout: false, status: 404
    end
end

和节目动作

OrganizationWorker.find(params:id)

我认为现在问题会解决。如果仍然存在错误,请再次阅读One To One关系&amp;再次清除关系概念。

希望它会有所帮助。

答案 1 :(得分:1)

在ID生成的引擎下调用的方法是to_param

因此,在您的情况下,要获得所需的结果,您应该将其添加到Organization班级:

class Organization < ApplicationRecord
  ...

  def to_param
    name
  end

  ...
end

!!!警告!!! - 由于Rails也使用另一方的参数(例如在show方法Organization.find(params[:id])中使用URL id),现在它将是{ {1}}因此,相应地更改实例查找 - 在params[:id] == "some_organization_name"操作中,例如使用show等等

至于您的路由错误 - 请确保Organization.find_by!(name: params[:id])不是worker.organization

答案 2 :(得分:1)

有一个gem friendly_id可以满足您的要求:https://github.com/norman/friendly_id

你添加,

gem 'friendly_id'

然后bundle install并运行rails generate friendly_idrails db:migrate

到您的Gemfile,

class Organization < ApplicationRecord
  extend FriendlyId
  friendly_id :name, use: :slugged
end
然后

到你的模型,

class OrganizationController < ApplicationController
  def show
    @user = Organization.friendly.find(params[:id])
  end
end

到您的控制器。

这可以防止你在Kkulikovskis中遇到的问题,你必须确保你正确地查找。

答案 3 :(得分:1)

我刚刚写了一篇文章here详细说明了这一点。我的大部分答案都是从那里开始的。相关的Rails文档是here

快速定义:

  • Slug:用于标识记录的网址的一部分,在您的情况下为organization_name
  • 主键:数据库记录的唯一标识符。这通常应该是id

摘要

如果您输入organization_path(@organization),它会自动使用网址中的id属性。要调整为使用organization_name,您需要进行2次更改:

  1. 覆盖routes.rb文件中的路线参数。
  2. 覆盖模型中的to_param方法
  3. 1。覆盖路线参数

    目前,如果您运行rails routes,您的路线就是这样:

    organizations       GET    /organizations(.:format)                     organizations#index
                        POST   /organizations(.:format)                     organizations#create
    new_organization    GET    /organizations/new(.:format)                 organizations#new
    edit_organization   GET    /organizations/:id/edit(.:format)            organizations#edit
    organization        GET    /organizations/:id(.:format)                 organizations#show
                        PATCH  /organizations/:id(.:format)                 organizations#update
                        PUT    /organizations/:id(.:format)                 organizations#update
                        DELETE /organizations/:id(.:format)                 organizations#destroy
    

    edit_organizationorganization路径使用id作为参数来查找您的组织。

    使用此选项覆盖路线参数

    Rails.application.routes.draw do
      resources :organizations, param: :organization_name
    end
    

    现在rails routes会显示您的路线如下:

    organizations       GET    /organizations(.:format)                                    organizations#index
                        POST   /organizations(.:format)                                    organizations#create
    new_organization    GET    /organizations/new(.:format)                                organizations#new
    edit_organization   GET    /organizations/:organization_name/edit(.:format)            organizations#edit
    organization        GET    /organizations/:organization_name(.:format)                 organizations#show
                        PATCH  /organizations/:organization_name(.:format)                 organizations#update
                        PUT    /organizations/:organization_name(.:format)                 organizations#update
                        DELETE /organizations/:organization_name(.:format)                 organizations#destroy
    

    2。覆盖模型参数

    默认情况下,organization.to_param将返回组织的id。这需要被覆盖,通过修改模型来执行此操作:

    class Organization < ApplicationRecord
      def to_param
        organization_name
      end
    end
    

    结论&amp;警告

    您现在可以像往常一样继续使用重定向和表单,但现在使用组织名称而不是使用id的路由。

    另外,祝你的采矿池好运! Lemme知道你正在挖掘哪枚硬币,我可能会加入!

    另外,我没有说明这一点,因为它不是原始问题的一部分,但是,您应该确保organization_name是唯一的!您不仅应该在模式中添加唯一性约束validates :organization_name, uniqueness: true,还应该在迁移中在数据库级别强制执行它。

    附录1:为路线定制

    当您的路线定义如下:

      resources :organizations, :only => [:show] do
        post  'update_work'
        get   'get_work'
        get   'mine'
        get   'poll'
        post  'submit'
        get   'home'
        get   'terms_of_use'
      end
    

    您的路线将如此:

     organization_update_work POST   /organizations/:organization_id/update_work(.:format)                                    organizations#update_work
        organization_get_work GET    /organizations/:organization_id/get_work(.:format)                                       organizations#get_work
            organization_mine GET    /organizations/:organization_id/mine(.:format)                                           organizations#mine
            organization_poll GET    /organizations/:organization_id/poll(.:format)                                           organizations#poll
          organization_submit POST   /organizations/:organization_id/submit(.:format)                                         organizations#submit
            organization_home GET    /organizations/:organization_id/home(.:format)                                           organizations#home
    organization_terms_of_use GET    /organizations/:organization_id/terms_of_use(.:format)                                   organizations#terms_of_use
                 organization GET    /organizations/:id(.:format)                                                             organizations#show
    

    像这样更改param

      resources :organizations, :only => [:show], param: :organization_name do
        post  'update_work'
        get   'get_work'
        get   'mine'
        get   'poll'
        post  'submit'
        get   'home'
        get   'terms_of_use'
      end
    

    将您的路线改为

     organization_update_work POST   /organizations/:organization_organization_name/update_work(.:format)                     organizations#update_work
        organization_get_work GET    /organizations/:organization_organization_name/get_work(.:format)                        organizations#get_work
            organization_mine GET    /organizations/:organization_organization_name/mine(.:format)                            organizations#mine
            organization_poll GET    /organizations/:organization_organization_name/poll(.:format)                            organizations#poll
          organization_submit POST   /organizations/:organization_organization_name/submit(.:format)                          organizations#submit
            organization_home GET    /organizations/:organization_organization_name/home(.:format)                            organizations#home
    organization_terms_of_use GET    /organizations/:organization_organization_name/terms_of_use(.:format)                    organizations#terms_of_use
                 organization GET    /organizations/:organization_name(.:format)                                              organizations#show
    

    哪个应该可以完全正常使用重定向。