How to save images to respective id using paperclip? - ruby-on-rails

I am showing image preview after uploading images.My view contains table of persons with name ,email id,file upload and image preview.And on submit button it will save all images to respective one.I am stuck how to save hash of each image to respective one through paperclip.
I successfully get hash with each person id as key.
I have two controllers Person and Image and this preview and save functionality work on new and create of image.
Code for Image controller:
def new
#people = Person.where("avatar_file_name is ?",nil)
end
def create
#people = Person.where("avatar_file_name is ?",nil)
p=#people.coun
u=Array.new
#people.each do |e|
u.push(e.id)
end
h=Hash.new
h=params
u.each do |x|
#newimage=h["#{x}"]
######## Here in #newimage we get hash of image
end`
end
end
What I have to write after getting hash of each images?
Anyone needs some more description they can ask..........
Thanks in advance

got solution......very easy one
u.each do |x|
#person = Person.find(x)
#person.update_attribute(:avatar,h["#{x}"])
end
It's working fine

Related

How to query for records where Active Storage attached and image is variable?

How can I query for all the users who have an image attached and where the image is .variable??
e.g
I can do this
# controller
#users = User.all
view:
<% if user.image.attached? && user.image.variable? %>
<!-- display image -->
<% end %>
Rather than having that logic in the view, I wonder if I can simply query for only those #users which meet the conditions of both user.image.attached? and user.image.variable?
Is this possible with some Active Record query?
Active Storage doesn't provide shortcut scopes for what you want, but you can come up with a custom solution.
For fetching only users with an attached image, join the corresponding attachments:
User.joins(:image_attachment)
An attachment (or rather: a blob) is variable, if its content_type is present in the ActiveStorage.variable_content_types array, see https://github.com/rails/rails/blob/v6.1.3.2/activestorage/app/models/active_storage/blob/representable.rb#L42-L44.
So we can further query for that content_type, but we need to join the blob (implicitly through the attachment) for that:
User.joins(:image_blob).where(active_storage_blobs: {content_type: ActiveStorage.variable_content_types})
And that should be the query for what you want. Additionally, you can have that as a scope so it's shorter when used:
# app/models/user.rb
scope :with_variable_image -> do
joins(:image_blob).where(active_storage_blobs: {content_type: ActiveStorage.variable_content_types})
end
# app/controllers/users_controller.rb or wherever
users = User.with_variable_image

Rails saving arrays to separate rows in the DB

Could someone take a look at my code and let me know if there is a better way to do this, or even correct where I'm going wrong please? I am trying to create a new row for each venue and variant.
Example:
venue_ids => ["1","2"], variant_ids=>["10"]
So, I would want to add in a row which has a venue_id of 1, with variant_id of 10. And a venue_id of 2, with variant_id of 10
I got this working, and it's now passing in my two arrays. I think I am almost there I'm not sure the .each is the right way to do it, but I think that I'm on the right track haha. I have it submitting, however, where would I put my #back_bar.save? because this might cause issues as it won't redirect
Thanks in advance.
def create
#back_bar = BackBar.new
#venues = params[:venue_ids]
#productid = params[:product_id]
#variants = params[:variant_ids]
# For each venue we have in the array, grab the ID.
#venues.each do |v|
#back_bar.venue_id = v
# Then for each variant we associate the variant ID with that venue.
#variants.each do |pv|
#back_bar.product_variant_id = pv
# Add in our product_id
#back_bar.product_id = #productid
# Save the venue and variant to the DB.
if #back_bar.save
flash[:success] = "#{#back_bar.product.name} has been added to #{#back_bar.venue.name}'s back bar."
# Redirect to the back bar page
redirect_to back_bars_path
else
flash[:alert] = "A selected variant for #{#back_bar.product.name} is already in #{#back_bar.venue.name}'s back bar."
# Redirect to the product page
redirect_to discoveries_product_path(#back_bar.product_id)
end
end # Variants end
end # Venues end
end
private
def back_bar_params
params.require(:back_bar).permit(:venue_id,
:product_id,
:product_variant_id)
end
as i said in comments
this is untested code and just showing you how it's possible to do with ease.
class BackBar
def self.add_set(vanue_ids, variant_ids)
values = vanue_ids.map{|ven|
variant_ids.map{|var|
"(#{ven},#{var})"
}
}.flatten.join(",")
ActiveRecord::Base.connection.execute("INSERT INTO back_bars VALUES #{values}")
end
end
def create
# use in controller
BackBar.add_set(params[:venue_ids], params[:variant_ids])
# ...
end

Displaying from my database

I'm new to rails and I'm working on a project where I'm having an issue. I'm trying to display all the gyms that have the same zipcode. When I tried the code below, it only displays 1 and not the other ones. How can display all the gym that have the same zip code?
controller
def gym
#fitness = Fitness.find_by(zip_code: params[:zip_code])
end
gym.html.erb
<%= #fitness.name %>
You're doing this to yourself. By definition, #find_by only returns a single record, or nil. You probably want #where instead:
Fitness.where(zip_code: params[:zip_code])
If that still doesn't work, check both your table data and the content of your params hash to make sure you're creating a valid query.
def gyms
#fitness = Fitness.where("zip_code = ?", params[:zip_code])
end

Rails Paperclip copy set of images from model A to model B

Currently I have a model A (ItemRequest) that has many images.
Once this item request has been approved, it creates a model B (Item) that also has many images.
I'm using paperclip to handle image upload to S3, and what I would like is that after the approve process has been completed, copy the images from model A to model B, duplicating them.
Following some similar questions (but none using models with many images) I've written the following in my ItemRequest model approve method.
if images.length > 0
item.images = images.map { |img| img.dup }
end
And this apparently creates a new set of Image models, but when trying to access the url, it does not open any image and S3 returns 403.
I've checked and no image is created in S3. I can access other images so the S3 is properly configured.
Any ideas on how to solve this?
def resolve! user_id
if status != RESOLVED
ActiveRecord::Base.transaction do
self.resolved_by_id = user_id
self.resolved_date = DateTime.now
self.status = RESOLVED
save!
catalog_item = Item.create(
name: item_name,
oem_name: oem_name,
description: description,
category_id: category_id,
make: make,
part_number: part_number,
uom: uom,
cost_in_cents: cost_in_cents,
weight_in_grams: weight_in_grams
)
if images.length > 0
catalog_item.images = images.map { |img| img.dup }
catalog_item.save
end
end
end
true
end
Something is worth mentioning that doesn't simplify things, is that my Image model is polymorphic.
I've managed to write a solution but not happy with it yet.
Add this to the Image model
def file_remote_url=(url_value)
self.file = URI.parse url_value
#file_remote_url = url_value
end
And then
catalog_item.images = images.map { |img|
new_image = Image.new()
new_image.file_remote_url = img.url
new_image
}
catalog_item.save
Also, this solution does not work locally if uploading to the dev machine.
After a few days of trying different approaches, here is what solved the issue for me:
catalog_item.images = images.map do |img|
new_image = Image.new
new_image.imageable_type = 'CatalogItem'
new_image.imageable_id = catalog_item.id
new_image.file = img.file
new_image
end
This will create a copy of the image instead of changing the reference only. As far as I understood, if you're using S3 and paperclip, it won't simply copy the image using the S3 api but rather make a copy and upload it again, which might be a bit inefficient, but that is a whole other unrelated issue.

best strategy to moderate uploaded images?

I'm trying to finalize my image moderation code,
I have just a simple assets model with a column moderated.
Images will not be shown unless the moderated flag is set to true ( boolean )
In addition to this I have the idea to store a is_moderated (integer) inside User model and store a value there like
0 = not moderated
1 = moderated and inappropriate image
2 = moderated and correct image
Then in application controller I do something like, in before filter:
def is_moderated
if user_signed_in?
#moderate = Moderate.find(current_user) rescue nil
if #user.is_moderated == "2"
render :template => "shared/moderated_bad_images"
end
end
end
end
How about you are only allowed to upload 1 image initially.
Then after that image is deemed appropriate you can add more.

Resources