TL; DR Вам необходимо указать и :trunk_id
и root_id
в своем URL или использовать form_for
, например:
<%= form_for [@trunk, @root, @comment] do |f| %>
Rails пытается создать URL из хеша, который вы ему даете, но этот хеш ничего не соответствует в таблице маршрутизации. Вы можете сделать это:
{ :controller => "comments", :action => "create", :trunk_id => trunk.id, :root_id => root.id }
Но это действительно немного tl; dr .
Прохладный способ сделать это так:
trunk_root_comments_path(trunk, root)
Где trunk
и root
являются Trunk
и Root
экземплярами соответственно.
Теперь, если вы хотите быть супер-злой-крутой , сделайте это так:
<%= form_for [trunk, root, comment] do |f| %>
Наука!
Так как это работает? Элементарно, моя дорогая:
Rails сначала признает, что мы используем form_for
, используя массив, и что мы имеем в виду бизнес . Rails использует этот переданный массив и строит из него URL. Это делается с помощью помощников маршрутизации, которые определены маршрутами. К сожалению, вы определили свои маршруты забавным образом, что не очень хорошо с этим работает, но не бойтесь! Мы можем это исправить.
То, как вы можете это сделать, это то, где у вас это есть в config/routes.rb
:
post '/t/:trunk_id/r/:root_id/comments'
Вместо этого поставьте это:
post '/t/:trunk_id/r/:root_id/comments', :as => "trunk_root_comments"
Вы можете или уже иметь это:
match '/t/:trunk_id/r/:root_id/comments', :via => :post
Что должно стать таким:
match '/t/:trunk_id/r/:root_id/comments', :via => :post, :as => "trunk_root_comments"
В любом случае, теперь у вас есть не один, а два (!!) помощников пути, определенных маршрутами. Это trunk_root_comments_path
и trunk_root_comments_url
соответственно. Названия этих методов очень важны для того, что я собираюсь вам объяснить. Обратите внимание!
Итак, вернемся к нашему маленькому form_for
звонку:
<%= form_for [trunk, root, comment] do |f| %>
Rails знает, что мы используем массив, потому что он может его видеть. То, что он делает с этим массивом, может казаться магическим, но на самом деле это не так.
Rails возьмет каждый элемент этого массива и создаст вспомогательный метод маршрутизации name из разных частей. На самом деле это не часть form_for
, а другой метод с именем url_for
, который вы можете использовать самостоятельно:
url_for([trunk, root, comment])
В начале имя этого вспомогательного метода маршрутизации, генерируемое url_for
, представляет собой просто пустой массив ([]
). Ничего особенного.
Но то, что происходит , является особенным!
Первым элементом будет постоянный экземпляр класса Trunk
. Под «постоянным» я подразумеваю, что это объект, который отображает непосредственно на запись в базе данных. Yay ORMs!
Rails узнает об этом и превратит помощника по маршрутизации в: [:trunk]
.
Вторым элементом будет постоянный экземпляр класса Root
. Rails также знает это (черт, Rails - это smart !) И затем добавит это в массив, превратив его в [:trunk, :root]
. Потрясающе.
Третий (и последний) элемент затем проверяется Rails. Он видит, что (в данном случае) это непостоянный элемент, то есть он не был сохранен в базе данных ... пока. Rails обрабатывает это по-другому и вместо этого добавляет [:comments]
к массиву, превращая его в следующее:
[:trunk, :root, :comments]
Видите, куда я иду с этим сейчас?
Теперь, когда Rails выполнил свою задачу (или thang , если хотите), он объединит эти три части вместе, вот так: trunk_root_comments
, и просто для правильной меры поместит _path
в конце, превращая его в окончательного trunk_root_comments_path
помощника.
А потом! Человек, а затем ... Rails вызывает этот метод и передает ему аргументы! Просто так:
trunk_root_comments_path(:trunk_id => trunk.id, :root_id => root_id)
Это генерирует полный путь к ресурсу, как это:
/t/:trunk_id/r/:root_id/comments
И БАМ! Полный круг! Именно так Rails узнает, что нужно сгенерировать URL, и вам больше не нужно использовать уродливые хэши.
Успех!