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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With