This may end up being very simple but I have been trying to figure this out to no avail. I am using wicked_pdf to render pdfs on html pages. When I do this the restful way by adding the respond_to block to a controllers show action everything works fine when going to controller/id.pdf.
What I am trying to do however, is use the respond_to block on a custom controller action. I have a reports controller which has many reports and custom actions. One of these reports has a form which is submitted to another custom controller action to render the report. This all works fine with the html render however, when I added the respond_to block to this custom action it simply tells me it cannot find the show action for that controller. Below is the related code:
routes.rb
resources :reports do
collection do
get 'customer_summary'
post 'summary_report'
end
end
reports_controller.rb
def summary_report
#tickets = tickets
respond_to do |format|
format.html
format.pdf do
render pdf: "summary_report", header: {spacing: 10, html: {template: 'shared/header'}}, footer: {html: {template: 'shared/footer'}}, margin: { top: 20, bottom: 20 }
end
end
The templates exsist as well as the summary_report.pdf.haml file. What am I doing wrong? Thank you in advance for your help!
Related
I'm making AJAX based application with Devise as authentication system. The problem I encountered is that when I sign in with Devise with AJAX, then when view changes and log out button appears it's showing this error when clicked:
ActionController::InvalidAuthenticityToken in Customization::SessionsController#destroy
ActionController::InvalidAuthenticityToken
Parameters:
{"_method"=>"delete",
"authenticity_token"=>"hitX5aEjoTzi3tKP3y76+c60MuJumv5mwNEjyGUOQiY="}
Here you have my devise session controller's create method for signing in (I had to change few things to make AJAX happen):
# POST /resource/sign_in
def create
self.resource = warden.authenticate!(auth_options)
sign_in(resource_name, resource)
yield resource if block_given?
if user_signed_in?
flash[:logged] = "Zalogowany"
respond_to do |format|
format.html { redirect_to root_path }
format.js { render "sign_in_success.js.erb" }
end
end
end
sign_in_success.js.erb file:
$("body").empty();
$("body").append("<%= j(render template: 'layouts/user') %>");
button inside "layouts/user":
a href="#{destroy_user_session_path}" data-method="delete" rel="nofollow"
button.btn.btn-primary.m-r-20 type="button"
b Log Out
How do I send Authenticity Token with AJAX? Can I send it to "layouts/user" via locals option in render and use it this way?
I have solution. The problem was that csrf_meta_tags, was not updated when new session was created. The solution to that problem was to include additional code inside sign_in_success.js.erb file:
$("body").empty();
$("meta[name='csrf-token']").remove()
$("meta[name='csrf-param']").remove()
$("head").append("<meta name='csrf-token' content='<%= form_authenticity_token %>'>");
$("head").append("<meta name='csrf-param' content='<%= request_forgery_protection_token %>'>");
$("body").append("<%= j(render template: 'user/logged_signed') %>");
With code seen above firstly we are empting body element , then we are removing from DOM meta tags created by csrf_meta_tags helper. After that we are manually adding new csrf-token and csrf-param, this time our new authenticity token is assigned to meta name="csrf-token".
After that when we click on our log_out button rendered by "user/logged_signed" template we are logged out successfully and back at our root_path.
I'm having some problems to update my div after submitting a form with Rails 4. Here is the relevant part of my code:
View:
_details.html.haml
= form_tag(url_for(save_answer_path(format: :js)), remote: true) do
(some html code ....)
= submit_tag t('app.bouton.send'), id: 'sendButton'
%div#divlogs
= render partial: 'logs'
Controller:
def save_answer
some code ...
respond_to do |format|
format.js
end
end
JS:
save_answer.js.erb
$('#divlogs').html("<%= escape_javascript(render partial: 'logs') %>");
When I submit, everything is called correctly but I'am getting an incorrect output. What I want is to update my div, but instead I get a page with what I have on my JS file, but with the content of my partial.
Example:
My URL after submitting:
http://domaine/controller/save_answer.js
What I get on the screen:
$('#divlogs').html("<p>This should appear on the div </p>");
Does anyone know what is going on?
Solution:
As #VladKhomich said in the comments above, I was missing the JS file rails.js.
You can download it from here: https://github.com/rails/jquery-ujs/blob/master/src/rails.js
I'm trying to make a form in Rails that will respond with a js file. Right now, I have a file in app/assets/javascripts/login.js.coffee.erb that I'd like to be returned when the user submits the form via ajax (I've got users without javascript enabled working fine). Here's my template code for the form:
<%= form_tag("/trade/submit", :method => "post", :remote => true) do %>
# some stuff in here
<% end %>
In my trade controller, I have a method submit, which follows:
def submit
respond_to do |format|
format.html { render :layout => 'widget' + #widget_type.to_s, :template => 'login/index' }
format.js { render :action => 'login', :content_type => 'text/javascript' }
end
end
My respond with html works fine, but when calling the form via ajax, it returns this response:
Missing template trade/submit, application/submit with {:handlers=>[:erb, :builder, :coffee], :formats=>[:js, :html], :locale=>[:en, :en]}. Searched in:
* "~/app_dir/app/views"
Obviously, it shouldn't be looking in views, but rather in javascripts, right? I tried removing the render block after format.js (keeping it default so it will look for submit), and I get the same problem. Does this mean I have to save my js files in my views directory? Seems kinda messy, so I feel like surely I must just be doing something wrong. Any help is greatly appreciated!
It tries to find app/view/trade/submit.js.erb! Try to do a simple test.
touch app/view/trade/submit.js.erb
vim app/view/trade/submit.js.erb
alert('done!');
And run it again.
Ch8 of Beginning Rails book has an Ajax forms example which works ok except it does not output an alert for invalid input.
The controller code is:
def create
#comment = #article.comments.new(params[:comment])
if #comment.save
respond_to do |format|
format.html { redirect_to #article, :notice => 'Thanks for your comment' }
format.js
end
else
respond_to do |format|
format.html { redirect_to #article, :alert => 'Unable to add comment due to errors in your input'}
# logger.info("#{Time.now} Ajax invalid validation
##{#comment.errors.full_messages}!")
format.js { render 'fail.js.erb' }
end
end
end
The 'fail_create.js.erb' file contains the one line;
alert("<%= #comment.errors.full_messages.to_sentence %>");
Can some kind person explain why this is not working, thank you
You are rendering "fail.js.erb" but in your question you say the file "fail_create.js.erb" contains the code. Is that a typo in your question or is that the problem in your code?
Also, using RJS is considered bad form in Rails. If you are going through the example as a learning experience more power to you, but it was a failed experiment in the Rails community. Javascript should live on its own (and preferably be added to a site unobtrusively).
Book says to use jQuery 1.4.2
Upgraded to 1.4.4 and all worked well
I'm trying to add some Ajax functionality in my Rails 3 app.
Specifically, I want a button that will submit an Ajax request to call a remote function in my controller, which subsequently queries an API and returns a JSON object to the page.
Once I receive the JSON object I want to display the contents.
All of this with the new Rails 3 UJS approach, too. Is there a good example/tutorial for this online somewhere? I haven't been able to find one on google. A simple example using a button as the entry point (ie, the user clicks the button to start this process) would work, too.
Edit
Let me try this with a different approach. I want to have this button query an external API, which returns JSON, and display that JSON on the page. I have no idea where to even begin. Does the button itself query the external API? Do I need to go through the controller, and have the controller query the external API, get the JSON, and give the JSON back to this page? How do I display/access the contents of this JSON? I honestly can't find a good Rails 3.x example of how to handle JSON...
Here is a start:
First create your button with a link_to method in your view, for example:
=link_to "delete", "#{invitation_path(invitation)}.json", :method=>:delete, :remote=>true, :class=>"remove", :confirm=>'Are you sure you?'
Note that I am appending ".json" to the url of my resource. This is just an example of a an AJAX delete, google link_to to see the meaning of the parameters. The concept if that you make your HTTP request with the parameter :remote set to true, in other words this is translated to an AJAX call from your browser.
Second, write some javascript so that you can process what ever is the result of the AJAX call your browser will make when the user click on the link_to of step 1. For details you can see this blog post: http://www.alfajango.com/blog/rails-3-remote-links-and-forms/
An example from my site:
jQuery(function($) {
// create a convenient toggleLoading function
var toggleLoading = function() { $("#loading").toggle() };
$("#pending_invitation")
.live("ajax:loading", toggleLoading)
.live("ajax:complete", toggleLoading)
.live("ajax:success", function(event, data, status, xhr) {
var response = JSON.parse(xhr.responseText)
if (response.result == "ok") {
$(this).fadeOut('fast');
}
else {
var errors = $('<div id="error_explanation"/>');
errors.append('<h2>Pending invitation action error</h2><ul><li>' + response.error + '</li></ul>');
$('#new_invitation_error').append(errors)
}
});
});
where you can see that I parse the returned json and and change the html on the page based on that. Note that this js uses the CCS ids and classes defined in the top view that is not included here.
If you now want to write you own controller to spit out the json here is an example:
class InvitationsController < ApplicationController
respond_to :html, :json
# other methods here
# ...
def destroy
#invitation = Invitation.find(params[:id])
respond_to do |format|
if #invitation
#invitation.destroy
flash[:success] = I18n.t 'invitations.destroy.success'
format.json { render :json =>{:result => "ok", :message=>"Invitation #{params[:id]} was destroyed", :resource_id=>params[:id] } }
else
format.json { render :json => { :result=>"failed", :error=>"Cannot find Invitation #{params[:id]}", :resource_id=>params[:id] } }
end
end
end
end
Hope this help.
Old question, but a really good overview of Ajaxifying Rails applications is:
Ajax in Rails 3.1 - A Roadmap
Also consider returning errors in the following format:
render :json => #myobject.to_json, :status => :unprocessable_entity
This will ensure that your client can process the response as an error.