在Rails 3中动态创建路由别名

时间:2014-06-12 13:27:02

标签: ruby-on-rails ruby ruby-on-rails-3 alias rails-routing

我的一些客户希望为Rails中的某些页面创建别名。下面显示了这种别名的一个示例:

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

我们正在使用rails admin,所以如果我创建一个包含手动别名创建字段的表:

  • 别名
  • 控制器
  • ID
  • 区域设置

某些模型已经在表格中使用了别名,我们称之为模型页面。模型页面有一个字段别名,可以在路径中执行类似的操作:

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

问题: 我只是想找到最像这样做的铁路。

3 个答案:

答案 0 :(得分:2)

执行此操作的典型方法是在路径文件末尾使用通配符路径,例如:

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

对于与任何其他路线不匹配的任何网址,将使用alias参数中的路径调用PagesController的show动作。

然后在show动作中,您可以执行Page.find_by_alias!(params[:alias]) - 如果没有页面匹配,您将获得一个标准的404页面(因为将抛出ActiveRecord::RecordNotFound异常),如果该页面是存在,那么你可以继续正常。

编辑:

对于您想要这样的别名的多个模型,您可以将通配符指向另一个控制器,然后在该控制器中迭代您的模型以查找匹配的模型。例如。第一个Page.find_by_alias(params[:alias]) ....如果它是零,那么Testimonial.find_by_alias(params[:alias])等......当你找到匹配的那个时,你就可以渲染出适当的视图。

当然,如果你这样做,你就冒着命名冲突的风险 - 如果你有一个推荐书和一个具有相同别名的页面会发生什么?一个永远不会被查看,因为另一个将被查找并首先匹配。

答案 1 :(得分:1)

在我亲爱的朋友七人的帮助下,一切都很顺利:

我做了什么:

1)向表中添加了所需的Alias字段/列

2)创建了Alias模型/控制器 此代码为伪代码,但您将获得图片

  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

这没有交叉表验证

谢谢大家的帮助:)

答案 2 :(得分:0)

未经测试,但这样的事情应该有用(如果你不介意做重定向,这在某些方面似乎更合适):<​​/ p>

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