2014-06-12 86 views
1

我的一些客戶希望爲Rails中的某些頁面創建別名。下面顯示這種別名的一個例子:在Rails中動態創建路由別名3

match '/events_nl' => 'pages#show', :defaults => { :id => '1' , :locale => "nl"} 

我們正在使用的軌道管理等什麼,如果我創建一個表,用於手動別名創建領域:

  • 別名
  • 控制器
  • ID
  • 區域

有些模型已經在表格中有一個別名,我們稱它爲model Page。型號頁有一個字段別名是有可能做這樣的事情在路線:

pages_with_alias = Page.find_all_by_alias(true) 
pages_with_alias.each do page 
    match page.alias , :to "pages#show", :defaults => { :id => page.id , :locale => page.locale} 
end 

問題: 我只是在尋找最像鋼軌這樣的方式。

回答

1

隨着我親愛的朋友sevenseacat一切的幫助下制定了很大:

我做了什麼:

1)增加所需的別名字段/列於表

2)創建了別名模型/控制器 此代碼是僞代碼,但您將獲得圖片

def show 
    object = Model.where("lower(alias) =?", params[:alias].downcase).first || OtherModel.where("lower(alias) =?", params[:alias].downcase).first 
    if object.class.name == "Model" 
     @model = Model.find_by_id!(object.model_id) 
     render "model/show" 
    elsif object.class.name == "OtherModel" 
     @othermodel = OtherModel.find_by_id!(object.othermodel_id) 

     I18n.locale = object.locale 
     render "othermodel/show" 
    else 
     not_found 
    end 
    end 

3)創建的路線

get '*alias', to: 'alias#show', as: 'alias' 

只是爲了信息NOT_FOUND:

def not_found 
    raise ActionController::RoutingError.new(t("activemodel.errors.messages.not_found")) 
    end 

注1

這是不交叉表的有效性

謝謝大家的幫助:)

+0

我知道這只是僞代碼,但保持一致 - 一個子句使用'where(id:foo).first',另一個使用'find_by_id!' - 第一個可能只返回nil,渲染時會爆炸視圖。 – sevenseacat

+0

@sevenseacat修復它。 – Vinozio

2

這樣做,這將是與你的路由文件的末尾通配符路線,喜歡的事的典型方法:

get '*alias', to: 'pages#show', as: :page 

其中,對於不符合任何其他途徑的任何URL,將調用您的PagesController的show操作使用參數alias中的路徑。

然後在show動作中,你可以做一個Page.find_by_alias!(params[:alias]) - 如果沒有頁面匹配,你將得到一個標準的404頁面(因爲會拋出一個ActiveRecord::RecordNotFound異常),如果頁面確實存在,那麼你可以繼續正常。

編輯:

對於要這樣的別名,你可以代替你的通配符指向不同的控制器,然後通過你的模型,控制器迭代尋找一個匹配的多個模型。例如。第一個Page.find_by_alias(params[:alias]) ....如果它的零,然後Testimonial.find_by_alias(params[:alias]),等.....當你找到一個匹配,那麼你可以渲染適當的觀點。

當然,如果你這樣做,你冒着命名衝突的風險 - 如果你有一個證明和一個頁面具有相同的別名會發生什麼?一個永遠不會被看到,因爲另一個將被首先查找和匹配。

+0

Sevenseacat嗨,至於說在此之前的作品都不錯1種模式(頁),但什麼,我想別名,告別賽,網頁,特定作業多個模型, ... – Vinozio

+0

@Vinozio看到我的編輯。 – sevenseacat

+0

是不是可以創建一個必須在所有表上唯一的列? – Vinozio

0

未經檢驗的,但這樣的事情應該工作(如果你不介意做一個重定向,在某些方面似乎最好反正):

get '*alias', to: redirect { |params, request| 
    object = Page.find_by_alias(params[:alias]) || Other.find_by_alias(params[:alias]) 
    Rails.application.routes.url_helpers.url_for(object) 
} 

你的方法可能是更好的如果(且僅當)您不需要動態更新路由(例如,在您重新啓動應用程序之前,您的解決方案將不會有新創建的Page對象的路徑)。您可以撥打Rails.application.reload_routes!作爲模型觀察的一部分,但看起來並不乾淨。