Сбой маршрута Rails 3.1 - PullRequest
       28

Сбой маршрута Rails 3.1

0 голосов
/ 16 августа 2011

Этот вопрос сравним с этим , но я спрашиваю его еще раз, потому что предоставленный ответ не решает проблему, и, как говорит человек, задающий этот вопрос: это может быть ошибка в 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 направляется к действию show на контроллере book_chapters.

Но я бы также ожидал, что /books/friendly-id-of-book/edit направит к действию edit на контроллере books, потому что ограничение на маршрут book_chapters исключает edit в качестве идентификатора. Это не работает, и кажется, что проблема в 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

маршрут завершается неудачей, то есть он направляется к контроллеру book_chapters с идентификатором «edit», в то время как я действительно ожидал бы, что он все еще вернет false, и, таким образом, направит к действию edit контроллера книг.

Я не могу понять, что здесь происходит не так. Есть идеи?

Ответы [ 2 ]

1 голос
/ 17 августа 2011

Это вызвано ошибкой в ​​мастере Rails 3.1 (по адресу 0e19c7c414bb). Смотрите отчет об ошибке на GitHub . Пока он не исправлен, вы можете временно обойти его, используя request.path_parameters[:id] вместо request.params[:id].

1 голос
/ 16 августа 2011

Мне кажется, что то, с чем вы сталкиваетесь, является проблемой сфер. 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

Или, если вам действительно нужно, чтобы INVALID_IDS был доступен в другом месте в IdConstraint, вы можете сделать:

# 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 .

UPDATE

Да, вы правы насчет ошибки с 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
...