Auto fill doesn't work on edit with image uploader - ruby-on-rails

I trying to create a blog with a obligatory image, but after create, when i try to edit this blog, his image appears on thmbnail but not in field and
i have to select the image again.
For upload image i use the carrierwave gem.
My model
class Blog < ActiveRecord::Base
validates :name, :description, :picture, presence: true
mount_uploader :picture, BlogPictureUploader
def picture_url
picture.url
end
My view
= simple_form_for [blog] do |f|
.row
.col-md-6
.panel.panel-default
.panel-heading Foto
.panel-body
.thumbnail class="#{blog.picture? ? "" : "hide"}"
= image_tag blog.picture
p= f.input :picture, label: 'Selecione a foto:', hint: 'A foto deve ter 270x270.'
My controller
class BlogsController < ApplicationController
expose(:blog, attributes: :blog_params)
def update
authorize blog
blog.save
respond_with blog, location: [:blog]
end
The behavior on edit: edit view after click button

If I were you I would create a img element for displaying the image in your edit-page, that was originally uploaded. You don't necessarily have to use the path of the original-image in your input element at the edit-page, and IF the user uploads a new picture it will replace the old one.

Related

How to edit multiple attached images using ActiveStorage `has_many_attached` in ActiveAdmin

I have a simple model that can have multiple images attached via ActiveStorage handling the file storage.
I am using ActiveAdmin to edit my model and to upload/attach the images - so far no problems.
The problem is, when I want to edit my model, and add new images, then the previous ones are deleted, and only the new ones added.
I can do a preview of already attached images, and could also delete them separately, but how do I achieve, that by uploading new images, the old ones are NOT deleted?
My model:
class Post < ActiveRecord::Base
has_many_attached :images
end
My ActiveAdmin page:
ActiveAdmin.register AdminPost do
permit_params images:[]
form do |f|
f.input :images, as: :file, input_html: { multiple: true }
if #resource.images.exists?
#resource.images.map do |m|
para image_tag m
end
end
end
end
Assuming you are using rails 6.0+;
you can solve this by adding following code in to your environments (i.e - development.rb )
https://github.com/rails/rails/issues/35817#issuecomment-628654948
config.active_storage.replace_on_assign_to_many = false
in your form,
form do |f|
f.input :images, as: :file, input_html: { multiple: true }
f.object.images.each do |image|
span image_tag(image)
end
end
So I chose the way of adding the new attachments manually, so they don't replace the existing attached images.
I added a field to handle the posted images, and a method to add them in my model.
class Post < ActiveRecord::Base
has_many_attached :images
attr_accessor :new_images
def attach_images
return if new_images.blank?
images.attach(new_images)
self.new_images = []
end
end
And the ActiveAdmin page controller handles the upload, and calls the new method:
ActiveAdmin.register AdminPost do
permit_params new_images:[]
form do |f|
f.input :new_images, as: :file, input_html: { multiple: true }
if #resource.images.exists?
#resource.images.map do |m|
para image_tag m
end
end
end
controller do
after_save :add_images
def add_images(post)
post.attach_images
end
end
end

Fields_for form fields not displaying in rails form

I have a class Rfsestimation shown below:
class Rfsestimation < ActiveRecord::Base
has_one :rfstaskset
has_one :rfsnote
enum request_type: [:front_end, :back_end, :front_end_and_back_end]
enum band_type: [:Simple, :Medium, :High, :Complex, :VComplex, :Outside_AD]
**accepts_nested_attributes_for :rfstaskset**
**accepts_nested_attributes_for :rfsnote**
validates_presence_of :number, :name, :date_of_estimation, :request_type_id, :band_id, :hours_per_day, :estimated_start_date, :estimated_end_date, :message => "Should be present"
validates_numericality_of :number
end
Please see the two lines for association above marked in bold. I am attempting to create the associated objects, Rfsnote and Rfstask through fields_for shown in below form:
<%= f.fields_for :rfstaskset do |rfs_task| %>
However the fields which are supposed to appear do not appear as expected. But if i use rfstasksets, as below, the form fields appear as expected.
What might be the reason for this?
<%= f.fields_for :rfstasksets do |rfs_task| %>
I think you are not building the associated object in your controller.
You new action need to look like this:
def new
#rfsestimation = Rfsestimation.new
#rfsestimation.build_rfstaskset
end

Render Edit form for nested attributes via ajax (with image upload via jquery-fileupload)

