简体   繁体   English

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

[英]How do I make my redirect include the name instead of an ID?

I'm using Rails 5.1. 我正在使用Rails 5.1。 In my controller, I would like to redirect to my "show" method like so 在我的控制器中,我想重定向到我的“show”方法

redirect_to(@organization)

but I would like the URL to appear as 但我希望URL显示为

/organization/organization_name

instead of 代替

/organization/primary_key_id

How do I set this up? 我该如何设置? I already have a field "name" in my Organization model. 我的组织模型中已经有一个字段“name”。

Edit: As requested, this is the index method of my PagesController ... 编辑:根据要求,这是我的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

Edit: My config/routes.rb file 编辑:我的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

Here's the app/model/stratum_worker.rb file 这是app/model/stratum_worker.rb文件

class StratumWorker < ApplicationRecord

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

OK, if you are not interested to use any gem then you can without gem like 好的,如果你对使用任何宝石不感兴趣那么你可以没有宝石之类的

class Model < ApplicationRecord
   def to_param  # overridden
      organization_name
    end
end

in this case, you need to make sure the organization_name name is unique, for uniqueness the organization_name you can use validation like this 在这种情况下,你需要确保organization_name名是唯一的,独特的organization_name您可以使用验证这样

validates_uniqueness_of :organization_name

then the model will look like this 然后模型看起来像这样

class Model < ApplicationRecord
    validates_uniqueness_of :organization_name

    def to_param  # overridden
      organization_name
    end
end

and now to the controller using find_by_organization_name(params[:organization_name]) instead of find(params[:id]) . 现在使用find_by_organization_name(params[:organization_name])代替find(params[:id])到控制器。

Second Option 第二选择

You can not change anything to your controller if used like this in just model 如果在模型中使用这样的话,则无法对控制器进行任何更改

class Model < ApplicationRecord
    def to_param  # overridden
      organization_name
      "#{id} #{organization_name}".parameterize
    end
end

then the URL looks like this /10-microsoft . 然后URL看起来像/10-microsoft

See this to_param method. 请参阅此to_param方法。 The complete reference of with gem or without gem Rails Friendly URLs 带有gem或没有gem Rails Friendly URLs的完整参考

RailsCasts.com created an episode for Pretty URLs with FriendlyId, can you check it out for getting the idea. RailsCasts.comPrettyId创建了一个漂亮网址的剧集,你可以看看它是否有想法。

From Comment 来自评论

I don't think what's going on but sure something wrong with the relationship, can you check like this 我不认为发生了什么,但确定这种关系有问题,你能不能这样检查

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

Update 更新

I think worker.organization are missing somehow, would you try like this? 我认为worker.organization以某种方式丢失了,你会这样尝试吗?

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

the present method making sure worker.organizations not blank. present方法确保worker.organizations不是空白。

I don't know about the relationship, you can try like this and let me know what's happening if it's not working then I strongly recommend to post the models with relationship concept. 我不知道这种关系,你可以尝试这样,让我知道发生了什么,如果它没有工作,那么我强烈建议发布关系概念的模型。

Update 2 after question update 问题更新后更新2

At first, you don't need the through relationship because it uses too Many To Many relationships. 首先,您不需要through关系,因为它使用了太多Many To Many关系。 Your relationship is One To One then your model will look like this 您的关系是One To One那么您的模型将如下所示

class StratumWorker < ApplicationRecord

    has_one :organization_worker
....

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

organization_worker.rb file like this 像这样的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
....

Then the action looks like this 然后动作看起来像这样

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

and the show action 和节目动作

OrganizationWorker.find(params:id)

I think the problem will solve now. 我认为现在问题会解决。 If still, you getting errors then please read the One To One relationship again & again until clearing the relationship concept. 如果仍然存在错误,那么请再次阅读One To One关系,直到清除关系概念。

Hope it will help. 希望它会有所帮助。

Method that is called under the hood for id generation is to_param 在id生成的引擎盖下调用的方法是to_param

so in your case to get your desired result you should add this to your Organization class: 因此,在您的情况下,要获得所需的结果,您应该将其添加到您的Organization类:

class Organization < ApplicationRecord
  ...

  def to_param
    name
  end

  ...
end

