I've been struggling for a week now, I'm trying to create a form inside active_admin where a user can select several pictures, add a description and a title, then submitting his form to create something that would look like a gallery
So far, I have two models created with the commands:
rails g model Gallery title:string description:text
rails g model Image url:text #just in case the user has LOTS of images to upload
Here are how look my models now:
gallery.rb
class Gallery < ApplicationRecord
has_many :images
accepts_nested_attributes_for :images, allow_destroy: true
end
image.rb
class Image < ApplicationRecord
belongs_to :gallery
mount_uploader :image, ImageUploader #Using Carrier Wave
end
admin/gallery.rb
permit_params :title, :description, :images
form html: { multipart: true } do |f|
f.inputs do
f.input :title
f.input :description
f.input :images, as: :file, input_html: { multiple: true }
end
f.actions
end
My problem is that even though my 'image' form shows up, I can't manage to save the images through the other model, nothing gets uploaded inside my 'public/upload' directory, and nothing gets written inside my database.
I can't find anything interesting internet that could solve this problem
Feel free to ask for another file
Any help welcome
permit_params :title, :description, :images
Why :images, I think you meant images_attributes: [:url]?
But that wouldn't work either. I followed the steps here: https://github.com/carrierwaveuploader/carrierwave/issues/1653#issuecomment-121248254
You can do it with just one model
rails g model Gallery title:string description:text url:string
models/gallery.rb
# your url is accepted as an array, that way you can attach many urls
serialize :url, Array
mount_uploaders :url, ImageUploader
Note: Use serialize with Sqlite, For Postgres or some other database capable of handling arrays read: Add an array column in Rails
admin/gallery.rb
permit_params :title, :description, url: []
form html: { multipart: true } do |f|
f.inputs do
f.input :title
f.input :description
f.input :url, as: :file, input_html: { multiple: true }
end
f.actions
end
Related
I have two models
class ComfortFactorSubCategory < ApplicationRecord
has_one :image, as: :imageable, dependent: :destroy
validates :heading, presence: true
accepts_nested_attributes_for :image, :reject_if => lambda { |a| a[:name].blank? }, allow_destroy: true
end
class Image < ApplicationRecord
belongs_to :imageable, polymorphic: true
mount_uploader :name, IconUploader
end
and my admin/comfort_factor_sub_category.rb I have these lines
ActiveAdmin.register ComfortFactorSubCategory do
permit_params do
permitted = [:heading, image_attributes: [:name, :_destroy, :id], additional_instruction_ids: []]
permitted
end
form do |f|
f.inputs do
f.input :heading
f.input :additional_instructions, as: :select, collection: AdditionalInstruction.pluck(:description, :id)
f.fields_for :image do |b|
b.input :name, label: "Image", :as => :file
end
end
f.actions
end
end
when I submit the form with wrong information lets say without heading and validation fail why do I need to select the image again while I did select in first submission
Seems like you need f.hidden_filed :name_cache for caching uploaded file
Take a look at the CarrierWave making uploads work across form redisplays section and upload through accept_nested_attributes_for wiki article
This is constrained by browser for security reasons. It avoids pre-filling the form with the default file object's value when error page is rendered.
This is a detailed excerpt about this.
This however is usually not supported by browsers. The usual
explanation is “security reasons.” And indeed it would be a security
risk if files from the user’s disk were submitted without the user’s
content. It might be all too easy to lure some users into submitting
some password files!
I also found this another answer talking about the same problem with ASP.net framework.
I have 3 models :
User
Dish
Dish_Image
and I am using devise, paperclip and aws s3 to create users and attach images to the dishes.
Question : The dish is getting created and associated correctly to the user, but the image information is not getting inserted into the dish_image table and no errors are seen anywhere.
I have provide snippets of code what I think may be necessary, but please let me know if any more information is needed.
The app/models/user.rb
Class User < ActiveRecord::Base
has_many :dishes
The app/models/dish.rb
class Dish < ActiveRecord::Base
belongs_to :user, dependent: :delete
has_many :dish_images
accepts_nested_attributes_for :dish_images
The app/models/dish_image.rb
class DishImage < ActiveRecord::Base
belongs_to :dish, dependent: :delete
has_attached_file :d_image, styles: {
thumb: '100x100>',
square: '200x200#',
medium: '300x300>'
}
# Validate the attached image is image/jpg, image/png, etc
validates_attachment_content_type :d_image, :content_type => /\Aimage\/.*\Z/
end
My dish_images_controller.rb file for create reads
def create
#dish = Dish.find(params[:dish_id])
#dish_image = #dish.dishimages.build(dish_image_params)
if #dish_image.save!
flash[:success] = "Image has been uploaded!"
else
flash[:notice] = "Image upload did not work!"
end
end
private
def dish_image_params
params.require(:dish_image).permit(:d_image)
end
The view for upload is
%h2 New Dish
= bootstrap_form_for([current_user, #dish], :html => { :multipart => true }) do |f|
%div
= f.text_field :title, autofocus: true
%div
= f.text_field :desc, autofocus: true
%div
= f.fields_for :dish_images do |ff|
Dish Image:
= ff.file_field :d_image, hide_label: true
%div= f.submit "Submit Dish"
and rake routes gives:
user_dish_dishimages GET /users/:user_id/dishes/:dish_id/dishimages(.:format) dishimages#index
POST /users/:user_id/dishes/:dish_id/dishimages(.:format) dishimages#create
user_dish_dishimage DELETE /users/:user_id/dishes/:dish_id/dishimages/:id(.:format) dishimages#destroy
Question : The dish is getting created and associated correctly to the user, but the image information is not getting inserted into the
dish_image table and no errors are seen anywhere.
Firstly, when the nested form is submitted, the create action of DishesController would be called. In order to save the dish_images records, you would need to whitelist dish_images_attributes in DishesController.
For example:
def dish_params
params.require(:dish).permit(:title, :desc, dish_images_attributes: [:id, :d_image])
end
NOTE: If you already have dish_params method to whitelist the attributes you would just need to update the arguments passed to permit in it. If your method for whitelisting attributes is named other than dish_params then update it accordingly.
Using ActiveAdmin with Rails 4, I have two models, Document and Attachment with a one-to-many relationship between them.
# models/document.rb
class Document < ActiveRecord::Base
has_many :attachments
accepts_nested_attributes_for :attachments
end
# models/attachment.rb
class Attachment < ActiveRecord::Base
belongs_to :document
end
I registered the models and included permit_params for all the fields in each.
Now I used has_many in the form view in the below code. This shows an option to add Attachments and it work just fine.
# admin/document.rb
ActiveAdmin.register Document do
permit_params :title, :description, :date, :category_id
show do |doc|
attributes_table do
row :title
row :description
row :attachments do
doc.attachments.map(&:document_path).join("<br />").html_safe
end
end
end
form do |f|
f.inputs "Details" do
f.input :title
f.input :description
f.input :category
f.has_many :attachments, :allow_destroy => true do |cf|
cf.input :document_path # which is a field in the Attachment model
end
end
f.actions
end
end
However, when I submit the form, the document object is saved but no attachment objects are saved with it. As much as I understand it should create as many attachments I added in the form and pass in their document_id attribute the created document ID. Unfortunately this is not happening leaving the Attachment row "EMPTY" in the show view. Am I missing something?
Thanks in advance.
You forgot to permit attachments_attributes.
In order to use accepts_nested_attribute_for with Strong Parameters, you will need to specify which nested attributes should be whitelisted.
More info http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html
I'm after some advice in regards to handling nested form data and I would be ever so grateful for any insights.
The trouble is I'm not 100% sure why I require the following code in my model
accepts_nested_attributes_for :holiday_image, allow_destroy: true, :reject_if => lambda { |a| a[:title].blank? }
I don't understand why I require to tact on on my accepts_nested_attributes_for association:
:reject_if => lambda { |a| a[:title].blank? }
If I remove this :reject_if lambda, it will save a blank holiday photo object in the database. I presume because it takes the :title field from the form as an empty string?
I guess my question is, am I doing this right or is there a better way of this this within nested forms if I want to extend my HolidayImage model to include more strings like description, notes?
Sorry If I couldn't be more succinct.
My simple holiday app.
# holiday.rb
class Holiday < ActiveRecord::Base
has_many :holiday_image
accepts_nested_attributes_for :holiday_image, allow_destroy: true, :reject_if => lambda { |a| a[:title].blank? }
attr_accessible :name, :content, :holiday_image_attributes
end
I'm using CarrierWave for image uploads.
# holiday_image.rb
class HolidayImage < ActiveRecord::Base
belongs_to :holiday
attr_accessible :holiday_id, :image, :title
mount_uploader :image, ImageUploader
end
Inside my _form partial there is a field_for block
<h3>Photo gallery</h3>
<%= f.fields_for :holiday_image do |holiday_image| %>
<% if holiday_image.object.new_record? %>
<%= holiday_image.label :title, "Image Title" %>
<%= holiday_image.text_field :title %>
<%= holiday_image.file_field :image %>
<% else %>
Title: <%= holiday_image.object.title %>
<%= image_tag(holiday_image.object.image.url(:thumb)) %>
Tick to delete: <%= holiday_image.check_box :_destroy %>
<% end %>
Thanks again for your patience.
accepts_nested_attributes_for is normally used to build children during mass-assignment (when creating a new record, building any associated models). For instance, if you have a model like User which has_many UserPhotos, you could take multiple UserPhotos during the creation of a User, and have them all built on User creation.
I don't believe you need to deal with nested attributes since you're just mounting a single image (ImageUploader) on a single model (HolidayImage). This gives the model HolidayImage a single field, :image, which CarrierWave will use to mount an instance of the ImageUploader.
There are a few approaches to handle this, but here is some basic information you should know:
You can use validates_presence_of :image to ensure the :image is present. This works because the mounted uploader implements the present? method used by the validation API (see Carrier Wave Wiki on Validating uploads with ActiveRecord). This way you don't have to test if the title is set, but instead can test if the image was uploaded before allowing the model to be created. Of course you should handle failed validations as necessary.
You can add a before_save that does anything you'd like, which can ask CarrierWave if the image is present or just uploaded. In your case you can call image.present? and image_changed? respectively to test for this in your HolidayImage model. See this CarrierWave How To for an example.
If you'd like to accept more than one image in a nested form, see this CarrierWave How To on using accept_nested_attributes_for.
I have the models Home and Photo, which have a has_many - belongs_to relationship (a polymorphic relationship, but I dont think that matters in this case). I am now setting up active admin and I would like admins to be able to add photos to homes from the homes form.
The photos are managed by the CarrierWave gem, which I dont know if will make the problem easier or harder.
How can I include form fields for a different model in the Active Admin Home form? Any experience doing something like this?
class Home < ActiveRecord::Base
validates :name, :presence => true,
:length => { :maximum => 100 }
validates :description, :presence => true
has_many :photos, :as => :photographable
end
class Photo < ActiveRecord::Base
belongs_to :photographable, :polymorphic => true
mount_uploader :image, ImageUploader
end
Try something like this in app/admin/home.rb:
form do |f|
f.inputs "Details" do
f.name
end
f.has_many :photos do |photo|
photo.inputs "Photos" do
photo.input :field_name
#repeat as necessary for all fields
end
end
end
Make sure to have this in your home model:
accepts_nested_attributes_for :photos
I modified this from another stack overflow question: How to use ActiveAdmin on models using has_many through association?
You could try this:
form do |f|
f.semantic_errors # shows errors on :base
f.inputs # builds an input field for every attribute
f.inputs 'Photos' do
f.has_many :photos, new_record: false do |p|
p.input :field_name
# or maybe even
p.input :id, label: 'Photo Name', as: :select, collection: Photo.all
end
end
f.actions # adds the 'Submit' and 'Cancel' buttons
end
Also, you can look at https://github.com/activeadmin/activeadmin/blob/master/docs/5-forms.md (See Nested Resources)
I guess you are looking for a form for a nested model. Take a look at following railscasts.
http://railscasts.com/episodes/196-nested-model-form-part-1
http://railscasts.com/episodes/197-nested-model-form-part-2
I cannot tell you much about active_admin, but I think this should not make a difference in handling the nested model.
I have a has_one model, like this:
f.has_many :addresses do |a|
a.inputs "Address" do
a.input :street ... etc.
While this correctly reflects our associations for Address (which is a polymorphic model) using f.has_one fails. So I changed over to has_many and all's well. Except now we have to prevent our users from creating multiple addresses for the same entity.