сделать POST запрос в рельсах с гиперссылками - PullRequest
6 голосов
/ 15 августа 2010

Мне нужна куча ссылок на странице, каждая из которых создает POST для другого контроллера.Но когда я использую обычные ссылки, я получаю ошибку ActionController :: InvalidAuthenticityToken.Я понимаю, что это из-за отсутствующего значения authenticity_token.Но я не хочу использовать формы для выполнения POST, потому что я хочу, чтобы они были ссылками, а не кнопками.Дело в том, что я хочу полностью контролировать стиль ссылок и кнопок, просто не делайте это для меня.Какой стандартный способ делать такие вещи?

Ответы [ 5 ]

2 голосов
/ 15 августа 2010

У вас есть много вариантов.

  1. Отключить проверку AT: protect_from_forgery :only => []
  2. Назначить обработчик onclick для ссылки и отправить скрытую форму с помощью JavaScript.
  3. Возьмите AT во время генерации представления и добавьте его в качестве параметра запроса.

Кстати, как именно вы делаете «публиковать» запросы, используя только атрибут «href»?Я думал, что для этого нужна форма.

1 голос
/ 02 апреля 2011

Если вы используете jQuery, вы также можете сделать что-то вроде этого:

<!--  in your view --> 
<%= form_tag( user_free_dates_path(:user_id => @user.id), :remote => true ) do |f| %>
  <%= hidden_field_tag :date, current_day.to_s(:short_db)  %>
  <%= link_to "Allow", "#", :class => "submit"%>
<% end %>        

// in application.js
$("form a.submit").live("click", function(){
  $(this).closest("form").submit();
  return false;
}); 

Идея состоит в том, что вы создаете "реальную" форму в своем представлении без кнопки отправки. Затем link_to с классом submit отправит отправку формы. Конечный результат выглядит как ссылка, но на самом деле это форма. Я уверен, что есть аналогичный способ с использованием Prototype.

В моем примере user_free_dates_path (: user_id => @ user.id) является просто помощником пути, а hidden_field_tag ​​ является одним из параметров, которые я передаю мой запрос POST.

1 голос
/ 15 августа 2010

Технически говоря, вы должны использовать кнопки и формы для всего, что не является GET; гиперссылки намеренно не допускают использования методов, отличных от GET (без хаков, таких как параметр _method). Одна очень практическая причина заключается в том, что иногда надстройки браузера «веб-ускоритель» предварительно выбирают ссылки на странице; если ссылка GET запускает мутативное действие, состояние пользователя или ресурса может быть ошибочно изменено.

Тем не менее, вы можете стилизовать кнопки, чтобы они вели себя как ссылки; Я использую что-то вроде следующего, чтобы сделать это довольно красиво. Он предполагает правильный сброс CSS с полями и отступами, и все эти хорошие вещи обнуляются.

input.restlink {
  border: 0;
  background: #fff;
  color: #236cb0;
  cursor: pointer;
}
input.restlink:hover {
  text-decoration: underline;
}

С таким правилом вы можете использовать <%=button_to "Yay button", something_path, :method => :post %>, и оно будет отлично выглядеть и вести себя как ссылка.

0 голосов
/ 01 февраля 2014

Заимствование в значительной степени из этих ответов / источников

, чтобы получить кнопку, которая выглядит как ссылка, но работает как кнопка. В моем приложении / helpers / application_helper.rb:

def button_as_link(action, link_text, hiddens)
    capture do
        form_tag(action, :class => 'button_as_link') do
            hiddens.each { |k, v| concat hidden_field_tag(k.to_sym, v) }
            concat submit_tag(link_text)
        end
    end
end

CSS:

form.button_as_link {
  display: inline;
}

/* See https://stackoverflow.com/a/12642009/326979 */
form.button_as_link input[type="submit"], form.button_as_link input[type="submit"]:focus, form.button_as_link input[type="submit"]:active {
  /* Remove all decorations to look like normal text */
  background: none;
  border: none;
  display: inline;
  font: inherit;
  margin: 0;
  padding: 0;
  outline: none;
  outline-offset: 0;
  /* Additional styles to look like a link */
  color: blue;
  cursor: pointer;
  text-decoration: underline;
}
/* Remove extra space inside buttons in Firefox */
form.button_as_link input[type="submit"]::-moz-focus-inner {
  border: none;
  padding: 0;
}

и, наконец, в моем шаблоне я вызываю функцию button_as_link:

button_as_link('/some/path',{:key1=>:val1,:key2=>:val2}, 'text to display')
0 голосов
/ 15 августа 2010

Если вы не против использования jQuery и некоторого ajax'n, у меня есть сообщение в блоге , которое освещает это.

Вот некоторая основная информация, если вы хотите высокийобзор уровня.

Добавьте этот макет:

<%= javascript_tag "var AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? %>

Этот код добавляет токен аутентификации в ответ.Таким образом, JS может забрать его и отправить на сервер.

Затем мы перехватываем любой ajax-вызов в application.js:

function isPost(requestType) {
  return requestType.toLowerCase() == 'post';
}

$(document).ajaxSend(function(event, xhr, settings) {
  if (isPost(settings.type)) {
    settings.data = (settings.data ? settings.data + "&" : "") + "authenticity_token=" + encodeURIComponent( AUTH_TOKEN );
  }
  xhr.setRequestHeader("Accept", "text/javascript, application/javascript");     
});

Добавьте это в контроллер вашего приложения:

before_filter :correct_safari_and_ie_accept_headers
after_filter :set_xhr_flash

protected
    def set_xhr_flash
      flash.discard if request.xhr?
    end

    def correct_safari_and_ie_accept_headers
      ajax_request_types = ['text/javascript', 'application/json', 'text/xml']
      request.accepts.sort!{ |x, y| ajax_request_types.include?(y.to_s) ? 1 : -1 } if request.xhr?
    end

И по вашему мнению:

<%= link_to "Delete", delete_product_path(product), :class => 'delete' %>

Вернемся к application.js:

$('a.delete').live('click', function(event) {
  if(event.button != 0) { return true; }

  $.post(link.attr('href').substring(0, link.attr('href').indexOf('/delete')), { _method: "delete" });

  return false;
});

В этом примере выполняется удаление, но на самом деле это тот же процессобрабатывать сообщения или путы.В блоге есть пример приложения, которое демонстрирует это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...