the first I am using db mysql but then I change to postgres.
I write some function to clone db from sql to postgres. And I have a problem with clone db from Image table.
ImageClone.all.each do |p|
img = Image.new()
img.imageable_id = p.imageable_id
img.imageable_type = p.imageable_type
img.uploader = p.uploader
puts p.uploader #=> 'testing_image.jpg'
img.save
end
=> #<Image id: 1, imageable_id: 1, imageable_type: "ProductType", uploader: nil>
how can I set image url = 'testing_image.jpg'.
any suggestion?
If you want to duplicate an attachment into a new object you need to tell the new object to read the original attachment like so:
new_object.attachment_file = File.open(old_object.attachment_file.path)
Where attachment_file is the attribute defined as the mounted uploader in your attachment class:
class Object < ActiveRecord::Base
mount_uploader :attachment_file, AttachmentUploader
And now your new object has the file loaded into memory. You can save it, validate it or discard it just like any other attachment!
Related
In rails 5.2, I have a model using has_many_attached :images. I would like to send out an email that includes all associated images as attachments.
My mailer method currently looks like:
def discrepancy_alert(asset_discrepancy_id, options={})
#asset_discrepancy = AssetDiscrepancy.find asset_discrepancy_id
#asset_discrepancy.images.each_with_index do |img,i|
attachments["img_#{ i }"] = File.read(img)
end
mail to: 'noone#gmail.com', subject: "email subject"
end
obviously, File.read does not work here because img is not a path, it is a blob. I have not been able to find any info on this in the docs
Question One:
Is there a rails method for attaching a blob like this?
I can use the following instead:
#asset_discrepancy.images.each_with_index do |img,i|
attachments["img_#{ i }"] = img.blob.download
end
Question Two:
the download method could use a log of RAM, is this usage ill advised?
It seems, with the addition of ActiveStorage, that rails mailers would have some new methods for interaction between the two....I have not seen anything in the docs. All the mailer attachments[] examples use paths to a local file.
in app/mailers/mailer.rb:
if #content.image.attached?
#filename = object.id.to_s + object.image.filename.extension_with_delimiter
if ActiveStorage::Blob.service.respond_to?(:path_for)
attachments.inline[#filename] = File.read(ActiveStorage::Blob.service.send(:path_for, object.image.key))
elsif ActiveStorage::Blob.service.respond_to?(:download)
attachments.inline[#filename] = object.image.download
end
end
in mailer view:
if #filename
image_tag(attachments[#filename].url)
else
image_tag(attachments['placeholder.png'].url)
end
This worked for me in production using Amazon S3.
in mailer view:
if #object.images
#object.images.each do |image|
path = "https://www.example.com" + Rails.application.routes.url_helpers.rails_blob_path(image, only_path: true)
<img src="<%=path%>">
end
end
Here is the working solution for active storage url in email template. I have seen the images visible in gmail. You can use "rails_blob_url". This works for file stored in aws s3.
mailer.rb
....
#image_url = Rails.application.routes.url_helpers.rails_blob_url(blob),
....
mailer view file
<img src="<%= #image_url %>">
Using: Rails 4.2, Prawn, Paperclip, DelayedJobs via ActiveJobs, Heroku.
I have a PDF that is very large and needs to be handled in the background. Inside a custom Job I want to create it, upload it to S3, and then email the user with a url when its ready. I facilitate this via a PdfUpload model.
Is there anything wrong with my approach/code? Im using File.open() as outlined in examples I found, but this seems to be the root of my error ( TypeError: no implicit conversion of FlightsWithGradesReport into String ).
class PdfUpload < ActiveRecord::Base
has_attached_file :report,
path: "schools/:school/pdf_reports/:id_:style.:extension"
end
/pages_controller.rb
def flights_with_grades_report
flash[:success] = "The report you requested is being generated. An email will be sent to '#{ current_user.email }' when it is ready."
GenerateFlightsWithGradesReportJob.perform_later(current_user.id, #rating.id)
redirect_to :back
authorize #rating, :reports?
end
/ the job
class GenerateFlightsWithGradesReportJob < ActiveJob::Base
queue_as :generate_pdf
def perform(recipient_user_id, rating_id)
rating = Rating.find(rating_id)
pdf = FlightsWithGradesReport.new( rating.id )
pdf_upload = PdfUpload.new
pdf_upload.report = File.open( pdf )
pdf_upload.report_processing = true
pdf_upload.report_file_name = "report.pdf"
pdf_upload.report_content_type = "application/pdf"
pdf_upload.save!
PdfMailer.pdf_ready(recipient_user_id, pdf_upload.id)
end
end
This results in an error:
TypeError: no implicit conversion of FlightsWithGradesReport into String
Changing this:
pdf_upload.report = File.open( pdf )
to this:
pdf_upload.report = StringIO.new(pdf.render)
fixed my problem.
I would like to set some images without uploading. (They already exist, or another task saves them...)
If I try (in rails console):
user = User.last
user.picture = '/some/picture.jpg'
user.save
user.picture # nil
The only way to do that is to set remote_picture_url, and then delete the upload (which is stupid)
Is there any method in carrierwave that lets you modify only the filename ?
class User < ActiveRecord::Base
attr_accessible :picture
# Don't want to write to the database, but want to be able to check
attr_writer :skip
# set a default value
def skip
#skip ||= false
end
mount_uploader :image, PictureUploader
# Make sure that the skip callback comes after the mount_uploader
skip_callback :save, :before, :store_picture!, if: :skip_saving?
# Other callbacks which might be triggered depending on the usecase
#skip_callback :save, :before, :write_picture_identifier, id: :skip_saving?
def skip_saving?
skip
end
end
class PictureUploader < Carrierwave::Uploader::Base
# You could also implement filename=
def set_filename(name)
#filename = name
end
end
Assuming you have the setup above, in your console:
user = User.last
user.picture.set_filename('/some/picture.jpg')
user.skip = true
# Save will now skip the callback store_picture!
user.save
user.picture # /some/picture.jpg
It should be noted that if you're in the console and you update an existing record that has an attached file (ie user.picture.file) it will show the old url/location. If you quit the console (assuming you're not in sandbox mode) and come back and query the same object it will have the updated url/location.
I have the following method:
class Topic
def create_or_rename_folder
unless self.destroyed?
bucket = CreateTopicFolder.new(bucket_name)
bucket.create_or_rename_folder(permalink.split("/").last)
end
end
...
which is called like: after_save :create_or_rename_folder, :if => :production_env?
I would like to test that upon creating a new Topic a new CreateTopicFolder instance gets created, and also that if a Topic is being destroyed, a new instance of CreateTopicFolder is not being created.
That class looks something like:
class CreateTopicFolder
def initialize(bucket_name)
s3 = AutoVideoAssociate
s3.connect
#bucket = s3.find_bucket(bucket_name)
end
...
What is the right way to go about testing this?
Thanks!
context "When creating a Topic" do
it "creates a CreateTopicFolder" do
create_topic_folder = mock(CreateTopicFolder)
CreateTopicFolder.stub(:new) { create_topic_folder }
create_topic_folder.
should_receive(:create_or_rename_folder).
with("Sample Bucket Name")
topic = Topic.new
topic.bucket_name = "Sample Bucket Name"
topic.save!
end
end
context "When destroying a Topic" do
it "does not create a CreateTopicFolder" do
CreateTopicFolder.should_not_receive(:new)
topic = mock_model(Topic)
topic.destroy
end
end
I am using ActiveResource to manage accessing an external service.
The external service has an URL like:
http://api.cars.com/v1/cars/car_id/range/range_num?filter=filter1,filter2
Here's my Car class:
class Car < ActiveResource::Base
class << self
def element_path(id, prefix_options = {}, query_options = nil)
prefix_options, query_options = split_options(prefix_options) if query_options.nil?
"#{prefix(prefix_options)}#{collection_name}/#{URI.parser.escape id.to_s}#{query_string(query_options)}"
end
def collection_path(prefix_options = {}, query_options = nil)
prefix_options, query_options = split_options(prefix_options) if query_options.nil?
"#{prefix(prefix_options)}#{collection_name}#{query_string(query_options)}"
end end
self.site = "http://api.cars.com/"
self.prefix = "/v1/"
self.format = :json
end
When I set up my object to get a particular car in rails console:
> car = car.new
> car.get('1234')
I get a URL like this:
http://api.cars.com/v1/cars//1234.json
How do I get the URL to include the range and range_num elements?
Also, i don't want the .json extension on the end of the URL. I've attempted overriding the element_name and collection_name methods as described here: How to remove .xml and .json from url when using active resource but it doesn't seem to be working for me...
Thanks in advance for any ideas!
Get rid of the forward slash in the URL
"#{prefix(prefix_options)}#{collection_name}/#{URI.parser.escape id.to_s}#{query_string(query_options)}"
becomes:
"#{prefix(prefix_options)}#{collection_name}#{URI.parser.escape id.to_s}#{query_string(query_options)}"