I'm new to Ruby and using MVC for web apps so I was wondering where I would put the example code from the gem documentation. For my app, I'm using Paperclip to upload a PDF file and I want to display the PDF in the view. I tried putting the code in the controller like so:
require 'rubygems'
require 'open-uri'
class BooksController < ApplicationController
...
def index
io = open('http://www.cbu.edu.zm/downloads/pdf-sample.pdf')
reader = PDF::Reader.new(io)
puts reader.info
end
but when I run this, it freezes the server. I'm wondering how would I get this PDF to show in the view and also how I could test output with the console. For example, with the code above, where can I see the output of the "puts reader.info" statement?
Try, this one:
io = open('http://www.cbu.edu.zm/downloads/pdf-sample.pdf')
reader = PDF::Reader.new(io)
reader.pages.each do |page|
puts page.fonts
puts page.text
puts page.raw_content
end
According to the documentation, If you need to access the full program for rendering a page, use the walk method of PDF::Reader::Page
class RedGreenBlue
def set_rgb_color_for_nonstroking(r, g, b)
puts "R: #{r}, G: #{g}, B: #{b}"
end
end
io = open('http://www.cbu.edu.zm/downloads/pdf-sample.pdf')
reader = PDF::Reader.new(io)
page = reader.page(1)
receiver = RedGreenBlue.new
page.walk(receiver)
Try using Active Storage for PDF uploads, it's got better documentation, easier implementation and it's well integrated into rails from version 5.2.2.
Enabling Active Storage in your application starts with a Rake task: running
rails active_storage:install
Once executed, it creates two tables that Active Storage needs to deliver on its promises: active_storage_attachments and active_storage_blobs.
Here is a link to the official documentation:
https://github.com/rails/rails/blob/d3893ec38ec61282c2598b01a298124356d6b35a/activestorage/README.md
That's all.
I hope this helps
Related
I am learning payment gateway integration in rails.
I chose insta mojo and was working but the documentation they provide is very inconvenient and hard to understand..
https://github.com/AnkurGel/Instamojo-rb#usage
I have no idea where to Set my API keys
require 'Instamojo-rb'
api = Instamojo::API.new do |app|
app.api_key = "api_key-you-received-from-api#instamojo.com"
app.auth_token = "auth_token-you-received-from-api#instamojo.com"
end`
I tried instamojo.rb in initializers and tries to run console but it gives error that no such method exists.
You can put require statement in application.rb or anywhere else so that file is loaded while application is loading.
You can make 'Payment' model in which you can make methods like verify and get details.
Internally in those methods, you will be making API object and using the above code.
class Payment < ActiveRecord::Base
def verify
client = get_intamojo_client
#Some code
end
def get_details
client = get_intamojo_client
#Some code
end
private
def get_instamojo_client
api = Instamojo::API.new(ENV["INSTAMOJO_KEY"],{auth_token: ENV["INSTAMOJO_TOKEN"], endpoint:"https://test.instamojo.com/api/1.1/"})
return api.client
end
end
And to explore what you can do using client object, just use rails console and make a client object there, and use client.public_methods and start exploring.
EDIT:
I think you are using older version of gem i.e 0.1, their documentation is for version > 1.0. To update, use this gem 'Instamojo-rb', '~> 1.1' in gem file and use bundle update.
So for version 0.1, use
api = Instamojo::API.new(ENV["INSTAMOJO_KEY"],{auth_token: ENV["INSTAMOJO_TOKEN"], endpoint:"https://test.instamojo.com/api/1.1/"})
And for versino >= 1.0, use
api = Instamojo::API.new(ENV["INSTAMOJO_KEY"], ENV["INSTAMOJO_TOKEN"], "https://test.instamojo.com/api/1.1/")
In my ruby on rails application, have implemented a facility seeing the railscast video http://railscasts.com/episodes/396-importing-csv-and-excel, that will directly import and update the db at same time, but it is creating problems when the file is too large.
So I want to write a facility to upload a csv or excel file in my application and save it in a directory. Then I want to add some kind of observer that will observe the contents of the directory and on an event like create or update of a file in that directory will trigger contents of those files to be uploaded in db. I am getting no idea about how to approach this.
Thanks in advance.
I think that the best approach is to use Resque to import and convert in a worker separately from the request.
Suppose you have a controller to add the Excel file, which I'm going to call Information model:
class InformationController < ApplicationController
def create
#information = Information.new(params[:information])
if #information.save
resque = Resque.enqueue(ImportDataJob, #information.id)
redirect_to #information, :notice => "Successfully created information for further processing."
else
render :new
end
end
end
You'll need make a job, in this case ImportDataJob:
class ImportDataJob
def self.perform(information_id)
information = Information.find(information_id)
# convert information.raw_csv or wherever attribute you saved the Excel or CSV into
# and save it into the database where you need to
end
end
You'll find a full tutorial in Resque RailsCast, where it shows how to add Resque into your existing Rails app.
Note: There's a conflict between README and the actual implementation for Resque. Apparently they want to change the way Resque is called (which is in the readme), but is not implemented yet. See this Issue in Github for more details.
As an alternative to Resque (and i do think doing it in a background job is the best approach), see also Spawnling, previously known as Spawn:
https://github.com/tra/spawnling
Super-low maintenance. In your controller action do something like
#file = <uploaded file here>
spawn do
#perform some long-running process using #file, in a new process
end
#current thread carries on straight away.
If you need to test if it's finished (or crashed for that matter) you can save the id of the new process like so:
#file = <uploaded file here>
spawner = spawn do
#perform some long-running process using #file, in a new process
end
#current thread carries on straight away.
spawner = spawn do
#make it in a temp file so serve_if_present doesn't serve a halfmade file
FileUtils.rm #filename if File.exists?(#filename)
temp_filename = "#{#filename}.temp"
ldb "temp_filename = #{temp_filename}"
current_user.music_service.build_all_schools_and_users_xls(:filename => temp_filename)
FileUtils.mv temp_filename, #filename
end
#spawn_id = spawner.handle
This might be a dumb question but when I'm putting together an HTML email in Rails, is there a particularly easy built-in way to preview the template it in the browser or do I need to write some sort of custom controller that pulls it in as its view?
Action Mailer now has a built in way of previewing emails in Rails 4.1. For example, check this out:
# located in test/mailers/previews/notifier_mailer_preview.rb
class NotifierPreview < ActionMailer::Preview
# Accessible from http://localhost:3000/rails/mailers/notifier/welcome
def welcome
Notifier.welcome(User.first)
end
end
Daniel's answer is a good start, but if your email templates contain any dynamic data, it won't work. E.g. suppose your email is an order receipt and within it you print out #order.total_price - using the previous method the #order variable will be nil.
Here's a little recipe I use:
First, since this email preview functionality is definitely for internal use only, I set up some generic routes in the admin namespace:
#routes.rb
MySite::Application.routes.draw do
namespace :admin do
match 'mailer(/:action(/:id(.:format)))' => 'mailer#:action'
end
end
Next, I create the controller. In this controller, I create one method per email template. Since most emails contain dynamic data, we need to populate whatever member variables the template expects.
This could be done with fixtures, but I typically prefer to just grab some pseudo-random real data. Remember - this is NOT a unit test - this is purely a development aid. It doesn't need to produce the same result every single time - in fact - it's probably better if it doesn't!
#app/controllers/admin/mailer_controller.rb
class Admin::MailerController < Admin::ApplicationController
def preview_welcome()
#user = User.last
render :file => 'mailer/welcome.html.erb', :layout => 'mailer'
end
end
Note that when we render the template, we use layout=>:mailer. This embeds the body of your email inside the HTML email layout that you've created instead of inside your typical web application layout (e.g. application.html.erb).
And that's pretty much it. Now I can visit http://example.com/admin/mailer/preview_welcome to preview change to my welcome email template.
37Signals also has their own mail testing gem called mail_view. It's pretty fantastic.
The easiest setup I've seen is MailCatcher. Setup took 2 minutes, and it works for new mailers out of the box.
I use email_preview. Give it a try.
Easiest solution in rails 6: just remember one url:
http://localhost:3000/rails/mailers
I'm surprised no one's mentioned letter_opener. It's a gem that will render and open emails as a browser page whenever an email is delivered in dev.
I recently wrote a gem named Maily to preview, edit (template file) and deliver the application emails via a browser. It also provides a friendly way to hook data, a flexible authorization system and a minimalist UI.
I have planned to add new features in the near future, like:
Multiple hooks per email
Parametrize emails via UI (arguments of mailer method)
Play with translations keys (list, highlight, ...)
I hope it can help you.
rails generates a mail preview if you use rails g mailer CustomMailer.
You will get a file CustomMailerPreview inside spec/mailers/previews folder.
Here you can write your method that will call the mailer and it'll generate a preview.
For ex -
class CustomMailerPreview < ActionMailer::Preview
def contact_us_mail_preview
CustomMailer.my_mail(user: User.first)
end
end
Preview all emails at http://localhost:3000/rails/mailers/custom_mailer
You can use Rails Email Preview
REP is a rails engine to preview and test send emails, with I18n support, easy premailer integration, and optional CMS editing with comfortable_mexican_sofa.
There is no way to preview it directly out of the Mailer.
But as you wrote, you can write a controller, which looks something like this.
class EmailPreviewsControllers < ActionController::Base
def show
render "#{params[:mailer]}_mailer/#{params[:method]}"
end
end
But I think, that's not the best way to test emails, if they look correctly.
Rails Email Preview helps us to quickly view the email in web browser in development mode.
1) Add “gem ‘rails_email_preview’, ‘~> 0.2.29’ “ to gem file and bundle install.
2) Run “rails g rails_email_preview:install” this creates initializer in config folder and add routes.
3) Run “rails g rails_email_preview:update_previews” this crates mailer_previews folder in app directory.
Generator will add a stub to each of your emails, then u populate the stub with mock data.
Ex:
class UserMailerPreview
def invitation
UserMailer.invitation mock_user(‘Alice’), mock_user(‘Bob’)
end
def welcome
UserMailer.welcome mock_user
end
private
def mock_user(name = ‘Bill Gates’)
fake_id User.new(name: name, email: “user#{rand 100}#test.com”)
end
def fake_id(obj)
obj.define_singleton_method(:id) { 123 + rand(100) }
obj
end
end
4) Parameters in search query will be available as an instance variable to preview class. Ex: if we have a URL like
“/emails/user_mailer_preview-welcome?user_id=1” #user_id is defined in welcome method of UserMailerPreview it helps us to send mail to specific user.
class UserMailerPreview
def welcome
user = #user_id ? User.find(#user_id) : mock_user
UserMailer.welcome(user)
end
end
5) To access REP url’s like this
rails_email_preview.rep_root_url
rails_email_preview.rep_emails_url
rails_email_preview.rep_email_url(‘user_mailer-welcome’)
6) We can send emails via REP, this will use environment mailer settings. Uncomment this line in the initializer to disable sending mail in test environment.
config.enable_send_email = false
Source : RailsCarma Blog : Previewing Emails in Rails Applications With the Mail_View Gem
I prefer mails_viewer gem. This gem is quite useful as it save the HTML template into tmp folder.
In my Rails 3 application on Windows I have the following page which shows a job receipt and lets user to edit it:
http://localhost:3001/jobs/45/invoice
I have also a "Create PDF" button in the bottom of the page. When pressed, create_pdf_invoice of my JobsController is called:
def create_pdf_invoice
job = Job.find(params[:id])
kit = PDFKit.new("<h1>Hello</h1><p>This is PDF!!!</p>", :page_size => "A4")
file = kit.to_file("my_file_name.pdf")
redirect_to(:action => 'index')
end
end
All this works fine, i.e. the PDF is created!
My question is how can I print the invoice itself rather than this static text (like if I press "Print" on the http://localhost:3001/jobs/45/invoice page) ?
UPDATE
I tried to put
require 'pdfkit'
and
config.middleware.use PDFKit::Middleware
in config/application.rb as suggested here.
The server starts normally, but when I go to
http://localhost:3001/jobs/45/invoice.pdf
Ruby crashes:
I use:
ruby 1.9.2p0 (2010-08-18) [i386-mingw32]
Rails 3.0.1
rake, version 0.8.7
pdfkit (0.5.0)
Any ideas ?
first you need to tell the application to use pdfkit as a middleware.
So somewhere in an initializer you need to put:
# PDFKit
require 'pdfkit'
middleware.use PDFKit::Middleware
PDFKit.configure do |config|
config.wkhtmltopdf = 'windows_path_to_wkhtmltopdf'
end
After this if you call
http://localhost:3001/jobs/45/invoice.pdf
a pdf should be generated for you.
PDFkit is a middleware that intercepts the pdf format rendering the page accordingly.
If you want you can also restrict pdfable routes in the config through regexes or string.
Just a caveat, if you have images in the page they must be called with an absolute path.
We are also finding some problems with pdfkit 0.5.0 but things are working fine with version 0.4.6 it is something to do with paths so maybe it can solve your issues.
With the help of PDFKit middle-ware you can only view the html page in pdf format in the browser.
If want to show the download prompt then you have to set the header in your action.
headers["Content-Disposition"] = "attachment; filename=export"
Further, If you want to save the pdf file in server then you can try this link.
Save PDF file shown by PDFKit middleware
I'm trying to read in the html of a certain website.
Trying #something = open("http://www.google.com/") fails with the following error:
Errno::ENOENT in testController#show
No such file or directory - http://www.google.com/
Going to http://www.google.com/, I obviously see the site. What am I doing wrong?
Thanks!
You need to require 'open-uri' first to be able to open() remote paths.
See the docs for more info.
You should use a utility like Nokogiri to parse the returned content like so:
(From the Nokogiri site front page # http://nokogiri.org/)
require 'nokogiri'
require 'open-uri'
# Get a Nokogiri::HTML:Document for the page we’re interested in...
doc = Nokogiri::HTML(open('http://www.google.com/search?q=tenderlove'))
# Do funky things with it using Nokogiri::XML::Node methods...
# Search for nodes by css
doc.css('h3.r a.l').each do |link|
puts link.content
end
will print to the screen:
Some Link