Necesito un montón de enlaces en una página cada uno de los cuales hace una POST a un controlador diferente. Pero cuando uso enlaces normales, obtengo un error ActionController :: InvalidAuthenticityToken. Entiendo que esto se debe al valor de authenticity_token faltante. Pero no quiero usar formularios para hacer el POST porque quiero que sean enlaces y no botones. El hecho es que quiero un control total sobre el estilo de los enlaces y botones, pero no lo hago por mí. ¿Cuál es la forma estándar de hacer tales cosas?haciendo la solicitud POST en rieles con hipervínculos
Respuesta
Tienes muchas opciones.
- Desactivar el momento del registro:
protect_from_forgery :only => []
- Asignar onclick manejador al enlace y presentar formulario oculto con javascript.
- Capture AT mientras se genera la vista y agréguela como parámetro de solicitud.
Por cierto, ¿cómo se hacen las solicitudes 'post' usando solo el atributo 'href'? Pensé que la forma es imprescindible para eso.
Técnicamente hablando, debe usar botones y formularios para cualquier cosa que no sea GET
; los hipervínculos intencionalmente no permiten métodos distintos de GET
(sin hacks como el parámetro _method
). Una razón muy práctica es que, a veces, los complementos del navegador "web accelerator" captan previamente los enlaces en la página; si un enlace GET inicia una acción mutativa, el usuario o el estado del recurso pueden modificarse erróneamente.
Dicho esto, puede hacer que los botones se comporten como enlaces; Uso algo como lo siguiente para hacerlo bastante bien. Supone un restablecimiento CSS adecuado con márgenes y relleno y todas esas cosas buenas que se anulan.
input.restlink {
border: 0;
background: #fff;
color: #236cb0;
cursor: pointer;
}
input.restlink:hover {
text-decoration: underline;
}
Con una regla de esa manera, puede utilizar <%=button_to "Yay button", something_path, :method => :post %>
y va a buscar y se comportan como un vínculo muy bien.
Consideré esto, pero no funcionó porque aún hay ese molesto efecto push cuando se mueve hacia abajo en un botón; junto con una línea de puntos alrededor de él en algunos navegadores. – akula1001
Con un restablecimiento CSS adecuado, ninguno de esos es el caso. Puede establecer 'outline: none' para los navegadores que muestran el rectángulo sucio. –
Si no se opone al uso de jQuery y algunos ajax'n, tengo un blog post que cubre esto.
Aquí hay información básica si desea una descripción general de alto nivel.
Añadir ésta su diseño:
<%= javascript_tag "var AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? %>
Este código añade el token de autenticación a la respuesta. De esta forma, el JS puede recogerlo y enviarlo al servidor.
continuación interceptar cualquier llamada Ajax en los 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");
});
Agregar a su controlador de aplicación:
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
Y en su opinión:
<%= link_to "Delete", delete_product_path(product), :class => 'delete' %>
Volver a 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;
});
Este ejemplo realiza una eliminación, pero en realidad es el mismo proceso para manejar las publicaciones o las publicaciones. La publicación del blog tiene una aplicación de muestra completa que demuestra esto.
Si está utilizando jQuery, también podría hacer algo como esto:
<!-- 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;
});
La idea es que se genera una forma "real" en su opinión, sin un botón de envío. Entonces, el link_to con la clase "submit" activará un envío de formulario. El resultado final parece un enlace, pero realmente es una forma. Estoy seguro de que hay una forma similar de usar Prototype.
En mi ejemplo, user_free_dates_path (: user_id => @ user.id) es sólo un ayudante camino, y la hidden_field_tag es uno de los parámetros que estoy pasando en mi solicitud POST.
préstamos en gran medida a partir de estas respuestas/fuentes
- 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/
para obtener un botón que sólo se parece a un enlace, sino que funciona como un botón. En mi app/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;
}
y finalmente en mi plantilla, llamo a la función button_as_link:
button_as_link('/some/path',{:key1=>:val1,:key2=>:val2}, 'text to display')
- 1. Haciendo solicitud HTTP POST
- 2. Enviar solicitud POST con netcat
- 3. solicitud POST en Symfony2
- 4. ¿Cómo enviar la solicitud POST?
- 5. Django jQuery solicitud POST
- 6. Utilice la solicitud POST en JSfiddle
- 7. Solicitud POST usando RCurl
- 8. Pubsubhubbub en rieles. ¿Cómo extraer el contenido del cuerpo de POST sin procesar de la solicitud de POST?
- 9. Modificar solicitud POST en mod_perl2
- 10. WPF - Haciendo que los hipervínculos se puedan hacer clic
- 11. Solicitud 'post' método no soportado
- 12. Django - solicitud POST
- 13. ¿Cómo enviar la solicitud HTTP POST con contenido gziped?
- 14. Solicitud web C# con la pregunta de codificación POST
- 15. Redirigir después de la solicitud POST con jquery
- 16. ¿Cómo pruebo la solicitud POST ajax con RSpec?
- 17. AFNetworking - ¿Cómo hacer solicitud POST
- 18. solicitud POST jQuery (no AJAX)
- 19. Apache HttpClient haciendo multiparte formulario post
- 20. solicitud POST y PUT AFNetworking
- 21. Hipervínculos en JLabels
- 22. Emita una solicitud POST con url_for en Flask
- 23. ¿Cómo envío una solicitud POST en RestSharp?
- 24. Obtenga hipervínculos PDF en iOS con Quartz
- 25. Haciendo una página web con ruby sin rieles
- 26. Envío de solicitud POST a acción segura
- 27. Cómo recibir JSON en la solicitud POST de node.js express?
- 28. Obtener el tamaño de la solicitud POST en PHP
- 29. ¿Restaurar la solicitud POST original después de la autenticación CAS?
- 30. ¿Cómo puedo actualizar la sesión durante una solicitud POST?
Carriles le permite especificar un '_method = (PUT | POST | DELETE) 'parámetro de consulta e interpretará la solicitud como si hubiera sido hecha con ese método. Es principalmente para apoyar 'PUT' /' DELETE' que no tienen soporte completo para el navegador. –
Realmente no conozco las implicaciones de seguridad de deshabilitar la verificación AT. Sin embargo, podría intentar agregarlo como un parámetro de solicitud. Pero el POST se hace a un controlador diferente de lo que creó esta vista. ¿Debería eso importar? ¿Cuál es el alcance de este token? – akula1001
@ manu1001 Por lo que tengo entendido, AT se crea para una sesión particular. Por lo tanto, debería funcionar. De todos modos, es fácil de probar: 'my_url? Authenticity_token = <% = form_authenticity_token%>' –