Ruby on Rails: действие link_to, маршрут не совпадает

#ruby-on-rails

#ruby-on-rails

Вопрос:

Я вхожу в Rails и пытаюсь добавить функцию «голосования» в настройках блога отсюда: http://guides.rubyonrails.org/getting_started.html

В app / controllers / posts_controller.rb я создал это:

   def incvotes
    @post = Post.find(params[:id])
    post.update_attributes(:upvotes => 1 )
    format.html { redirect_to(@post, :notice => 'Vote counted.') }
    format.xml  { head :ok }
  end
  

В app / views / posts /index.html.erb я создал это:

 <%= link_to 'Vote', :controller => "posts", :action => "incvotes", :id => post.id %>
  

Но ссылка выдает ошибку

Маршрут не совпадает {:controller=>»posts», :action=>»incvotes», :id=>1}

Я здесь чего-то не хватает, но не уверен, чего.

прокладывать маршруты:

 incvotes_post POST   /posts/:id/incvotes(.:format) {:action=>"incvotes", :controller=>"posts"}
        posts GET    /posts(.:format)              {:action=>"index", :controller=>"posts"}
              POST   /posts(.:format)              {:action=>"create", :controller=>"posts"}
     new_post GET    /posts/new(.:format)          {:action=>"new", :controller=>"posts"}
    edit_post GET    /posts/:id/edit(.:format)     {:action=>"edit", :controller=>"posts"}
         post GET    /posts/:id(.:format)          {:action=>"show", :controller=>"posts"}
              PUT    /posts/:id(.:format)          {:action=>"update", :controller=>"posts"}
              DELETE /posts/:id(.:format)          {:action=>"destroy", :controller=>"posts"}
   home_index GET    /home/index(.:format)         {:action=>"index", :controller=>"home"}
         root        /(.:format)                   {:action=>"index", :controller=>"home"}
  

Комментарии:

1. Что говорится в вашем файле маршрутов относительно записей?

Ответ №1:

попробуйте

 = link_to "vote", incvotes_post_path(post), :method=>:post
  

и если это не сработает, попробуйте изменить метод на:put

Комментарии:

1. При этом или put оба выдают ошибку: маршрут не совпадает с «/ posts / 1 /incvotes»

2. возможно, у вас в коде опечатка? У тебя есть post.update_attributes время, когда это должно быть @post.update_attributes . Хотя не уверен, вызовет ли это эту проблему. Не могли бы вы также опубликовать весь свой индексный вид и код контроллера, пожалуйста? Есть ли у вас учетная запись на github, где вы можете публиковать код для своей модели, контроллера и индексного представления? Возможно, просто вставьте его в pastie. Извините за беспокойство, но где-то что-то не так

3. у вас определенно есть опечатка в вашем методе incvotes — она должна быть @post.update_attributes — не могу сказать, исправит это или нет

4. Похоже на то. Теперь я получаю «слишком мало аргументов», и если я исправлю это, это должно сработать.

5. у вас слишком мало аргументов, когда вы меняете его на @post.update_attributes(:upvotes => 1) — я подумаю об этом

Ответ №2:

Я предполагаю, что у вас, вероятно, нет определения в вашем файле routes для действия, которое вы только что определили в контроллере. Для правильной генерации URL-адресов Rails должны быть определены как действие в контроллере, так и действие в файле routes.

В вашем файле routes, вероятно, есть что-то вроде этого:

 resources :posts
  

Но вы хотите добавить больше, чем стандартные действия, сгенерированные resources ключевым словом, поэтому попробуйте что-то вроде этого:

 resources :posts do 
  member do
    post 'incvotes'
  end
end
  

Это сообщает маршрутам, что у вас есть другое действие в вашем контроллере posts под названием incvotes, которое принимает HTTP-запросы post, если они указаны на маршрут участника с правильным действием (/posts/14 — маршрут участника, в то время как / posts / — маршрут «коллекции»). Таким образом, у вас будет новый маршрут, вероятно, подобный /posts/14/incvotes , на который вы можете отправить форму, и все должно начать работать должным образом.

Редактировать:

На самом деле, я думаю, поскольку вы просто добавляете 1 к атрибуту в модели, вам не нужны действия POST (которые обычно связаны с формами публикации, такими как create и update ). Чтобы отправить сообщение, вам может потребоваться изменить HTML-код в представлении, чтобы включить форму и отправить ее по правильному URL. Так что вы можете попробовать это, или вы можете изменить свой файл routes на read get 'incvotes' вместо post 'incvotes' . Извините за путаницу, надеюсь, это поможет!

Комментарии:

1. Мой файл маршрутов действительно выглядел так, поэтому я изменил его на этот, и кнопка голосования теперь выдает: Маршрут не совпадает с «/ posts / 1 / incvotes»

2. Можете ли вы запустить из командной строки rake routes и добавить результат к своему вопросу?

3. Вы пробовали перезапустить сервер? Я полагаю, что если вы вообще измените routes.rb файл, вам нужно перезапустить свой веб-сервер, чтобы изменения вступили в силу (даже если вывод rake routes выглядит правильно, ваш веб-сервер, возможно, не воспринял изменения, если он еще не был перезапущен).

4. Я только что попробовал перезапустить «rails server» и Apache, не помогло. Все еще переходим к domain.com/posts/1/incvotes и ошибка «Маршрут не совпадает» /posts/ 1 /incvotes»

5. Отредактировал мой ответ, чтобы дать больше информации о POST и GET

Ответ №3:

incvotes_post Маршрут принимает только HTTP POST, а ссылка всегда выдает HTTP GET.

Вместо этого используйте форму с кнопкой (или создайте сообщение с помощью AJAX).

Комментарии:

1. Практически в link_to документации указано, что передача :method параметра в качестве опции URL в link_to динамически создает HTML-форму с помощью метода post. Таким образом, вы можете технически использовать link_to для создания POST-запроса.

Ответ №4:

Попробуйте использовать button_to вместо link_to :

На ваш взгляд:

 <%= button_to 'Vote', incvotes_post_path(post) %>
  

В вашем config/routes.rb добавьте маршрут к incvotes действию как post :

 resources :posts do 
  member do
    post 'incvotes'
  end
end
  

И в вашем контроллере создайте incvotes действие:

 def incvotes
  # Something
  redirect_to :posts
end