!!!WARNING!!! !!!警告!!! - since Rails is also using the parameter on the other side (eg in show method Organization.find(params[:id]) uses the URL id), now it will be params[:id] == "some_organization_name" so change your instance lookups accordingly - in show action for example use Organization.find_by!(name: params[:id]) and so on - 因为Rails也在另一边使用参数(例如在show方法中, Organization.find(params[:id])使用URL id),现在它将是params[:id] == "some_organization_name"所以改变你的实例查找相应 - 例如在show动作中使用Organization.find_by!(name: params[:id])等等

As for your routing error - make sure that worker.organization is not nil . 至于你的路由错误 - 确保worker.organization不是nil

There is a gem friendly_id that does exactly what you are asking for: https://github.com/norman/friendly_id 有一个gem friendly_id完全符合您的要求: https//github.com/norman/friendly_id

You add, 你添加,

gem 'friendly_id'

Then bundle install and run rails generate friendly_id and rails db:migrate 然后bundle install和run rails generate friendly_idrails db:migrate

to your Gemfile and, 到您的Gemfile和,

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

to your model then, 那么你的模型,

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

to your controller. 到您的控制器。

This prevents the issues you can run into in Kkulikovskis answer where you have to make sure that you are looking things up correctly. 这可以防止你在Kkulikovskis中遇到的问题回答,你必须确保你正确地查找事情。

I wrote a post here detailing exactly this a while ago. 在这里写了一篇文章详细介绍了这个问题。 Most of my answer will be from there. 我的大部分答案都是从那里开始的。 The relevant Rails documentation for this is here . 相关的Rails文档就在这里

Quick definitions: 快速定义:

  • Slug: part of the URL to identify the record, in your case organization_name Slug:用于标识记录的URL的一部分,在您的情况下为organization_name
  • Primary key: a unique identifier for database records. 主键:数据库记录的唯一标识符。 This usually is and should be id . 这通常是并且应该是id

Summary 摘要

If you type organization_path(@organization) , it'll automatically use the id attribute in the URL. 如果键入organization_path(@organization) ,它将自动使用URL中的id属性。 To adjust to using organization_name , you'll need to make 2 changes: 要调整为使用organization_name ,您需要进行2次更改:

  1. Override the route params in your routes.rb file. 覆盖routes.rb文件中的路径参数。
  2. Override the to_param method in the model 覆盖模型中的to_param方法

1. Override The Route Params 1.覆盖路线参数

At the moment, if you run rails routes your routes look like so: 目前,如果您运行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

The edit_organization and organization paths use id as a parameter to lookup your organization. edit_organizationorganization路径使用id作为查询组织的参数。

Use this to override the route params 用它来覆盖路线参数

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

Now rails routes will show that your routes look like so: 现在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. Override The Model Params 2.覆盖模型参数

By default organization.to_param will return the id of the organization. 默认情况下, organization.to_param将返回organization.to_paramid This needs to be overridden, do this by modifying your Model: 这需要被覆盖,通过修改模型来执行此操作:

class Organization < ApplicationRecord
  def to_param
    organization_name
  end
end

Conclusion & Warning 结论和警告

You can now continue using your redirects and forms as usual, but instead of the route using the id , it'll now use the organization name. 您现在可以像往常一样继续使用重定向和表单,但现在使用组织名称而不是使用id的路由。

Also, good luck with your mining pool! 还有,祝你的采矿池好运! Lemme know which coin you're mining and I might join! Lemme知道你正在挖掘哪枚硬币,我可能会加入!

Also, I didn't cover this because it isn't a part of your original question, but, you should ensure that the organization_name is unique! 此外,我没有介绍这个,因为它不是原始问题的一部分,但是,您应该确保organization_name是唯一的! Not only should you add a uniqueness constraint validates :organization_name, uniqueness: true in the mode, you should also enforce it at the database level in your migration. 您不仅应该在模式中添加唯一性约束validates :organization_name, uniqueness: true ,还应该在迁移中在数据库级别强制执行它。

Addendum 1: Customizing for routs 附录1:定制路线

When your routes are defined as so: 当您的路线定义如下:

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

Your routes will be as so: 您的路线将如下:

 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

Changing the param like so: 像这样改变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

Will change your routes to 将您的路线改为

 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

Which should work totally fine with your redirect. 哪个应该与您的重定向完全一致。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM