Rails admin gem showing s3 attachments which is IMAGES/PDF/DOCS/XLSX - ruby-on-rails

I am using rails_admin gem for the rails api application for the backend admin side.
I am using rails 6 with active_storage and storing attachments on the S3.
On the admin side, I need to display the list of attachments which might be images or files anything.
My question is How to show those in index method, do I need to show images then what to show in pdf/docs, do I need to show the only the link of s3?
currently, it looks like these broken images are the images and other one were files
My model
class Attachment < AttachmentBlock::ApplicationRecord
self.table_name = :attachments
include Wisper::Publisher
has_one_attached :attachment
belongs_to :account, class_name: 'AccountBlock::Account'
has_and_belongs_to_many :orders , class_name: 'BxBlockOrdermanagement::Order'
scope :not_expired, -> {where('is_expired = ?',false)}
end
What should I use here to list the attachment that the user upload?
how to check the attachment type and then if its image then shows the image and if it files then show file url from s3?
thanks.

Yours is a two part question:
To add links to the side menu on rails admin you need to define models so if you wanted an index for all the attachments of type 'pdf' you could use rails STI (single table inheritance) or define a custom default_scope like this:
class ImageAttachment < Attachment
def self.default_scope
where('attachments.attachment LIKE ?', '%png') }
end
end
To customize the row of each individual attachment record you need to defined that behavior for the field on the model rails admin config.
For example you can put this block of code inside your ImageAttachment class.
class ImageAttachment < Attachment
def self.default_scope
where('attachments.attachment LIKE ?', '%png') }
end
rails_admin do
configure :attachment do
view = bindings[:view]
attachment = bindings[:object]
if view
view.content_tag(:img, attachment.attachment.url)
else
''
end
end
list do
field :attachment
end
end
end
As you can see inside the attachment field configuration block you have access to the attachment object and of course all its methods, you can determine the type of attachment and do some special html rendering.

Related

RoR Carrierwave: Add remote files with multiple upload

I'm using the possibility to upload multiple files at once with carrierwave as described here:
https://github.com/carrierwaveuploader/carrierwave#multiple-file-uploads
So I have
class Item < ActiveRecord::Base
mount_uploaders :images, ImagesUploader
serialize :images, JSON
...
end
Now I want to upload a remote file (not from local drive). Usually I would use something like this in my controller
class ItemsController < ApplicationController
...
item.remote_images_url = params[:image_url]
...
end
But the helper remote_images_url (mind the plural version remote_images_url) only give me
undefined method remote_images_url
I also tried remote_image_url which would be the default helper in case of single file upload. Also undefined method.
How can I upload remote files when using "multiple files upload" with carrierwave?
Eventually I had a look into the github repository of carrierwave and I found this:
https://github.com/carrierwaveuploader/carrierwave/blob/master/lib/carrierwave/mount.rb
Luckily it's all described in the comments in this file. There was only one little thing I had to change. In the comments it says that for a column called images I had to use the helper method remote_image_urls. But actually I have to use remote_images_urls (always plural).
So that's the solution in my case:
class Item < ActiveRecord::Base
mount_uploaders :images, ImagesUploader
serialize :images, JSON
...
end
class ItemsController < ApplicationController
...
item.remote_images_urls = [params[:image_url]]
...
end
Mind the right plural types in the helper method as well as the surrounding array for the params (carrierwave excpects an array).
You need to use item.remote_images_urls not item.remote_images_url and assign the array of remote url. This works for me although CarrierWave rubydoc suggests me to use item.remote_image_urls . So, maybe you should try one of these .
For reference CarrierWave rubydoc

paperclip where does it store file id

I'm new to ror and paperclip.
I use paperclip to upload file, and I wonder how does paperclip determine the file id. For example in my User model, I add paperclip attachment "has_attachment_file", then I find that in database(I use sqlite3) there are four new columns in table "User" including file name, file type, uploaded time and file size. However I can't find the file id this column as I can retrieve from user.file.id. Where does paperclip store this things?
The attached file isn't stored in relation to the User — it's stored directly on it. That's why your User table has the extra columns, and why the file doesn't have an id.
If you want a User to have many files you will need to model them separately and use Rails' has_many. Something like:
class User < ActiveRecord::Base
has_many :images
end
class Image < ActiveRecord::Base
has_attached_file :file
belongs_to :user
end

Rails: Select Avatar From Table

In the rails application I am developing, I want the to give the end users the ability to select an avatar. Nothing unusual here.
Unfortunately, I have found numerous articles, posts and gems about the uploading and selection of images (example: Is there any rails gem for avatar selection? | http://rubygems.org/gems/paperclip ) but what I want is for them to select from an 'Avatar' table in my database. I do not want them to be able to upload anything. The Avatars which they can select from will be created for them.
My thought is that the Avatar table would have two columns: id and url_path.
In their user profile I would have a field I assume to store the avatar_id -- but from there I am stuck --- I want them to see the gallery of avatars and make a selection to populate that field. I am open to a gem -- but most seem more complex than I need.
Any assistance would be appreciated.
Here's some input to push you in the right direction. I don't think you need a gem for this.
You need three models:
class User < ActiveRecord::Base
has_one :avatar, through: :profile_picture
has_one :profile_picture
# change both associations to has many if a user can have multiple avatars
end
class Avatar < ActiveRecord::Base
has_one :profile_picture
# attribute: filename
end
class ProfilePicture < ActiveRecord::Base
belongs_to :user
belongs_to :avatar
# attributes: user_id and avatar_id
end
The profile picture model links users with avatars.
Since the user will only be able to choose from a set of avatars, you simply create the avatars as admin. Just put avatar images in assets/images/avatars and create the avatar records in the database yourself:
# assuming an avatar's filename is avatar.png
Avatar.create(filename: 'avatar.png')
# and make sure you have such an image in assets/images/avatars
Then, assuming you have a page where you render all avatars as, e.g., linked images as preview that users can click on to select one, you could simply link those images to a ProfilePicturesController's create action. You will need the following route
resources :profile_pictures, only: [ :create ]
and the following erb code for your images for the user to choose from:
<% Avatar.all.each do |a| %>
<%= link_to image_tag("assets/images/avatars/#{a.filename}"), profile_pictures_path(avatar_id: a.id), method: :post %>
<% end %>
and the following controller code:
class ProfilePicturesController < ActionController::Base
def create
ProfilePicture.create(
avatar_id: params[:avatar_id],
user_id: current_user.id # or however you retrieve the current user
)
flash[:notice] = 'Avatar updated.' # just a suggestion
redirect_to :back # just a suggestion
end
end
Haven't actually tried any of this, so let me know if it works.

Multiple paperclip attachments get saved without specifying a file input

I have a User model which has a has_many association of Asset model(standard paperclip setup). In the view, I use fields_for helper to setup a number of file fields for the assets. When the end user does not specify a file, the asset records will not be saved. Which is what I want. So far so good.
Then I added a caption attribute to Asset model. I also put a text field to each corresponding file field. Here comes the problem. When the end user does not specify a file or a caption, the asset records will be SAVED. The saved record has a caption of empty string, with all other paperclip attributs being nil.
The question is how can I prevent the asset record being saved when there is no file assigned to paperclip attributes? And since the assets are optional, I don't want any error feedback generated. Any ideas? Thanks.
You could do a validates_presence_of :caption in your Asset model, but that also makes captions required. How about this checking for the presence of a file on all assets linked to the User before_validation? Something like this maybe? (might need some tweaking)
class User < AR::Base
has_many :assets, :dependent => :destroy
before_validation :check_assets
def check_assets
self.assets.each do |asset|
unless asset.attachment.file?
if asset.new_record?
self.assets.delete(asset)
else
asset.destroy
end
end
end
end
end

rails find model without loading relevant associations

My rails application has two models, gallery and photo. Galleries have many photos and photos belong to one gallery.
When I delete a photo, I noticed that rails also loads the gallery - which I do not need. It is an added database query.
When I find the photo to delete, I use #photo = Photo.find(params[:id]). This loads the association.
I know that there is #photo = Photo.find(params[:id], :include => :gallery), which tells it to load the gallery. What is the opposite of this? I tried the following:
#photo = Photo.find(params[:id], :include => [])
#photo = Photo.find(params[:id], :include => nil)
I also tried to select only the fields that I need in order to delete the photo, but I need the gallery_id in order to delete the actual file because the path of the file is based off the gallery. This just ends up loading the gallery too.
Edit:
My Photo model looks like this:
class Photo < ActiveRecord::Base
belongs_to :gallery
mount_uploader :file, PhotoUploader
end
mount_uploader is from carrierwave. I have an uploader with the following code in it:
def store_dir_base
"galleries/#{model.gallery.id}/"
end
Could it be the culprit?
Thanks!
The reason this was happening was because of my uploader code that I used for carrierwave.
This code was accessing the gallery model, when all I needed to access was the id:
def store_dir_base
"galleries/#{model.gallery.id}/"
end
All I had to do was change it to:
def store_dir_base
"galleries/#{model.gallery_id}/"
end
This made it so I was accessing the photo model column gallery_id instead of the gallery model.

Resources