What should be the format for the parameter: media , in the call below, for updating with multiple images.
def twitter_status_update_with_media (twitter_client, text, media, opts)
twitter_client.update_with_media(self.text, media, opts)
end
For a single image, File.new(filepath) works fine..
To attach multiple images to a tweet, you first need to upload the images using the upload method:
media_ids = %w(image1.png image2.png image3.png image4.png).map do |filename|
Thread.new do
twitter_client.upload(File.new(filename))
end
end.map(&:value)
This will return media IDs, which you can pass into the media_ids parameter (as a comma-separated string) of the update method.
twitter_client.update("Tweet text", :media_ids => media_ids.join(','))
Related
The Issue:
App has a network of various printers. Some of them work through PrintNode. They should receive string encoded as base64. Code which receives my document looks like
PrintNode::PrintJob.new printer_id, 'PrinterClass', method, Base64.encode64(document), 'AppName'
method should contain method - in my case raw_base64 or pdf_base64. So I have next code
case FileMagic.mime.buffer(document, true)
when 'text/plain'
then method = 'raw_base64'
# when 'text/html' # this commented because I have to avoid it
# then method = 'pdf_base64'
when 'application/pdf'
then method = 'pdf_base64'
else
raise InvalidDocumentError
end
I render the document with Controller.render method
document = InstanceController.render :label, { id: instance.id, formats: :pdf, locals: { instance: instance_note } }
As I see document is a string(which includes html) and because of that FileMagic.mime returns text/html(I think so). This is a problem. I'm not near printers and can't just test with a real printer. Also, we have 5 printer types(barcodes, a4, etc.). So I'm not sure that I can just use commented approach(text/html).
So the main question - can I render real PDF with Controller.render method? (if yes then how?)
NOTE: We use PrinceXML and gem princely. So when the same controller used to return PDF through a browser then I get valid good PDF.
Ok. It is a problem with princely. It rewrites an instance method render, not a class method. So to generate PDF with princely I have to call InstanceController.new.render. But its signature is not the same, so it is not very useful.
InstanceController.new.render would call princely only if first param is a hash but in this case we cant send action name.
Because of first item princely tries to get action name fron controller's action_name which in our case is nil and crashes.
But at the same time, I found the way to generate pdf with princely from html explicitly
princely = Princely::Pdf.new
document = princely.pdf_from_string(InstanceController.render action_name, options) # it generates valid PDF from html
I realize this question has been asked a lot, but I could not find any information about how to do this in RoR. I am filling a PDF with form text fields using pdf-forms but this does not support adding images, and I need to be able to add an image of a customer's signature into the PDF. I have used prawn to render the image on the existing PDF, but I need to know the exact location to add the image on the signature line. So my question is how can I look at an arbitrary PDF and find the exact position of the "Signature" form field?
I ended up using pdf2json to find the x,y position of the form field. I generate a JSON file of the original pdf using this command:
%x{ pdf2json -f "#{form_path}" }
The JSON file is generated in the same directory as form_path. I find the field I want using these commands:
jsonObj = JSON.parse(File.read(json_path))
signature_fields = jsonObj["formImage"]["Pages"].first["Fields"].find_all do |f|
f["id"]["Id"] == 'signature'
end
I can use prawn to first create a new PDF with the image. Then using pdf-forms, I multistamp the image pdf onto the original PDF that I want to add the image to. But multistamp applies each page of the stamp PDF to the corresponding page of the input PDF so make sure your image PDF has the correct number of pages or else your image will get stamped on every page. I only want the image stamped onto the first page, so I do the following:
num_pages = %x{ #{Rails.configuration.pdftk_path} #{form_path} dump_data | grep "NumberOfPages" | cut -d":" -f2 }.to_i
signaturePDF = "/tmp/signature.pdf"
Prawn::Document.generate(signaturePDF) do
signature_fields.each do |field|
image Rails.root.join("signature.png"), at: [field["x"], field["y"]],
width: 50
end
[0...num_pages - 1].each{|p| start_new_page }
end
outputPDF = "/tmp/output.pdf"
pdftk.multistamp originalPDF, signaturePDF, outputPDF
You can use this gem 'wicked_pdf. You just write html, and this gem automatically convert it to pdf
Read more https://github.com/mileszs/wicked_pdf
Here's a pure ruby implementation that will return the field's name, page, x, y, height, and width using Origami https://github.com/gdelugre/origami
require "origami"
def pdf_field_metadata(file_path)
pdf = Origami::PDF.read file_path
field_to_page = {}
pdf.pages.each_with_index do |page, page_index|
(page.Annots || []).each do |annot|
field_to_page[annot.refno] = page_index
end
end
field_metas = []
pdf.fields.each do |field|
field_metas << {
name: field.T,
page_index: field_to_page[field.no],
x: field.Rect[0].to_f,
y: field.Rect[1].to_f,
h: field.Rect[3].to_f - field.Rect[1],
w: field.Rect[2].to_f - field.Rect[0]
}
end
field_metas
end
pdf_field_metadata "<path to pdf>"
I haven't tested it particularly thoroughly but the snippet can hopefully get you most of the way there.
Also -- keep in mind the above coordinates calculated are in points from the bottom left of the pdf page rather than the top right (and are not in pixels). I believe there's always 72 points per inch, and you can get the total page points by calling page.MediaBox in the pdf.pages loop above. If you're looking for pixel coordinates, you need to know the DPI of the resulting rendered document.
I have a Gallery model and a Post model. Each Post has an image, and I would like to create a composite image for each Gallery based on the posts in that gallery. I have a method for galleries that returns urls to the top 4 images in the gallery:
gallery.images_for_preview # => returns array of 4 image urls (200x200 images)
I'm using Carrierwave + RMagick to generate a composite image. I'm trying to follow along here: http://railscasts.com/episodes/374-image-manipulation but it seems my use case is slightly different. I have:
class GalleryImageUploader < CarrierWave::Uploader::Base
...
def store_dir
"galleries/#{model.obfuscated_id}"
end
version("full") { process :full_image }
def full_image
images = model.images_for_preview
puts images
manipulate! format: "png" do
image0 = Magick::Image.read(images[0]).first
image1 = Magick::Image.read(images[1]).first
image2 = Magick::Image.read(images[2]).first
image3 = Magick::Image.read(images[3]).first
underlay = Magick::Image.new(406, 406) { self.background_color = "#333333" }
underlay.composite!(image0, 2, 2, Magick::OverCompositeOp).composite!(image1, 204, 2, Magick::OverCompositeOp).composite!(image2, 2, 204, Magick::OverCompositeOp).composite!(image3, 204, 204, Magick::OverCompositeOp)
end
end
The full_image operation doesn't require a source file, but the only way I can seem to get it to generate the composite image is to do something like:
gallery.remote_image_url = "path/to/image"
which generates the image I need at /galleries/:id/full_image.png but also processes and generates an image at /galleries/:id/image.png
Is it possible to skip the "source" image and just generate a composite, then upload that as the ImageUploader's primary image?
Yes, just process the data on the go, no need for the version itself:
Replace this line:
version("full") { process :full_image }
With this one
process :full_image
I have an object like
{"Result":[{
"Links":[{
"UrlTo":"http://www.example.com/",
"Visited":1364927598,
"FirstSeen":1352031217,
"PrevVisited":1362627231,
"Anchor":"example.com",
"Type":"Text",
"Flag":[],
"TextPre":"",
"TextPost":""
}],
"Index":0,
"Rating":0.001416,
"UrlFrom":"http://www.exampletwo.com",
"IpFrom":"112.213.89.105",
"Title":"Example title",
"LinksInternal":91,
"LinksExternal":51,
"Size":5735
}]}
And I have a model with all of the keys.
UrlTo, Visited, FirstSeen, PrevVisited, Anchor, Type, TextPre, TextPost, Index, Rating, UrlFrom, IpFrom, Title, LinksInternal, LinksExternal, Size
I understand how to save this to the database without this bit below...
"Links":[{
"UrlTo":"http://example.com/",
"Visited":1364927598,
"FirstSeen":1352031217,
"PrevVisited":1362627231,
"Anchor":"example.com",
"Type":"Text",
"Flag":[],
"TextPre":"",
"TextPost":""
}],
Not sure how to save it with a nested object as well.
I had a search on Google and SO and couldn't find anything, what is the correct way to do this? Should I move the nested object into the one above? I have no need for it to be nested...
Thanks in advance
it looks like you want to save links, so I would loop over the Result/Links in the json provided, and create a new hash based on the links.
I've pretended below that your json is in a file called input.json -- but you'd obviously just parse the text or use an existing JSON object
require 'json'
json = JSON.parse File.read("input.json")
links = json["Result"].map do |result|
result["Links"].map {|link| link }
end.flatten
hash = {"Links" => links}
puts hash
This creates the object:
{"Links"=>[{"UrlTo"=>"http://www.example.com/", "Visited"=>1364927598, "FirstSeen"=>1352031217, "PrevVisited"=>1362627231, "Anchor"=>"example.com", "Type"=>"Text", "Flag"=>[], "TextPre"=>"", "TextPost"=>""}]}
I have a rails application that is using attachment_fu. Currently, it is using :file_system for storage, but I want to change it to :s3, to allow for better scaling as more files get uploaded.
What is involved with this? I imagine that if I just switch the code to use :s3, all the old links will be broken. Do I need to just copy the existing files from the file system to S3? A google search hasn't turned up much on the topic.
I would prefer to move the existing files over to S3, so everything is in the same place, but if necessary, the old files can stay where they are, as long as new ones go to S3.
EDIT: So, it is not as simple as copying over the files to S3; the URLs are created using a different scheme. When they are stored in :file_system, the files end up in places like /public/photos/0000/0001/file.name, but the same file in :s3 might end up in 0/1/file.name. I think it is using the id something, and just padding it (or not) with zeros, but I'm not sure of that.
That's correct. The ids are padded using :file_system storage.
Instead of renaming all your files, you can alter the s3 backend module to use padded numbers as well.
Copy the partitioned_path method from file_system_backend.rb and put it in s3_backend.rb.
def partitioned_path(*args)
if respond_to?(:attachment_options) && attachment_options[:partition] == false
args
elsif attachment_options[:uuid_primary_key]
# Primary key is a 128-bit UUID in hex format. Split it into 2 components.
path_id = attachment_path_id.to_s
component1 = path_id[0..15] || "-"
component2 = path_id[16..-1] || "-"
[component1, component2] + args
else
path_id = attachment_path_id
if path_id.is_a?(Integer)
# Primary key is an integer. Split it after padding it with 0.
("%08d" % path_id).scan(/..../) + args
else
# Primary key is a String. Hash it, then split it into 4 components.
hash = Digest::SHA512.hexdigest(path_id.to_s)
[hash[0..31], hash[32..63], hash[64..95], hash[96..127]] + args
end
end
end
Modify s3_backend.rb's full_filename method to use the partitioned_path.
def full_filename(thumbnail = nil)
File.join(base_path, *partitioned_path(thumbnail_name_for(thumbnail)))
end
attachment_fu will now create paths with the same names as it did with the file_system backend, so you can just copy your files over to s3 without renaming everything.
In addition to nilbus' answer, I had to modify s3_backend.rb's base_path method to return an empty string, otherwise it would insert the attachment_path_id twice:
def base_path
return ''
end
What worked for me, in addition to nilbus's answer, was to modify s3_backend.rb's base_path method to still use the path_prefix (which is by default the table name):
def base_path
attachment_options[:path_prefix]
end
And also, I had to take the attachment_path_id from file_system_backend.rb and replace the one in s3_backend.rb, since otherwise partitioned_path always thought my Primary Key was a String:
def attachment_path_id
((respond_to?(:parent_id) && parent_id) || id) || 0
end
Thanks for all those responses which helped a lot. It worked for me too but I had to do this in order to have the :thumbnail_class option working :
def full_filename(thumbnail = nil)
prefix = (thumbnail ? thumbnail_class : self).attachment_options[:path_prefix].to_s
File.join(prefix, *partitioned_path(thumbnail_name_for(thumbnail)))
end