我正在使用模型实例方法t_param来生成SEO样式的URL
def to_param
url
end
通过这种方式,我可以使用path_to_model(model)生成到模型的链接,并使用Model.find_by_url(url)查询模型。这到目前为止工作正常。
我的问题:我有后端的RESTFUL管理路由。我可以以某种方式使to_param方法对它所调用的路由作出反应吗?因为我想在后端使用ID参数而不是URL参数创建链接。或者这里的正确方法是什么?
答案 0 :(得分:2)
您是否完全反对在网址中提供ID?如果没有,我过去所做的事情(也实现了'seo friendly'网址的目标是:
class Person
def to_param
"#{id}-#{name.parameterize}"
end
end
因此,而不是:
http://www.example.com/users/1
你得到了
http://www.example.com/users/1-jerry-seinfeld
由于String::to_i
方法在遇到非整数字符时会停止(即"1".to_i
和"1-jerry-seinfeld".to_i
都返回1
),这意味着您也可以:
person = Person.find(params[:id])
无需覆盖任何发现者(还有在前端和管理员后端工作的额外好处)。
答案 1 :(得分:2)
我有同样的问题。模型真的不能/不应该知道控制器的任何信息。控制器的工作是确定正在请求的资源,并调用模型来访问它。如果您的AdminController需要使用标准数字ID,则您不想触及to_param
。
事实证明,解决方案非常简单,我在生产中使用它。
假设您已将命名空间命名为,您将拥有MyModelController和Admin :: MyModelController以及他们的帮助程序。在管理员中,以标准方式执行操作。在MyModelController中,执行以下操作:
在您的资源操作中,请参阅params[:id]
,但将其视为永久链接(URL)。例如
def get
@my_model = MyModel.find_by_url(params[:id])
...
end
在你的MyModelHelper
中def my_model_path my_model
super my_model.url
end
def my_model_url my_model
super my_model.url
end
对我而言,我觉得这是“不打架”铁轨并获得我需要的最佳方式。
可能有一种更聪明的方式来覆盖命名路由。此外,我认为你不能使用helper :all
这种方法,除非你在生成路径/网址之前检查你是否在管理员的状态。
答案 2 :(得分:2)
在模型类变量@@to_param
和类方法中使用以控制它。
例如在模型中:
class ProductCategory < ActiveRecord::Base
@@to_param = true
attr_accessible :description, :name, :parent_id
has_ancestry
has_many :products
validates :slug, :uniqueness => true, :presence => true
before_validation :generate_slug
#Trigger fo 'to_param' method
def self.to_param_trigger(test)
if (test)
@@to_param = true
else
@@to_param = false
end
end
def to_param
if @@to_param
slug
else
id
end
end
def generate_slug
self.slug ||= self.ancestors.map {|item| item.name.parameterize}.push(self.name.parameterize).join('/')
end
end
在控制器中:
class Backend::ProductCategoriesController < Backend::BaseController
def index
# Disable 'to_param'
ProductCategory.to_param_trigger false
@categories = ProductCategory
.select([:id, :name, :slug])
.select("COALESCE(ancestry, '0') as anctr")
.order :anctr, :name
end
def new
end
def edit
end
end
before_filter和help中的其他技巧=)
答案 3 :(得分:0)
这是一种方法......
class BlogPost
def to_param
url
end
# BlogPost.find_by_param("14") => looks for ID 14
# BlogPost.find_by_param("foobar") => looks for url "foobar"
# BlogPost.find_by_param("14-foobar") => looks for ID 14 (ignores the "-foobar" part)
def self.find_by_param(param)
if param.to_s =~ /^[0-9]+/
find_by_id param.to_i
else
find_by_url param.to_s
end
end
end
答案 4 :(得分:0)
抓住gem friendly_id并查看他们是如何做到的 - http://rubygems.org/gems/friendly_id
他们有
def to_param
(friendly_id || id).to_s
end
在他们的模型支持中 - https://github.com/norman/friendly_id/blob/master/lib/friendly_id/active_record_adapter/simple_model.rb - 但事情似乎通常像你想要的那样工作,所以如果不重用宝石,你可能会调整他们的代码。