2014-06-12 54 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!作为模型观察的一部分,但看起来并不干净。