如果我想覆盖资源路径(例如post_path(@post)),我该怎么做?

时间:2011-05-16 12:09:40

标签: ruby-on-rails ruby

更新(再次)|忽略模块的东西 - 我以前放在这里。最好只使用to_param并使路线有效。

to_param
  if slug
    "#{id}-#{slug}"
  else
    super
  end
end

match "/posts/:id(-:slug)" => "posts#show", :as => :post, :constraints => { :id => /\d+|\d+-.*/ }

诀窍在于那条路线。它使-:slug成为可选项,并为:id添加约束。约束的首选项是仅匹配一个数值(这是在请求进入时使用的值,因此您的参数中有:id:slug),但管道允许它也匹配一个出于路径生成的目的,数字值后跟slug。这是一个温和的黑客,但这一切都是真的。允许资源提供参数的散列将解决这个问题。这可以应用于您想要的任何花哨的路线(例如,在末尾而不是开始时使用:id。)

Rails 3.0.7。

采取如下路线:

match "/posts/:id-:slug" => "posts#show", :as => :post

这为我提供了一个post_path(obj)帮助器,当然,它只想从我的模型中生成一个参数,从我所知道的,我无法从模型中返回多个值{ {1}}方法。我知道我可以这样写to_param

to_param

但是这是作为路由的单个参数传递的,最终不匹配任何路由。同样地,我知道我可以从我的路由中删除to_param "#{id}-#{slug}" end ,但是"-:slug"参数包含虚假输入,基本上是一个黑客攻击(虽然显然是完成的事情)。

如果未来版本的Rails允许您从:id返回哈希值,那将是非常棒的,例如:

to_param

然后在找到正确的路线时使用它们。

我想弄清楚的是,我会去覆盖to_param { :id => id, :slug => slug } end 来提供正确的路线。我可以把它放在一个视图帮助器中,但是它在我的控制器中不可用,所以我猜这是错误的地方。

好奇不仅仅是好奇。我知道如果我只省略路由上的post_path()它可以正常工作,但在更复杂的情况下,我可以想象覆盖默认路径是一个有用的事情要知道。能够通过传递资源来生成路线是一个非常好的功能,我想采用,但营销部门将始终让我们填写URL将各种关键字mumbo jumbo,所以一些控制将是非常好的:)

1 个答案:

答案 0 :(得分:4)

路由有两个方面:路由生成并路由匹配

正如您所指出的,路线生成非常简单。覆盖任何ActiveModel中的to_param

# In a model:
def to_param
  # Use another column instead of the primary key 'id':
  awesome_identifier.to_s
end

路线匹配不太明显。可以在默认资源路由中指定:awesome_identifier来代替:id的每次出现。但是,我发现如果您在路线中留下:id,并且仅更改控制器中的逻辑,则Rails会减少阻力。请注意,这是一种权衡,因为路由中的:id基本上并不正确。

# In a controller:
def index
  @awesome_record = AwesomeModel.find_by_awesome_identifier(params[:id])
  # ...
end

正如您所注意到的,Rails已经优化了单个用例:如果您希望主键用于快速记录查找,但仍然希望将slug包含在URL中用户友好性或搜索引擎优化。在这种情况下,您可以从"#{id}-#{whatever}"方法返回to_param形式的字符串,并且在将相同的字符串反馈回find方法时,将忽略破折号后的所有内容。