Using wicked_pdf, save as pdf including user supplied data - ruby

I have a template to be filled out by a user. My goal is to convert the template into a pdf (containing information supplied by the user) using wicked_pdf.
Also, none of the user input is hitting the model/database. I simply need to convert the template to a pdf containing the user's data, nothing more.
So far, I can convert the template to a pdf, save it and redirect back to my index view. However, none of the fields filled in by the user are saved; all fields that were containing input or values typed by the user are blank. It's simply saving a blank template. How can I convert a pdf and user supplied data to a pdf using wicked_pdf?
# controller save method --->
def save_grade_sheet
#result = Result.find(params[:id])
if current_user.admin?
filename = "#{#result.user.last_name}_grades.pdf"
save_path = "#{Rails.root}/public/uploads/#{#result.user.last_name}/#{filename}"
respond_to do |format|
pdf = render_to_string pdf: filename,
template: "/results/grade_sheet.html.erb",
encoding: "UTF-8",
disposition: "attachment",
save_to_file: save_path,
save_only: true
File.open(save_path, "wb") do |file|
file << pdf
end
flash[:notice] = "#{filename} successfully saved"
format.html { redirect_to results_path }
end
else
head :unauthorized
end
end
# sample template code
<div>
<div>
<h2>PERSONNEL INFORMATION</h2>
<p>Examinee's Name: <%= #result.user.first_name %> <%= #result.user.last_name %></p>
<p>Examiner's Name: <input class="inline" type="text"></p>
</div>
<div>
<p>Exam Type: <%= #result.test.upcase %></p>
<p>Exam Version: <input class="inline" type="text"></p>
<p>Exam Date: <%= #result.created_at.strftime("%m-%d-%y") %></p>
</div>
<%= button_to "Create Grade Sheet", save_grade_sheet_result_path(#result), data: { method: :post }, class: "btn btn-primary btn-lg"%>
</div>

I was sending everything to the correct route, but none of the data was actually being passed. Instead, I needed to wrap everything in a form_tag and use a submit_tag.
<%= form_tag(save_grade_sheet_result_path(#result), method: :post) %>
<div>
<h2>PERSONNEL INFORMATION</h2>
<p>Examiner's Name: <%= text_field_tag :examiner_name, #examiner_name, class: "inline" %></p>
<p>Exam Version:<%= text_field_tag :exam_version, #exam_version, class: "inline" %></p>
</div>
<%= submit_tag "Create Grade Sheet", class: "btn btn-primary btn-lg" %>
<% end %>
And in my controller, I needed to grab the params passed in:
def save_grade_sheet
#result = Result.find(params[:id])
#examiner_name = params[:examiner_name]
#exam_version = params[:exam_version]
if current_user.admin?
# existing code
end
end

Related

How to update feed using ajax in Rails 4.0

I am trying to create an ajax functionality for a sample app of michael heart book . I created a feed model controller which is micropost in hear book . I am trying to use ajax like post feed method . But I am getting some error . I am attaching my code below take a look and help me .
#feeds_controller.erb
class FeedsController < ApplicationController
before_action :authenticate_user! ,only: [:create, :destroy]
def create
#feed = current_user.feeds.build(feed_params)
if #feed.save
flash[:success] = "Micropost created!"
#redirect_to root_url
respond_to do |format|
format.html { redirect_to root_url }
format.js
else
#feed_items = []
render 'static_pages/home'
end
end
def destroy
end
private
def feed_params
params.require(:feed).permit(:content)
end
end
And my home page is rendering some partials Here is the code :
#static_pages/home.html.erb
<% if user_signed_in? %>
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<%= render 'shared/user_info' %>
</section>
<section class="stats">
<%= render 'shared/stats' %>
</section>
</aside>
<div class="col-md-8">
<h3>Micropost Feed</h3>
<section class="micropost_form">
<%= render 'shared/feed_form' %>
</section>
<%= render 'shared/feed' %>
</div>
</div>
<% else %>
<% end %>
Here are two codes Everything work perfectly but when I am trying to add ajax I get the error which is :
Rendered shared/_feed.html.erb (3.1ms)
Rendered feeds/create.js.erb (6.0ms)
Completed 500 Internal Server Error in 73ms (ActiveRecord: 44.4ms)
NoMethodError (undefined method `any?' for nil:NilClass):
app/views/shared/_feed.html.erb:1:in `_app_views_shared__feed_html_erb___516512175__638262078'
app/views/feeds/create.js.erb:1:in `_app_views_feeds_create_js_erb___967625174__637838198'
app/controllers/feeds_controller.rb:9:in `create'
To execute ajax on create method I added these files unders feeds views file name is create.js.erb
$("#feed_add").html("<%= escape_javascript(render partial: "shared/feed") %>");
And form file is under shared view file with name _feed_form.html.erb
<%= form_for(#feed,:remote => true) do |f| %>
<div id="feed_add">
<%= f.text_area :content, placeholder: "Compose new feed..." %>
</div>
<%= f.submit "Post", class: "btn btn-primary" %>
<% end %>
#_feed.html.erb
<% if #feed_items.any? %>
<ol class="microposts">
<%= render #feed_items %>
</ol>
<%= will_paginate #feed_items %>
<% end %>
So tell me how can I add feed and without refreshing how can I show feed using partial In this code .
Here you simply need to render one thing that is feed for that in micheal heart book you simply add this line of code inside your create ajax file here is the code :
$(".microposts").prepend('<%= j render #feed %>');
Here you can get the result what you want .

Else part is not working in Rails ajax form

I have a Rails ajax form to submit.When user will give the correct data it will search the database and do the operation accordingly.If user is giving the Wrong data it should display user to alert message.But it is not happening like that.
I am explaining my codes below.
home.html.erb
<% if current_admin %>
<p class="flash-message"><%=flash[:notice]%></p>
<div class="col-md-6" style="float:none; margin:auto;">
<%= form_for :sdf ,:url => {:action => "scan_report" },remote: true do |f| %>
<% if params[:receipt_no] %>
<div class="input-group bmargindiv1 col-md-12"> <span class="input-group-addon text-left">Receipt No. Scan :</span>
<%= f.text_field :Receipt_No,:class => "form-control", :value => params[:receipt_no] %><%= f.submit "Scan Report" %>
</div>
<% else %>
<div class="input-group bmargindiv1 col-md-12"> <span class="input-group-addon text-left">Receipt No. Scan :</span>
<%= f.text_field :Receipt_No,:class => "form-control",placeholder:"Receipt No. scan" %><%= f.submit "Scan Report" %>
</div>
<% end %>
<% end %>
<% end %>
controller/homes_contorller.rb
class HomesController < ApplicationController
def home
#sdf=TSdf.new
respond_to do |format|
format.html
format.js
end
end
def scan_report
if #sdf=TSdf.find_by_Receipt_No(params[:sdf][:Receipt_No])
if #sdf && #sdf.HCSY_Status=='YES'
#hcsy=THcsy.find_by_Sdp_Id(#sdf.Sdp_Id)
#hcsy_deatils=THcsyDetails.find_by_HCSY_ID(#hcsy.id)
#woods=THcsyFundTypeMaster.find_by_Fund_Type_Code(1)
#burn=THcsyFundTypeMaster.find_by_Fund_Type_Code(2)
#good=THcsyFundTypeMaster.find_by_Fund_Type_Code(3)
#swd=THcsyFundTypeMaster.find_by_Fund_Type_Code(5)
#photo=THcsyFundTypeMaster.find_by_Fund_Type_Code(6)
end
else
flash[:notice]="Not Found"
end
end
end
In this form its only taking the correct input but if user is trying to give the wrong input the else part is not executing.Please help me to resolve this error and let me to know how can i make this ajax call in below format.
$('form').submit(function() {
var valuesToSubmit = $(this).serialize();
$.ajax({
type: "POST",
url: $(this).attr('action'), //sumbits it to the given url of the form
data: valuesToSubmit,
dataType: "JSON" // you want a difference between normal and ajax-calls, and json is standard
}).success(function(json){
console.log("success", json);
});
return false; // prevents normal behaviour
});
Please help me.I am using Rails version 3.2.19.
Here you send AJAX POST request to scan_report, and if it is successful it should render template scan_report.js.erb, and rendered template will appear in json variable in success callback.
But if params are not valid, the same template is rendered, but all instance variables are missing. And probably empty json is returned or an error appears in log.
Anyway, if you'd like to change flash in remote form, you should put custom code in fail callback. Something like
$("#flash").html('<%= j render flash[:notice] %>');

Carrierwave error messages not being displayed

I have a form that uploads files via an ajax call (using the remotipart gem), not sure if this is related but when validation fails with file type (using carrierwave white list), I can't get the error message to display in the view, even though other error messages will show (say when file size is to large).
So in my Uploader class
class MediaUploader < CarrierWave::Uploader::Base
def extension_white_list
%w(jpg jpeg gif png docx mp4 pdf)
end
end
So in my form I will attatch a csv file, click submit and the request and responses look like so
Processing by DocumentsController#create as JS
Parameters: {"utf8"=>"✓",
"document"=>
{"skill_id"=>"1",
"media_cache"=>"",
"media"=>#<ActionDispatch::Http::UploadedFile:0x000000070157a0 #tempfile=#<Tempfile:/tmp/RackMultipart20150205-4409-ltyy7t.csv>, #original_filename="csvtest.csv", #content_type="text/csv", #headers="Content-Disposition: form-data; name=\"document[media]\"; filename=\"csvtest.csv\"\r\nContent-Type: text/csv\r\n">},
"commit"=>"Upload",
"remotipart_submitted"=>"true",
"authenticity_token"=>"token here",
"X-Requested-With"=>"IFrame",
"X-Http-Accept"=>"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01"
}
(1.8ms) BEGIN
(2.7ms) ROLLBACK
In my controller I have grabbed the error messages #document.errors
#<ActiveModel::Errors:0x0000000666e418
#base=#
<Document id: nil,
media: nil,
user_id: 1,
skill_id: 1,
created_at: nil,
updated_at: nil>,
#messages={:media=>[
"You are not allowed to upload \"csv\" files, allowed types: jpg, jpeg, gif, png, docx, mp4, pdf",
"At least 1 File is required"
]
}>
After this the relevant controller action/views are called
Rendered documents/_document_form.html.erb (5.1ms)
Rendered documents/create.js.erb (7.7ms)
Completed 200 OK in 167ms (Views: 83.2ms | ActiveRecord: 64.6ms)
My form is set out to iterate through each of the error messages but it doesn't display them
_document_form
<%= form_for #document, remote: true, html: { multipart: true, id: #document.object_id.to_s, class: 'upload_document' } do |f| %>
<% if #document.errors.any? %>
<h2><%= pluralize(#document.errors.count, "error") %> prohibited this record from being saved</h2>
<ul class="error_list">
<% #document.errors.full_messages.each do |msg| %>
<li><%= error_edit(msg) %></li>
<% end %>
</ul>
<% end %>
<%= f.hidden_field :skill_id %>
<%= f.label :media %>
<%= f.file_field :media %>
<%= f.submit 'Upload', class: 'btn btn-success' %>
<div class="js-error"></div>
<% end %>
create action
def create
#document = current_user.documents.new(document_params)
respond_to do |format|
if #document.save
format.html { redirect_to root_path, notice: success_save_msg }
#format.js { render :js => "window.location.href='"+root_path+"'", notice: success_save_msg }
else
format.html
format.js { render action: 'create.js.erb' }
ap(#document.errors)
end
end
end
create.js.erb
$("#<%= #document.skill_id %>").html("<%= j render(partial: 'documents/document_form', locals: { skill_id: #document.skill_id }) %>")
Also I'm looking at the response in the net tab and it's clearly returning the error messages:
<textarea data-type="text/javascript" data-status="200" data-statusText="OK">$
("#1").html("<\n<form id=\"55100200\" class=\"upload_document\" enctype=\"multipart/form-data\" action=\"/documents\" accept-charset=\"UTF-8\" data-remote=\"true\" method=\"post\"><input name=\"utf8\" type=\"hidden\" value=\"✓\" />\n <div id=\"error_explanation\" class=\"alert alert-dismissable\">\n <button type=\"button\" class=\"close\" data-dismiss=\"alert\"><span aria-hidden=\"true\">×<\/span><span class=\"sr-only\">Close<\/span><\/button>\n <h2>2 errors prohibited this record from being saved<\/h2>\n <ul class=\"error_list\">\n <li> You are not allowed to upload "csv" files, allowed types: jpg, jpeg, gif, png, docx, mp4, pdf<\/li>\n <li> At least 1 File is required<\/li>\n <\/ul>\n <\/div>\n\n <input value=\"1\" class=\"skill_id\" type=\"hidden\" name=\"document[skill_id]\" id=\"document_skill_id\" />\n\n <label class=\"custom-file-upload btn btn-info\" for=\"document_media_60835260\">\n <span class=\"glyphicon glyphicon-cloud-upload\"><\/span>\n Find File\n<\/label>\n <input class=\"document_file_field\" id=\"document_media_60835260\" type=\"file\" name=\"document[media]\" />\n <input type=\"hidden\" name=\"document[media_cache]\" id=\"document_media_cache\" />\n\n <input type=\"submit\" name=\"commit\" value=\"Upload\" class=\"btn btn-success\" />\n <div class=\"js-error\"><\/div>\n\n<\/form>")
</textarea>
Can anyone see why the error messages would not display when coming from carrierwave as opposed to a validation from within my Document model?
Thought I Would share this so if anyone else has the same problem it might help. I came across this this Blog. Which then led me to This stackoverflow post.
Turns out i just needed to set the message (or custom message if I wanted) in my en.yml file and carrierwave did the rest
en:
errors:
messages:
extension_white_list_error: 'My Custom Message'
Hope this helps someone
Thats my en.yml
en:
hello: "Hello world"
errors:
messages:
extension_white_list_error: 'My Custom Message'
EDIT This fixed my script
en:
# hello: "Hello world"
errors:
messages:
extension_whitelist_error: "You are not allowed to upload %{extension} files, allowed types: %{allowed_types}"

Save record in rails 4.0 using params hash

I'm trying to create a new record in rails using the form_for helper method. I think the params hash is blank because I keep getting blank errors when I submit the form.
This is my form:
<% provide(:title, "Add Department") %>
<h1>Add Department</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(#department) do |f| %>
<%= render 'shared/department_error_messages' %>
<%= f.label :Full_Department_Title %>
<%= f.text_field :full_name %>
<%= f.label :Department_Abbreviation %>
<%= f.text_field :abbreviation %>
<%= f.submit "Add department", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>
This is my departments controller
class DepartmentsController < ApplicationController
def show
#department = Department.find(params[:id])
end
def new
#department = Department.new
end
def create
#department = Department.new(params[department_params]) # Not the final implementation!
if #department.save
redirect_to root_path
else
render 'new'
end
end
private
def department_params
# This says that params[:department] is required, but inside that, only params[:department][:full_name] and
# params[:department][:abbreviation] are permitted. Unpermitted params will be stripped out
params.require(:department).permit(:full_name, :abbreviation)
end
end
This is the Model:
class Department < ActiveRecord::Base
validates :full_name, presence: true, length: { minimum: 6 }
end
When I submit, errors are rendered saying the full_name can't be blank (and the fields are now empty). The debug info is:
--- !ruby/hash:ActionController::Parameters utf8: ✓
authenticity_token: EjfYjWAzaw7YqVZAkCPZwiEMFfb2YLIRrHbH1CpZOwA=
department: !ruby/hash:ActionController::Parameters
full_name: Sports Department
abbreviation: SD
commit: Add department
action: create
controller: departments
I've also checked the development log. The transaction starts and is then rolled back. I can save a record in the console so I'm guessing its something to do with the params hash, but can't figure it out. Please help
This line:
#department = Department.new(params[department_params])
Should be:
#department = Department.new(department_params)
And, as a minor issue (but not causing this problem), your label tags should look like:
f.label :full_name, "Full Department Title"
This way they are correctly associated with the input.

RoR: How can I get my microposts to show up?

Here is the users show view where they are supposed to show up. ..
<section>
<div id= "purchases">
<%= render 'shared/micropost_form_purchase' %>
</div>
<div id="sales">
<%= render 'shared/micropost_form_sale' %>
</div>
</section>
<%= #sales %> <%# This is just to see if it outputs anything. It doesn't :( %>
<div id="purchases list">
<ol class="microposts">
<%= render #purchases unless #purchases.nil? %>
</ol>
</div>
<div id="sales list">
<ol class="microposts">
<%= render #sales unless #sales.nil? %>
</ol>
</div>
so the forms (partials) are loading fine, but then when I make a post, in either one, neither the purchases list nor the sales list shows up. I checked the database and they are being created along with an entry in the column indicating kind (either sale or purchase).
Here are the forms:
<%= form_for (#micropost) do |f| %>
<div class="field no-indent">
<%= f.text_area :content, placeholder: "What's something else you want to buy?" %>
<%= hidden_field_tag 'micropost[kind]', "purchase" %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
and
<%= form_for (#micropost) do |f| %>
<div class="field no-indent">
<%= f.text_area :content, placeholder: "What's something else you want to buy?" %>
<%= hidden_field_tag 'micropost[kind]', "sale" %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
also, here is the show part of the users_controller.rb
def show
#user = User.find(params[:id])
#micropost=Micropost.new
#microposts = #user.microposts.paginate(page: params[:page])
end
and here is the show part of the microposts_controller.rb
def show
#micropost = Micropost.find(params[:id])
#microposts = Micropost.where(:user_id => #user.id)
#purchases= #microposts.collect{ |m| m if m.kind == "purchase"}.compact
#sales = #microposts.collect{ |m| m if m.kind == "sale"}.compact
end
additionally, with the help of this post (http://stackoverflow.com/questions/12505845/ruby-error-wrong-number-of-arguments-0-for-1#12505865) the variables #microposts, #purchases, and #sales are all outputting correctly in the console.
can anyone help me out?
edit: using scopes as suggested by the answer given works in the console (it outputs everything correctly, but they still don't show up in the view. Does this mean it is something wrong with my syntax for the users show page?
edit 2:
Here is the view/microposts/_micropost.html.erb code
<li>
<span class="content"><%= micropost.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(micropost.created_at) %> ago.
</span>
<% if current_user?(micropost.user) %>
<%= link_to "delete", micropost, method: :delete,
confirm: "You sure?",
title: micropost.content %>
<% end %>
</li>
I'm making some assumptions without seeing more of your code, but it looks like you could
write what you've shown a little differently. I'm assuming your databases are migrating
and have the required columns, e.g., Micropost#kind, Micropost#user_id, etc.
You can use scopes to refine a collection of microposts more expressively. It might be helpful to read
up about ActiveRecord scopes: http://guides.rubyonrails.org/active_record_querying.html#scopes.
class Micropost < ActiveRecord::Base
belongs_to :user
scope :purchases, where(:kind => "purchase")
scope :sales, where(:kind => "sale")
# your code
end
I'm also assuming your user has many microposts:
class User < ActiveRecord::Base
has_many :microposts
# your code
end
For your forms, I'd suggest attaching your hidden field to the form object (f.hidden_field) so
you don't have to specify the name as 'micropost[kind]'.
<%= form_for(#micropost) do |f| %>
<div class="field no-indent">
<%= f.text_area :content, placeholder: "What's something else you want to buy?" %>
<%= f.hidden_field :kind, :value => "sale" %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
In MicropostsController#show, you can use your new scopes:
def show
#micropost = Micropost.find(params[:id])
#microposts = #user.microposts
#purchases = #microposts.purchases
#sales = #microposts.sales
end
You should also confirm that your MicropostsController#create action is actually adding
the microposts to the user sending the form (I'm assuming a current user method).
def create
#micropost = current_user.microposts.create(params[:micropost])
# yada
end
You can also confirm expected results on rails console after creating purchases or sales micropost with:
Micropost.purchases
Micropost.sales
Again, I could be missing something without seeing more of the code base.
Check Micropost.count, #purchases.count, #sales.count (by printing them in the controller, or some part of the view) to see if the records actually exist.
Also, if you want to render collections likes #sales and #purchases, you need to make sure that the model partial exists (_micropost.html.erb in your case). That is probably where you need to look for the view errors. For all you know, that file could be empty, thus no errors will show up at all.
The problem might also lie in your microposts#create (or whichever action that you are saving the micropost in), the micropost should be associated with the current_user:
#micropost = current_user.microposts.build(params[:micropost])
Taking this and your previous question into account, I suggest you go through the original code for the RoR tutorial again (and verify that all tests are passing) before taking it apart. You can always add new tests to it for your experiments and they will help in figuring out where you went wrong.

Resources