создание запроса POST в rails с гиперссылками
Мне нужна куча ссылок на странице, каждая из которых делает сообщение другому контроллеру. Но когда я использую обычные ссылки, я получаю ошибку ActionController::InvalidAuthenticityToken. Я понимаю, что это из-за недостающего значения authenticity_token. Но я не хочу использовать формы для публикации, потому что я хочу, чтобы они были ссылками, а не кнопками. Дело в том, что я хочу полный контроль над стилем ссылок и кнопок, просто не делайте этого за меня. Какой способ ведения таких вещи?
5 ответов
у вас есть много вариантов.
- отключить при регистрации:
protect_from_forgery :only => []
- назначьте обработчику onclick ссылку и отправьте скрытую форму с помощью javascript.
- захватить во время создания представления и добавить его в качестве параметра запроса.
кстати, как именно вы делаете запросы "post", используя только атрибут "href"? Я думал, для этого нужна форма.
Технически говоря, вы должны использовать кнопки и формы для всего, что не является GET
; гиперссылки намеренно не допускают методов GET
(без хаков вроде
Если вы используете 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.
если вы не против использования jQuery и некоторых ajax'N, у меня есть блоге что это покрывает.
вот некоторые основные сведения, если вы хотите обзор высокого уровня.
добавьте этот ваш макет:
<%= javascript_tag "var AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? %>
этот код добавляет маркер auth в ответ. Таким образом, JS может забрать его и отправить на сервер.
Далее мы перехватываем любой вызов ajax в приложении.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' %>
вернуться к применению.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;
});
в этом примере выполняется удаление, но это действительно тот же процесс для обработки сообщений или puts. Сообщение в блоге имеет полный пример приложения, которое демонстрирует это.
заимствования в значительной степени из этих ответов / источников
- https://stackoverflow.com/a/3486036/326979
- https://stackoverflow.com/a/12642009/326979
- http://juliankniephoff.wordpress.com/2011/03/23/using-form_for-in-helper-methods/
получить кнопку, которая выглядит как ссылка, но работает как кнопка. В моем app / помощники / 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')