link_to не запускает действие

У меня есть ниже в index.html.erb (объявлена ​​только важная часть объявления post)

<%=link_to yay_post_path(post), :remote=>true, class:'btn-default btn' do %>
  <span class="glyphicon glyphicon-chevron-up"></span>
<% end %>
<%=link_to nah_post_path(post), :remote=>true, class:'btn btn-default' do %>
  <span class="glyphicon glyphicon-chevron-down"></span>
<%end %>

И это в route.rb

resources :posts do
   member do
    put 'yay', to: 'posts#yay'
    put 'nah', to: 'posts#nah'
  end
end

И это в PostsController

  def yay
    @post = Post.find(params[:id])
    @post.liked_by current_user
    @redirect_to @post
  end

  def nah
    @post = Post.find(params[:id])
    @post.downvote_from current_user
    @redirect_to @post
  end

Обратите внимание, что вышеуказанные методы не имеют собственных представлений. Это просто специальные методы.

Когда я нажимаю на ссылку, я получаю сообщение об ошибке 404

cannot find /post/1/yay

Что можно исправить?


person Amit Joki    schedule 08.04.2015    source источник


Ответы (2)


Вы объявляете путь в маршрутизаторе с помощью html-метода put, поэтому вам необходимо соответствующим образом настроить свою ссылку. Обычная ссылка всегда http GET, но rails поможет вам, когда вы напишете:

<%=link_to yay_post_path(post), remote: true, method: :put, class:'btn-default btn' do %>
  <span class="glyphicon glyphicon-chevron-up"></span>
<% end %>

поэтому вы должны явно добавить http-метод, если он отличается от значения по умолчанию.

[EDIT: обработка js в контроллере] Для обработки js в контроллере есть два варианта:

ничего не возвращать

def yay
  respond_to do |format|
    format.js do 
      @post = Post.find(params[:id])
      @post.liked_by current_user
      head :ok
    end
  end
end

Примечание: это вернет статус http 406 для html-вызовов, чего я и хотел бы :)

Более стандартным подходом было бы

def yay
  @post = Post.find(params[:id])
  @post.liked_by current_user
  respond_to do |format|
    format.html { @redirect_to @post }
    format.js   { head :ok }
  end
end

Но это зависит от того, что вы хотите поддерживать (например, разрешить откат к стандартному html или нет).

Если вы хотите обновить представление, которое я хотел бы (иначе они могли бы продолжать возмущаться и отрицать, если вы не справитесь с этой стороной браузера), вы можете сделать что-то вроде:

def yay
  respond_to do |format|
    format.js do 
      @post = Post.find(params[:id])
      @post.liked_by current_user
    end
  end
end

и добавьте представление yay.js.erb, содержащее

$('#yays_and_nays').hide()

или например обновить часть представления

$(#yays_and_nays').replaceWith('<% escape_javascript(render 'yay_or_nayed_status') %>');
person nathanvda    schedule 08.04.2015
comment
Плюс 1, но я получаю 400: Bad Request что мне делать? - person Amit Joki; 08.04.2015
comment
Вы не обрабатываете или не разрешаете format.js в контроллере? Перенаправление не имеет смысла для js. Так что удалите remote: true или обработайте format.js. - person nathanvda; 08.04.2015
comment
Поэтому я должен использовать fomat.js. Хорошо, понял. Спасибо. - person Amit Joki; 08.04.2015
comment
Я использую пустой respond_to do |format| format.html {} format.js {} format.json {} end, так как не хочу ничего возвращать, но это вызывает внутреннюю ошибку 500. Как я могу это реализовать? Извините, я новичок в рельсах, кстати. - person Amit Joki; 08.04.2015
comment
Нет проблем, я немного расширил свой ответ. Короче говоря: используйте head :ok для js. - person nathanvda; 08.04.2015

на ваших маршрутах...

put 'yay', to: 'posts#yay'

это PUT, так что вам также нужно включить :method=>"put"в link_to.

person Milind    schedule 08.04.2015