carrierwave + nested models: file_field not calling "create" method - ruby-on-rails

I am trying to follow Railscast Ep 381 to integrate multi-file upload into my Rails app. For my app, the Projects model has many Steps, and Steps have many Images. The Image model is using a Carrierwave uploader.
Right now, I'm able to upload single image files from within the edit_steps path. But I'm trying to design the upload interface so that a gallery on the edit_steps page automatically refreshes once new images have been added (so once images have been selected but the form has not yet been submitted).
According to the Railscast episode, when you select images, they should automatically call the create action for each file. But my application is clearly not doing that. How can I ensure that the create method of the Image model is being called?
step.rb
class Step < ActiveRecord::Base
extend FriendlyId
friendly_id :number
attr_accessible :description, :name, :number, :project_id, :images_attributes
belongs_to :project
has_many :images
accepts_nested_attributes_for :images, :allow_destroy => :true
end
image.rb
class Image < ActiveRecord::Base
attr_accessible :project_id, :step_id, :file, :caption
belongs_to :step
belongs_to :project
mount_uploader :file, FileUploader
end
views/steps/edit.html.erb
%= semantic_form_for [#project, #step], :html => {:multipart => true} do |f| %>
<%= f.inputs do%>
....
<div id="images">
<%= render :partial => 'images/image', :collection => #step.images.all %>
</div>
<div class="clear"></div>
....
<%= f.fields_for :images, Image.new do |image_form| %>
<%= image_form.file_field :file, multiple: true, name: "image[file]"%>
<%end%>
javascript/images.js.coffee
jQuery ->
$('#new_image').fileupload
dataType: "script"
controllers/images.controller
def create
#image = Image.create(params[:image])
end
images/create.js.erb
<% if #image.new_record? %>
alert("Failed to upload image: <%= j #image.errors.full_messages.join(', ').html_safe %>");
<% else %>
alert("adding images")
$("#images").append("<%= j render(#image) %>");
<% end %>

Related

rails file_field not showing

I would like to make my app upload multiple files with Shrine, but one doc suggests two file_fields whereas the other suggests only one. After posting a question to their discourse forum, it was suggested that I hide the one named files[]. Whether I do this or not, the first file_field always fails to render. Why does this field not display?
<%= form_for #item, html: { enctype: "multipart/form-data" } do |f| %>
<%= f.fields_for :photos do |i| %>
<%= i.label :image %>
<%= i.hidden_field :image, value: i.object.cached_photos_data, class: "upload-data" %>
<%= i.file_field :image, class: "upload-file" %> /// why is this not rendering?😢
<% end %>
<%= file_field_tag "files[]", multiple: true %> // what purpose does this one serve?
<%= f.text_field :title %>
<%= f.submit "Submit" %>
<% end %>
Models:
class Item < ApplicationRecord
has_many :photos, as: :imageable, dependent: :destroy
end
class Photo < ApplicationRecord
include ImagesUploader::Attachment(:image)
belongs_to :imageable, polymorphic: true
validates_presence_of :image
end
Controller:
class ItemsController < ApplicationController
def new
#item = current_user.items.new
end
def create
#item = current_user.items.create(item_params)
#item.save
end
private
def item_params
params.require(:item).permit(:title, photos_attributes: { image: [] })
end
end
Read the first link carefully: It says that the single field (i.file_field :image) is used to display existing images (which is why it's wrapped in f.fields_for :photos in the example) and the multiple field (file_field_tag "files[]", multiple: true) is used to upload new files. So if your #item doesn't have an :image, then the field isn't shown.
Let me know if this needs any further clarification – happy to help!

rails 4 unpermitted params nested form

I know there are alot of these kinds of posts on SO, and I think Ive read and tried each of them, all without success.
I have Post and Image models that I need to work together with a many to one relationship.
class Post < ActiveRecord::Base
has_many :images
end
class Image < ActiveRecord::Base
belongs_to :post
mount_uploader :file, images_uploader
end
Here is the post_parms declaration in my posts controller, which includes all of the fields in my image model migration.
private
def post_params
params.require(:post).permit(:title, :content, image_attributes: [:id, :post_id, :file])
end
and here is my post creation form where, I hope to allow multiple image asset creation with each post.
<%= form_for #post, html: {class: "pure-form pure-form-stacked"} do |post| %>
<%= post.fields_for :image, :html => { :multipart => true } do |image| %>
<%= image.label :file, "Upload Image:" %>
<%= image.file_field :file, multiple: true %>
<% end %>
<fieldset class="post-form">
<%= post.label :title %>
<%= post.text_field :title %>
<%= post.label :content %>
<%= post.text_area :content, :class => "redactor", :rows => 40, :cols => 120 %>
</fieldset>
<div class = "button-box">
<%= post.submit class: "pure-button pure-button-primary" %>
<%= link_to "Cancel", posts_path, :class => "pure-button" %>
</div>
Despite repeated effort and reading every post I can find on this topic, I'm still getting:
Unpermitted parameters: image
The trouble here is that this error provides no clue where to start looking for the problem. Since Im not really sure where to look next I thought I would post it here looking for more professional opinions.
Update the Post model as below:
class Post < ActiveRecord::Base
has_many :images
accepts_nested_attributes_for :images ## Add this
end
This way upon form submission you would receive the image attributes in key images_attributes and not image which you are currently receiving which is causing the warning as Unpermitted parameters: image
As you have 1-M relationship between Post and Image
You need to update post_params as below:
def post_params
params.require(:post).permit(:title, :content, images_attributes: [:id, :post_id, :file])
end
Use images_attributes (Notice plural images) and NOT image_attributes (Notice singular image)
And change fields_for in your view as
<%= post.fields_for :images, :html => { :multipart => true } do |image| %>
Use images (Notice plural) and NOT image (Notice singular)
UPDATE
To resolve uninitialized constant Post::Image error
Update Image model as below:
class Image < ActiveRecord::Base
belongs_to :post
## Updated mount_uploader
mount_uploader :file, ImagesUploader, :mount_on => :file
end
Also, suggested to remove multiple: :true from
<%= ff.file_field :file, multiple: true %>

rails 3.2.x, simple_form_for, paperclip, multiple uploads

Ok just to get this out of the way I dont need anything fancy just to be able to list 5 file fields for uploading images. Currently, I receive no errors when visiting the form but the form file upload inputs aren't being display where the rest of the form is rendering properly.
Things I have working so far:
s3 with paperclip
Upload single files
With that said Ill post portions of the models to give a better picture of my setup:
My product model:
has_many :photos
attr_accessible :name, :description, :price, :category_id, :location_ids
accepts_nested_attributes_for :photos, :allow_destroy => true
My photo model:
belongs_to :products
attr_accessible :image,
has_attached_file :image, styles: {
thumb: '100x100>',
square: '200x200#',
medium: '300x300>'
}
My product controller:
def new
#product = Product.new
5.times { #product.photos.build }
end
My product post form:
<%= simple_form_for #product,
:url => admin_products_path do |form| %>
<% form.simple_fields_for :photos do |builder| %>
<% if builder.object.new_record? %>
<p>
<%= builder.input :image %>
</p>
<% end %>
<% end %>
....
<% end %>
I tried to keep this as simple as possible since this is my first implementation. Most of the documentation online was for a little bit older rails but I attempted to make it work with rails 3.2.1, paperclip, simple_forms_for, aws-sdk.
Please help :D
I believe you need to use the erb output syntax for the simple_fields_for nested attributes helper:
<%= form.simple_fields_for :photos do |builder| %>
# ^ ...

Carrierwave image upload in nested form still creating record even no file is specified

I have a Carrierwave image upload in a nested simple_form which works (sort of) unless the user does not specify a file, in which case a blank Picture object is created unless there was a previously existing one. Not quite sure how to make it so that if the user doesn't specify a "new" image to upload, the old one isn't deleted and/or a blank record without a file is created.
One (maybe odd) thing I am doing is always sending the logged in #user to the user#edit action, then building a #user.picture if it doesn't exist. I am thinking this is where my bad design is.
# user.rb
class User < ActiveRecord::Base
[...]
has_one :picture, :dependent => :destroy
accepts_nested_attributes_for :picture
[...]
end
# picture.rb
class Picture < ActiveRecord::Base
attr_accessible :image, :remove_image
belongs_to :user
mount_uploader :image, ImageUploader
end
# users_controller.rb
def edit
if #user.picture.nil?
#user.build_picture
end
end
#_form.html.erb
<%= simple_form_for #user, :html => {:multipart => true} do |f| %>
<%= render "shared/error_messages", :target => #user %>
<h2>Picture</h2>
<%= f.simple_fields_for :picture do |pic| %>
<% if #user.picture.image? %>
<%= image_tag #user.picture.image_url(:thumb).to_s %>
<%= pic.input :remove_image, :label => "Remove", :as => :boolean %>
<% end %>
<%= pic.input :image, :as => :file, :label => "Picture" %>
<%= pic.input :image_cache, :as => :hidden %>
<% end %>
<br/>
#rest of form here
<% end %>
I think I had the same issue which I solved by adding a reject_if option to the accepts_nested_attribute. So in your example, you could do something like
class User < ActiveRecord::Base
[...]
has_one :picture, :dependent => :destroy
accepts_nested_attributes_for :picture,
:reject_if => lambda { |p| p.image.blank? }
[...]
end
When you use build_* it sets the foreign key on the object. ( similar to saying Picture.new(:user_id => id) )
Try This
# users_controller.rb
def edit
if #user.picture.nil?
#user.picture = Picture.new
end
end
Today I had the same problem, I solved this like:
accepts_nested_attributes_for :photos,
:reject_if => :all_blank

Rails 3 - Update_attribues won't get changed parameters

i have somes relations in my table like this
Model : Floors
has_many :photo
Model : Photo
belongs_to :floors
belongs_to :file_type
Model : file_type
has_many :photo
Photo are nested attributes with render inside floors form.
The problem is if i change the file type inside the form without any other change in the form, the new selected alements are not updated, and the update_attributes (in the WEBrick) console, the new selected are not updated.
Photo are a paperclip element with versioning. I don't want to update each time the file if i just want to change his file type related.
Thanks for your help.
EDIT : Has asked, my views.
# _form.html.erb
<% f.fields_for :floor_photo do |floor_photo| -%>
<%= render 'floor_photo_fields', :f => floor_photo %>
<% end -%>
<div>
<%= link_to_add_fields "Add Photo", f, :floor_photo %>
</div>
# _floor_photo_fields.html.erb
<div class="fields">
<%= f.label 'Photo' %><br/>
<%= f.file_field :photo %>
<%= f.collection_select :file_type_id, FileType.all(:order => 'name'), :id, :name, {:prompt => 'Select'}%>
<%= link_to_remove_fields "remove", f %><br/>
<div style="margin-bottom:10px;"><%= f.object.photo_file_name %></div>
</div>
For now, if i click Add Photo, and set a file type to the photo, it's work, but when i edit a floors and want to change the file type, he don't want to take the new file_type_id and don't do any update sql statement. Like if i have nothing changed in my form.
And yes, sorry for my relations, it was a typo mistake, all are good in my models form.
# floor_photo.rb
class FloorPhoto < ActiveRecord::Base
versioned
belongs_to :floor
belongs_to :file_type
has_attached_file :photo, :keep_old_files => true, :url => "/system/buildings/photos/:id/:version/:basename.:extension",
:path => ":rails_root/public/system/buildings/photos/:id/:version/:basename.:extension"
Paperclip.interpolates :version do |attachment, style|
attachment.instance.version.to_s
end
end
# file_type.rb
class FileType < ActiveRecord::Base
has_many :floor_photos
end
I hope this help someone to help me.
Sorry, here is my controller
floors_controllers.rb
def edit
#floor = Floor.find(params[:id])
end
def update
#floor = Floor.find(params[:id])
if #floor.update_attributes(params[:floor])
redirect_to space_path(#floor)
else
render :action => 'edit'
end
end
The code doesn't look right:
Model : Floors
has_many :photo #should be :photos
Model : Photo
belongs_to :floors #should be :floor
belongs_to :file_type
Model : file_type
has_many :photo #should be :photos

Resources