2014-06-15 68 views
20

我有一個名爲'公司'的控制器,而不是每個公司的URL用一個:ID表示我想要使用他們的網址:名稱,如:url/company/microsoft而不是url/company/3Rails路由與:名稱,而不是:ID的url參數

在我的控制器我以爲我會

def show 
    @company = Company.find(params[:name]) 
end 

由於不會在網址中的其他參數,我希望軌將瞭解到:名稱引用的:名字列在我的公司模式。我認爲這裏的魔法會在路線上,但我堅持在這一點上。

+2

有一個寶石[frendly_id](https://github.com/norman/friendly_id)此 – zishe

+0

[更改在導軌路由參數id]的可能重複(http://stackoverflow.com/問題/ 2837102 /改變參數在軌道路由) –

+0

你可以使用'to_param'方法,閱讀更多關於'to_param'方法[here](http://apidock.com/rails/ActiveRecord/ Base/to_param) –

回答

11

params

底線是你正在尋找在錯誤的解決方案 - params哈希鍵是相當無關緊要,你需要能夠更有效地使用其中包含的數據。

你的路線將建設成爲:

#config/routes.rb 
resources :controller #-> domain.com/controller/:id 

這意味着,如果你申請這條航線:domain.com/controller/your_resource,在params[:id]哈希值會your_resource(不要緊,如果它被稱爲params[:name]params[:id]

-

friendly_id

你有幾個答案建議friendly_id的原因是因爲它覆蓋的ActiveRecordfind方法,讓您在您的查詢中使用slug

#app/models/model.rb 
Class Model < ActiveRecord::Base 
    extend FriendlyId 
    friendly_id :name, use: [:slugged, :finders] 
end 

這可以讓你做到這一點:

#app/controllers/your_controller.rb 
def show 
    @model = Model.find params[:id] #-> this can be the "name" of your record, or "id" 
end 
+1

因此,如果我理解正確,沒有簡單的方法(在routes.rb和我的控制器中)告訴Rails查看我的模型的name列而不是:id列? 如你所示重寫find方法的不足之處,使用一個爲我做的gem是最簡單的方法? 對不起,這似乎是通常會使用的東西。 – dscher

+2

不用'find' - 如果你想這樣做,你需要使用'find_by name:params [:id]';但這意味着您只能使用'name'屬性 –

5

其實沒有什麼神奇的實現這一點,你必須build it yourself通過你的模型正確實施to_param(不推薦)要麼或使用可用的寶石之一此類似:

我使用friendly_id它很好地完成了這項工作。

2

Model.find(primary_key)
此處的默認參數是primary_key id。 如果你想使用其他列,你應該使用Model.find_by_xxx 所以這裏可能是

def show 
    @company = Company.find_by_name(params[:name]) 
end 
6

我建議使用用於此目的的friendly_id。 請注意的是,有friendly_id 4和5之間的差異在friendly_id 4,你可以這樣

@company = Company.find(params[:id]) 

使用,但是,你不能這樣做,在friendly_id 5,您必須使用:

@company = Company.friendly.find(params[:id]) 

在您不希望使用PARAMS情況[:編號],但PARAMS [:名字],你必須覆蓋routes.rb中的路線。例如

get '/companies/:name', to: "companies#show" 

希望這些信息將有助於您

56

使用Rails 4.0+的好回答:

resources :companies, param: :name 

您也可以選擇使用only:except:列表來指定路線

,如果你想構建一個URL,您可以覆蓋相關模型的ActiveRecord :: Base的#to_param:

class Video < ApplicationRecord 
    def to_param 
    identifier 
    end 

    # or 
    alias_method :to_param, :identifier 
end 

video = Video.find_by(identifier: "Roman-Holiday") 
edit_videos_path(video) # => "/videos/Roman-Holiday" 
+4

優雅的解決方案。 – Elvn

+4

如果您希望爲此資源中的一條成員路由設置不同的參數,則可以再次將資源定義爲:resources:companies,only:[],param::name do;成員做; get:page;結束;結束; – Jarred

+3

@Jarred您也可以使用「except」作爲黑名單 – Matrix

8

老實說,我只會覆蓋型號中的to_param。這將允許company_path傭工正常工作。

注:我會爲複雜的名稱創建一個單獨的slug列,但這只是我。這是一個簡單的例子。

class Company < ActiveRecord::Base 
    def to_param 
    name 
    end 
end 

然後改變我的路線param的可讀性。

# The param option may only be in Rails 4+, 
# if so just use params[:id] in the controller 
resources :companies, param: :name 

最後,在我的控制器我需要看看它的正確途徑。

class CompaniesController < ApplicationController 
    def show 
    # Rails 4.0+ 
    @company = Company.find_by(name: params[:name]) 
    # Rails < 4.0 
    @company = Company.find_by_name(params[:name]) 
    end 
end 
相關問題