I have 2 models:
Building → has_many :building_views
BuildingView → belongs_to :building
I can create BuildingView only for existing Building — via Edit form of Building.
BuildingView have image and title attributes. Image is uploading via Carrierwave.
Workflow:
I go to edit page of Building
There I have file_field that allow choose multiple files
I choose few images and they uploading via jquery-fileupload-rails gem (creating BuildingView for each image)
Right after upload they appear in the Edit form (without reloading page) with thumb and input field to edit title of BuildingView
1, 2 and 3 are ok. Images are uploading, BuildingView are creating and after page reload they appear in the Edit form of Building with title edit input field (which also can be successfully edited). The problem with 4: I can't append BuildingView edit forms via ajax.
Here is my files:
controllers/admin/buildings_controller.rb
# other defs ...
def edit
#building = Building.find(params[:id])
end
def update
#building = Building.find(params[:id])
if #building.update_attributes(building_params)
flash[:success] = 'Woohoo!'
redirect_to admin_buildings_url
else
render :edit
end
end
# other defs ...
private
def building_params
params.require(:building).permit(:all_building_params,
building_views_attributes: [
:_destroy,
:id,
:building_id,
:image,
:title
])
end
views/admin/buildings/edit.html.haml
%h1 Edit building
= form_for [:admin, #building] do |f|
= render 'admin/buildings/form', f: f
.form-element-container
.form-element.b-form-labels
.form-element.b-form-fields
= f.submit 'Edit building'
= link_to t('admin.cancel'), :back
= form_for [:admin, BuildingView.new] do |f_bv|
= f_bv.hidden_field :building_id, value: #building.id
= f_bv.file_field :image, multiple: true, name: 'building_view[image]'
views/admin/buildings/_form.html.haml
// fields for Building...
#building_views
.form-element-container
.form-element
%h2 Building views
= f.fields_for :building_views do |bv_form|
= render 'admin/buildings/form_building_views', f: bv_form
views/admin/buildings/_form_building_views.html.haml
.form-element-container
.form-element.b-form-labels Image:
.form-element.b-form-fields= image_tag(f.object.image_url(:thumb)) if f.object.image
.form-element-container
.form-element.b-form-labels Title:
.form-element.b-form-fields= f.text_field :title
assets/javascript/admin/buildings.js.coffee
jQuery ->
$('#building_view_image').fileupload(
dataType: 'script'
)
controllers/admin/building_views_controller.rb
class Admin::BuildingViewsController < ApplicationController
def create
#building_view = BuildingView.create(building_view_params)
end
private
def building_view_params
params.require(:building_view).permit(:building_id, :image)
end
end
views/admin/building_views/create.js.haml
- if #building_view.new_record?
== alert('Oops!');
- else
== $('#building_views').append('#{j render('admin/buildings/form_building_views')}');
I choose files to upload → error from console:
ActionView::Template::Error (undefined local variable or method `f' for #<#<Class:0x007ffaa52faad8>:0x007ffaa7393970>):
So I need to pass f, when I'm rendering edit form in views/admin/building_views/create.js.haml.
But I can't figure out how. I tried:
j render('admin/buildings/form_building_views', f: #building_view)
but:
ActionView::Template::Error (undefined method `object' for #<BuildingView:0x007ffaa738a348>):
Well, as far as I can see, I can't pass this f to this partial. So I recreated partial manually.
views/admin/buildings/_form_building_views_ajax.html.haml
.form-element-container
.form-element.b-form-labels= image_tag(#building_view.image_url(:thumb)) if #building_view
.form-element.b-form-fields= text_field_tag "building[building_views_attributes][#{building_nested_model_count(#building_view, #building)}][title]", nil, placeholder: 'Title'
= hidden_field_tag "building[building_views_attributes][#{building_nested_model_count(#building_view, #building)}][id]", #building_view.id
I just recreated form, which rails generate with the fields_for helper.
There's new helper there: building_nested_model_count(#building_view, #building) — it counts the amount of BuildingViews for current Building. I will use it for params hash (see id and name input field params).
I need to update 3 files.
Define #building
controllers/admin/building_views_controller.rb
class Admin::BuildingViewsController < ApplicationController
def create
#building_view = BuildingView.create(building_view_params)
#building = #building_view.building
end
private
def building_view_params
params.require(:building_view).permit(:building_id, :image)
end
end
Add building_nested_model_count helper
helpers/admin/building_views_helper.rb
module Admin::BuildingsHelper
def building_nested_model_count(nested_var, building)
nested_class = nested_var.class
nested_class.where(building_id: building.id).count
end
end
And switch partial for ajax render
views/admin/building_views/create.js.haml
- if #building_view.new_record?
== alert('Oops!');
- else
== $('#building_views').append('#{j render('admin/buildings/form_building_views_ajax')}');
I don't know is it good or bad way to solve this, but it works: form for new BuildingView is rendering, and its title saving to db after form submit.

Deleting a Paperclip Attachment in Activeadmin

I'm using paperclip to add image attachments to several models and Activeadmin to provide a simple admin interface.
I have this code in my activeadmin model file which allows for image uploads:
form :html => { :enctype => "multipart/form-data"} do |f|
f.inputs "Details" do
f.input :name
f.input :subdomain
end
f.inputs "General Customisation" do
f.input :standalone_background, :hint => (("current image:<br/>").html_safe + f.template.image_tag(f.object.standalone_background.url(:thumb))).html_safe, :as => :file
end
end
which works fine. All of the images I'm attaching like this are optional and so I'd like to give the user the option to remove a previously added image but can't work out how to do this in Activeadmin. All of the example I've seen are for situations where the attachments are managed through a separate has_many association rather than being part of the main model.
Does anyone know of a way to do this?
In your active admin view
form :html => { :enctype => "multipart/form-data"} do |f|
f.inputs "Details" do
f.input :name
f.input :subdomain
end
f.inputs "General Customisation" do
f.input :standalone_background, :hint => (("current image:<br/>").html_safe + f.template.image_tag(f.object.standalone_background.url(:thumb))).html_safe, :as => :file
f.input :remove_standalone_background, as: :boolean, required: false, label: "remove standalone background"
end
end
In your model
You could define a status flag like bellow
attr_writer :remove_standalone_background
def remove_standalone_background
#remove_standalone_background || false
end
OR (depreciated in rails 3.2)
attr_accessor_with_default : standalone_background,false
before_save :before_save_callback
And
def before_save_callback
if self.remove_standalone_background
self.remove_standalone_background=nil
end
end
You could implement this by creating a custom method. This can be done
member_action :custom_action, :method => :get do
//code
end
Also you should add a custom column with a link such as
index do
column "Custom" do |item|
link_to "Custom action", "/admin/items/custom_action"
end
end
Another option is to have a status flag for the attachment or image. Before saving the edited object, you unlink the image.
Thank you for your help guys. This is the final working code...
admin/product.rb
f.input :image, required: false, hint: (("Current image:<br/>").html_safe + f.template.image_tag(f.object.image.url(:thumb))).html_safe
f.input :remove_image, as: :boolean, required: false, label: "Remove Image"
models/product.rb
attr_writer :remove_image
def remove_image
#remove_image || false
end
before_validation { self.image.clear if self.remove_image == '1' }
Although accepts_nested_attributes_for(:foo, allow_destroy: true) only works with ActiveRecord associations like belongs_to we can borrow from its design to have paperclip attachment deletion work in a similar way.
(To understand how nested attributes work in Rails see http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html).
Add a <attachment_name>_attributes= writer method like below to your model that already uses has_attached_file:
has_attached_file :standalone_background
def standalone_background_attributes=(attributes)
# Marks the attachment for destruction on next save,
# if the attributes hash contains a _destroy flag
# and a new file was not uploaded at the same time:
if has_destroy_flag?(attributes) && !standalone_background.dirty?
standalone_background.clear
end
end
The <attachment_name>_attributes= method calls Paperclip::Attachment#clear to mark the attachment for destruction when the model is next saved.
Next open the existing app/admin/your_model_here.rb file (use the correct file path for your app) and setup strong parameters to permit the _destroy flag nested attribute on <attachment_name>_attributes:
ActiveAdmin.register YourModelHere do
permit_params :name, :subdomain,
:standalone_background,
standalone_background_attributes: [:_destroy]
In the same file, add a nested _destroy checkbox to the ActiveAdmin form block. This checkbox must be nested within <attachment_name>_attributes using semantic_fields_for (or one of the other nested attributes methods provided by formtastic).
form :html => { :enctype => "multipart/form-data"} do |f|
f.inputs "Details" do
...
end
f.inputs "General Customisation" do
...
if f.object.standalone_background.present?
f.semantic_fields_for :standalone_background_attributes do |fields|
fields.input :_destroy, as: :boolean, label: 'Delete?'
end
end
end
end
Your form should now show a delete checkbox when there is an attachment present. Checking this checkbox and submitting a valid form ought to delete the attachment.
Source: https://github.com/activeadmin/activeadmin/wiki/Deleting-Paperclip-Attachments-with-ActiveAdmin

Use Carrierwave with Active Admin

Did any of you guys manage to get Active Admin with Carrierwave working?
When I installed AA everything worked fine but the image file upload
fields were plain text fields so added following:
ActiveAdmin.register Club do
form do |f|
f.inputs "Club" do
f.input :league
f.input :name
f.input :image, :as => :file
f.input :approved
end
f.buttons
end
end
Now it's displayed as a file upload field and I can select a file but
after I submitted the form nothing changed. There's still no image and
the image field is empty. Anyone knows what else to do to get it
working?
Finally found the problem.
form do |f|
needs to become:
form(:html => { :multipart => true }) do |f|
I still don't know why console is not working but well, at least I can upload new images now :) Thanks a lot for the help, bruno077!
Yes, it works without an issue, remember to set the attr_accessible if you haven't. According to your configuration, you should have the following code in your model:
#app/models/club.rb
class Club < ActiveRecord::Base
attr_accessible (previous list), :image #If exists
mount_uploader :image, ImageUploader
end
And of course you should have generated the Image uploader with
rails generate uploader image
Edit: you can follow Ryan's railscast if you have any issue. That's what I did for my ActiveAdmin app with Carrierwave

Resources