Rails 3.1路由约束失败

时间:2011-08-16 16:41:12

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

这个问题与this one相当,但我再次提出这个问题,因为提供的答案并没有解决问题,并且正如提出问题的人总结的那样:它可能是Rails中的一个错误(但没有后续跟进)就此而言。)

我有这些路线:

resources :books, controller: :projects, type: "Book" do
  resources "", as: :book_chapters, controller: :contributions, type: "BookChapter", except: :index, constraints: IdConstraint
end

这是IdConstraint:

class IdConstraint
  INVALID_IDS = %w[edit series new]
  def self.matches?(request)
    !INVALID_IDS.include? request.params[:id]
  end
end

我使用的是friedly_id,因此:id参数是一个基于书籍或书籍章节标题的字符串。

现在,/books/friendly-id-of-book/friendly-id-of-chapter之类的请求会路由到book_chapters控制器上的show操作。

但我还希望/books/friendly-id-of-book/edit路由到图书控制器上的edit操作,因为book_chapters路线上的约束将edit排除为id。这不起作用,似乎问题出在IdConstraint。如果我将matches?方法中的一行替换为false

class IdConstraint
  INVALID_IDS = %w[edit series new]
  def self.matches?(request)
    false
  end
end

.../edit路由正确路由到图书控制器上的编辑操作。

但是当我只在原始行之后添加false行:

class IdConstraint
  INVALID_IDS = %w[edit series new]
  def self.matches?(request)
    !INVALID_IDS.include? request.params[:id]
    false
  end
end

路由失败,即路由到id为“edit”的book_chapters控制器,而我真的希望它仍然返回false,从而路由到books控制器的编辑操作。

我无法弄清楚这里出了什么问题。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

在我看来,你正在遇到的是一个范围问题。 INVALID_IDS是在self.matches?()之外定义的,所以它在self.matches中不可用?()。

你可以尝试:

class IdConstraint
  def self.matches?(request)
     INVALID_IDS = %w[edit series new]
    !INVALID_IDS.include? request.params[:id]
  end
end

或者,如果你真的需要在IdConstraint的其他地方使用INVALID_IDS,你可以这样做:

# Note that you'll need to use IdConstraint.new as your constraint for
#   this one, not IdConstraint
class IdConstraint
  def initialize
    @INVALID_IDS = %w[edit series new]
  end

  def matches?(request)
    !@INVALID_IDS.include? request.params[:id]
  end
end

Rails Guide上有第二种方法的好例子。

更新

是的,你对request.params的错误是正确的。目前,这似乎相对较好:

class IdConstraint
  INVALID_IDS = %w[edit series new]
  def self.matches?(request)
    end_of_path = request.path.split('/').last
    !INVALID_IDS.include? end_of_path
  end
end

答案 1 :(得分:1)

这是由Rails 3.1 master(在0e19c7c414bb)中的错误引起的。见the bug report on GitHub。在修复之前,您可以使用request.path_parameters[:id]代替request.params[:id]暂时规避它。