I am currently using paperclip to upload images of items to my site. I set up my paperclip exactly as https://github.com/thoughtbot/paperclip. I uploaded pictures to my site but then nothing is saved to the database. There's also images found in my public folder.
in my config,
Paperclip.options[:command_path] = "/opt/local/bin/"
In my item.rb
class Item < ActiveRecord::Base
attr_accessible :photo_file_name, :photo_content_type, :photo_file_size,
:photo_updated_at
has_attached_file :photo
end
class AddPhotoColumnToItem < ActiveRecord::Migration
def self.up
add_column :items, :photo_file_name, :string
add_column :items, :photo_content_type, :string
add_column :items, :photo_file_size, :integer
add_column :items, :photo_updated_at, :datetime
end
...
end
items/_form.html.erb:
<%= form_for #item, :html => { :multipart => true } do |f| %>
<%= f.error_messages %>
<p>
<%= f.file_field :photo %>
</p>
<p><%= f.submit %></p>
<% end %>
and finally items_controller.rb (I am using cancan)
class ItemsController < ApplicationController
load_and_authorize_resource
def edit
end
def update
if #item.update_attributes(params[:item])
redirect_to #item, :notice => "Successfully updated item."
else
render :action => 'edit'
end
end
end
I checked with firebug that an image is indeed uploaded. I even puts params and I got this:
Parameters: {"utf8"=>"✓", authenticity_token"=>"XB0ptrmoxqRIakUB4YCBmbpYm2Pjex8KNm9g0pscpgo=",
"item"=>{"photo"=>#<ActionDispatch::Http::UploadedFile:0x007f9c5460ef80 #original_filename="lindsay-lohan.jpg",
#content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"item[photo]\"; filename=\"lindsay-lohan-boobs.jpg\"\r\nContent-Type: image/jpeg\r\n", #tempfile=#<File:/var/folders/14/gbn6ww_d1fs0lrcw22w50xdr0000gn/T/RackMultipart20110909-26576-auv9vl>>}, "commit"=>"Update Item", "id"=>"1"}
Anyone know why this is not working?
attr_accessible i think must be just attr_accessible :photo
Related
I got an error while setting up a polymorphic file upload with the paperclip gem on Ruby on Rails.
In the following, I will show you the relevant code parts.
I've set up a _form partial:
<%= form_for(#test_run, :html => { :multipart => true }) do |f| %>
<div class="row">
<div class="large-6 columns">
<%= fields_for :attachment do |attachment_fields| %>
<%= attachment_fields.file_field :attachment %><br />
<% end %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.submit t('buttons.general.save'), :class => "button slim", data: {disable_with: "#{t('buttons.general.disable')}"}, :alt => t('buttons.general.save'),:title => t('buttons.general.save') %>
</div>
</div>
My attachment model contains the file validation:
class Attachment < ActiveRecord::Base
belongs_to :attachable, :polymorphic => :true
has_attached_file :attachment
validates_attachment_content_type :attachment, content_type: /\A(image|application)\/.*\z/
end
In the attachment controller I whitelist the following parameters:
def attachment_params
params.require(:attachment).permit(:name, :user_id, :attachable_id, :attachable_type, :attachedfile)
end
The attachment should be attached to a test run. Here is the test run model:
class TestRun < ActiveRecord::Base
belongs_to :test_object
has_many :attachments, :as => :attachable
accepts_nested_attributes_for :attachments
end
The create method and the private methods of the test runs controller could be relevant, too:
def create
#test_run = TestRun.new(test_run_params)
attachment = Attachment.create(:attachable_id => #test_run_id, :attachment => params[:attachment])
render text: #test_run.attachments.first.inspect
end
private
# Use callbacks to share common setup or constraints between actions.
def set_test_run
#test_run = TestRun.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def test_run_params
params.require(:test_run).permit(:name, :test_object_id, :attachment, :start_time, :end_time, :test_demands, :allowed_bug_types, :max_testers, :test_language, :postprocessing_time, :test_standards, :target_tester, :target_devices)
end
To give you a completely overview, here is the attachment migration file:
class CreateAttachments < ActiveRecord::Migration
def change
create_table :attachments do |t|
t.string :name
t.integer :user_id
t.integer :attachable_id
t.string :attachable_type
t.timestamps null: false
end
end
end
Now, when I run this, fill out the form and select a valid file and submit the form after this, I receive the following error:
Paperclip::AdapterRegistry::NoHandlerError in TestRunsController#create
Ok, somehow, stackoverflow shrinks the error message, so I put it on pastebin.
If hope, someone of you could help me, as I am on this point since days of researching for bugs.
Thank you!
run migration:
rails generate paperclip attachment attachment
in your view:
<%= fields_for :attachment do |field| %>
<%= field.file_field :attachment %><br />
<% end %>
your attachment_params
def attachment_params
params.require(:attachment).permit(:name, :user_id, :attachable_id, :attachable_type, :attachment)
end
your method create
def create
#test_run = TestRun.new(test_run_params)
attachment = Attachment.create(attachment_params)
render text: #test_run.attachments.first.inspect
end
you must also included in this controller method attachment_params
I am developing a website in ruby on rails. I want to upload multiple images while creating post using paperclip. I could not find any images being uploaded into the public folder and hence images are not getting displayed when I create new post. I have created a model called Postimage.rb for images and referenced to already existing model "post".I have used paperclip to upload single image in other models and it is working fine.
rails g model postimage post:references caption:string
rails g paperclip post_images photo
Here is the Postimage.rb
class Postimage < ActiveRecord::Base
belongs_to :post
has_attached_file :photo,
:styles => {:small => "100x100>", :medium => "640x480>"}
validates_attachment_content_type :photo, :content_type => /\Aimage\/.*\Z/
end
And in the Post model,
class Post < ActiveRecord::Base
has_many :postimages
accepts_nested_attributes_for :postimages, :allow_destroy => true, :reject_if => lambda { |t| t[:postimage].nil? }
Here is the code in post controller
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
respond_to :html
def index
#posts = Post.all.order('created_at DESC').paginate(page: params[:page],:per_page =>7)
#users = User.all
respond_with(#posts)
end
def show
respond_with(#post)
end
def new
#post = Post.new
5.times {#post.postimages.build} # added this
respond_with(#post)
end
def edit
5.times{#post.postimages.build} # ... and this
end
def create
#post = current_user.posts.build(post_params)
#post.user_id = current_user.id
if #post.save
redirect_to #post, :notice =>"Post created successfully!!"
else
render "new"
end
end
def update
#post.update(post_params)
respond_with(#post)
end
def destroy
#post.destroy
redirect_to preschools_Home_path
#respond_with(#post)
end
private
def set_post
#post = Post.find(params[:id])
end
def post_params
params.require(:post).permit(:title, :content, postimages_attributes: [:caption, :photo])
end
Here is the code in _form.html in posts
<%= form_for(#post, :html =>{:multipart => true }) do |f| %>
<%=f.fields_for :postimages do |builder| %>
<%if builder.object.new_record? %>
<p>
<%= builder.label :caption, "Image Caption" %>
<%= builder.text_field :caption %>
</p>
<p>
<%= builder.label :photo, "Image File" %>
<%= builder.file_field :photo %>
</p>
<% end %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Here is the code in show.html.erb in posts
<div>
<% #post.postimages.each do |postimage|%>
<%= image_tag (postimage.photo.url(:medium))%>
<% end %>
</div>
Can you please help me. Thanks.
I have added image column to post model. And that image is getting displayed. But in the case of multiple upload, it is not working.
Logs code below might help.
Parameters: {"utf8"=>"✓", "authenticity_token"=>"PHcPmsB+a0qy6tn4U/nRyycjGFYHiFuum7LNqO8EX24+mGq+Yu7Ct0Ls/odNyAjUtVkT1cMImYRYwnpVajQRXA==", "post"=>{"title"=>"1st post", "content"=>"Added image", "postimages_attributes"=>{"0"=>{"caption"=>"1st image", "photo"=>#<ActionDispatch::Http::UploadedFile:0x007f4a351b0ba8 #tempfile=#<Tempfile:/home/ubuntu/workspace/website/RackMultipart20150715-1790-7hfszv.jpg>, #original_filename="Murali.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"post[postimages_attributes][0][photo]\"; filename=\"Murali.jpg\"\r\nContent-Type: image/jpeg\r\n">}
The solution provided below works with Paperclip as well:
Rails 4 multiple image or file upload using carrierwave
Only difference would be in post_attachment.rb
Instead of:
class PostAttachment < ActiveRecord::Base
mount_uploader :avatar, AvatarUploader
belongs_to :post
end
You would have
class PostAttachment < ActiveRecord::Base
belongs_to :post
has_attached_file :avatar, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\Z/
end
I've attempted to use the paperclip gem to add attachments to my contact model. It looks as though I can add an attachment - I can select the file without a problem. However when I then create the contact, the attachment is not saved. I know this because I can see in the rails console that the document_id is 'nil'.
In the _form.html.erb for creating a new contact, I have:
<%= simple_form_for(#contact, html: {class: "form-inline well", multipart: true}, role: "form") do |f| %>
<% if #contact.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#contact.errors.count, "error") %> prohibited this contact from being saved:</h2>
<ul>
<% #contact.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= f.input :name %>
<%= f.input :category %>
<%= f.input :area %>
<%= f.input :phone %>
<%= f.input :website %>
<%= f.input :email %>
<%= f.fields_for :document do |document_fields| %>
<%= document_fields.input :attachment, as: :file %>
<% end %>
<%= f.button :submit, class: "btn-success" %>
</div>
<% end %>
my db migration for this was:
class CreateDocuments < ActiveRecord::Migration
def change
create_table :documents do |t|
t.integer :user_id
t.timestamps
end
add_index :documents, :user_id
add_attachment :documents, :add_attachment
add_column :contacts, :document_id, :integer
end
end
My model for document.rb is:
class Document < ActiveRecord::Base
has_attached_file :attachment, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :attachment, :content_type => /\Aimage\/.*\Z/
end
and for contact.rb is:
class Contact < ActiveRecord::Base
belongs_to :user
belongs_to :document
accepts_nested_attributes_for :document
validates :name, presence: true,
length: { minimum: 2}
validates :user_id, presence: true
end
and my actions in the contacts_controller.rb are:
def create
#contact = current_user.contacts.new(contact_params)
respond_to do |format|
if #contact.save
format.html { redirect_to #contact, notice: 'Contact was successfully created.' }
format.json { render action: 'show', status: :created, location: #contact }
else
format.html { render action: 'new' }
format.json { render json: #contact.errors, status: :unprocessable_entity }
end
end
end
def contact_params
params.require(:contact).permit(:name, :email, :category, :area, :organisation, :website, :phone, :user_id, document_attributes: [:id, :attachment])
end
# PATCH/PUT /contacts/1
# PATCH/PUT /contacts/1.json
def update
#contact = current_user.contacts.find(params[:id])
if params[:contact] && params[:contact].has_key?(:user_id)
params[:contact].delete(:user_id)
end
respond_to do |format|
if #contact.update((contact_params))
format.html { redirect_to #contact, notice: 'Contact was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #contact.errors, status: :unprocessable_entity }
end
end
end
When I try to create a new contact with an attachment, here is my heroku log:
2014-03-10T23:41:49.594786+00:00 app[web.1]: Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"FGitLGkHzfw15yksCusGDvwdb//CgMyOMFh4SS4l63Y=",
"contact"=>{"name"=>"Oliver OT", "category"=>"OT", "area"=>"Rockdale",
"phone"=>"", "website"=>"", "email"=>"",
"document_attributes"=>{"attachment"=>#,
#original_filename="Screen Shot 2014-03-03 at 9.24.40 pm.png",
#content_type="image/png", #headers="Content-Disposition: form-data;
name=\"contact[document_attributes][attachment]\"; filename=\"Screen
Shot 2014-03-03 at 9.24.40 pm.png\"\r\nContent-Type:
image/png\r\n">}}, "commit"=>"Create Contact"}
2014-03-10T23:41:49.594786+00:00 app[web.1]: Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"FGitLGkHzfw15yksCusGDvwdb//CgMyOMFh4SS4l63Y=",
"contact"=>{"name"=>"Oliver OT", "category"=>"OT", "area"=>"Rockdale",
"phone"=>"", "website"=>"", "email"=>"",
"document_attributes"=>{"attachment"=>#,
#original_filename="Screen Shot 2014-03-03 at 9.24.40 pm.png",
#content_type="image/png", #headers="Content-Disposition: form-data;
name=\"contact[document_attributes][attachment]\"; filename=\"Screen
Shot 2014-03-03 at 9.24.40 pm.png\"\r\nContent-Type:
image/png\r\n">}}, "commit"=>"Create Contact"}
I'm not sure how get the attachment to save correctly?
Move the contact_params method outside of the update action so it can be accessed by the create action and change it to the following code.
def contact_params
params.require(:contact).permit(:name, :email, :category, :area, :organisation, :website, :phone, :user_id, document_attributes: [:id, :attachment])
end
The code above allows the id and attachment params for document_attributes.
Your migration has a problem:
add_attachment :documents, :add_attachment
This will mean your database table will have the attachment columns as add_attachment instead, thus causing Paperclip not to work
You'll need to change the columns in your db with a migration like this:
class Migration < ActiveRecord::Migration
def change
rename_column :documents, :add_attachment_file_name, :attachment_file_name
rename_column :documents, :add_attachment_content_type, :attachment_content_type
rename_column :documents, :add_attachment_file_size, :attachment_file_size
rename_column :documents, :add_attachment_updated_at, :attachment_updated_at
end
end
Using Rails 3.2 and Paperclip to upload multiple files (photos) at once using HTML5 multipart. Here is my form:
# shops/_form.html.erb
<%= form_for #shop, :url => { :action => action, :type => type }, :html => { :multipart => true } do |f| %>
<%= f.text_field :name %>
<%= f.file_field :shop_photos_data, :multiple => true, :name => "shop[photos_attributes][][data]" %>
<% end %>
It works and yields the following result when updated/created:
{"utf8"=>"✓",
"authenticity_token"=>"9jXvIwcllct7UyUfo6cvhEucQf2u3SY50SuaCLtFO4c=",
"shop"=>{
"name"=>"First shop",
"photos_attributes"=>{"0"=>{
"image"=>[
#<ActionDispatch::Http::UploadedFile:0x00000104b78978
#original_filename="first_test_image.jpg",
#content_type="image/jpeg",
#headers="Content-Disposition: form-data; name=\"gallery[photos_attributes][0][image][]\"; filename=\"first_test_image.jpg\"\r\nContent-Type: image/jpeg\r\n",
#tempfile=#<File:/var/folders/bQ/bQYZC2ukFZCvbKzEDGRtJE+++TI/-Tmp-/RackMultipart20110622-4459-vz78ee>>,
#<ActionDispatch::Http::UploadedFile:0x00000104b78950
#original_filename="second_test_image.jpg",
#content_type="image/jpeg",
#headers="Content-Disposition: form-data; name=\"gallery[photos_attributes][0][image][]\"; filename=\"second_test_image.jpg\"\r\nContent-Type: image/jpeg\r\n",
#tempfile=#<File:/var/folders/bQ/bQYZC2ukFZCvbKzEDGRtJE+++TI/-Tmp-/RackMultipart20110622-4459-1jzhhyg>>
]
}
}
}, "commit"=>"Save", "action"=>"create", "controller"=>"shops"}
It works, and it goes to the shops_controller.rb, but doesn't go into photos_controller.rb.
Here are my other parts of the code:
# photo.rb
class Photo < ActiveRecord::Base
belongs_to :attachable, :polymorphic => true, :counter_cache => true
belongs_to :user, :counter_cache => true
attr_accessible :data, :attachable_id, :attachable_type, :user_id
end
# shop.rb
class Shop < ActiveRecord::Base
attr_protected :photos_count
has_many :photos, :as => :attachable, :dependent => :destroy
accepts_nested_attributes_for :photos, :allow_destroy => true
end
# photos_controller.rb
class PhotosController < ApplicationController
end
# shops_controller.rb
class ShopsController < ApplicationController
before_filter :require_user, :only => [:new, :edit, :update, :create]
...
def update
#shop = Shop.find(params[:id])
if #shop.update_attributes(params[:shop])
flash[:notice] = 'Successfully updated.'
redirect_to shop_path(#shop)
else
render :action => :edit
end
end
end
I have a user_id field in my Photo model. Currently, the user_id is not saved in each new Photo record. What can I do in the shops_controller.rb to include the user_id in the file upload array? I don't want to do it in the form because it exposes security.
Thanks.
Put this in shops_controller.rb
def update
#shop = Shop.find(params[:id])
photos = params[:shop][:photos_attributes]
if !photos.blank?
photos.each do |photo|
photo.merge!(:user_id => current_user.id)
end
end
if #shop.update_attributes(params[:shop])
flash[:notice] = 'Successfully updated.'
redirect_to shop_path(#shop)
else
render :action => :edit
end
end
To add the field to the form use a hidden field like this:
<%= hidden_field_tag "user", #user.id %>
Then in the controller you can access it like this:
params[:user]
I am using CarrierWave with Rails 3.1. I am getting the following error message when I submit the form (trying to upload an image):
Error Message:
ActiveRecord::StatementInvalid in Admin::PostsController#create
NoMethodError: undefined method `name' for nil:NilClass: INSERT INTO "posts" ("body", "created_at", "draft", "image", "post_type", "title", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?, ?, ?, ?)
Rails.root: /Users/aziz/Sandbox/ruby/rails/Tumblelog
Application Trace | Framework Trace | Full Trace
app/controllers/admin/posts_controller.rb:18:in `create'
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"za+zNRDGNCcujnCmO726cWCo2ze1rgaXv5bL17JGaek=",
"post"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0x000001014aeff0 #original_filename="AzizLight.jpeg",
#content_type="image/jpeg",
#headers="Content-Disposition: form-data; name=\"post[image]\"; filename=\"AzizLight.jpeg\"\r\nContent-Type: image/jpeg\r\n",
#tempfile=#<File:/var/folders/ky/2ddtbt0d7k1g__2ctr8njcfc0000gn/T/RackMultipart20110918-21704-hp2ajt>>,
"draft"=>"0",
"user_id"=>"2",
"post_type"=>"image"},
"commit"=>"Post"}
The problem is that I don't know where this name comes from and I don't know what variable is being nil, so I can't debug properly (I tried to debug a log before asking here).
Line 18 corresponds to the #post.save line in the following controller:
PostsController:
# ...
def new
#post = Post.new
#form_html_options = (params[:post_type] == "image") ? { :multipart => true } : {}
#form_partial = get_form_partial(params[:post_type])
redirect_to admin_posts_path, :alert => "You tried to create an unknown type of post..." if #form_partial.nil?
#title = "Creating a new post..."
end
def create
#post = Post.new(params[:post])
if #post.save
flash[:success] = "Post created successfully!"
redirect_to admin_post_path(#post)
else
#title = "Creating a new post..."
#form_partial = get_form_partial(params[:post][:post_type])
render 'new'
end
end
# ...
Here other files that might be needed to spot the problem:
Post (model):
attr_accessible :title, :body, :user_id, :draft, :post_type, :image
belongs_to :user
mount_uploader :image_url, ImageUploader
ImageUploader:
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
storage :fog
def extension_white_list
%w(jpg jpeg gif png)
end
end
new.html.erb:
<h1><%= #title %></h1>
<%= form_for #post, :url => admin_posts_path, :html => #form_html_options do |f| %>
<%= render 'form', :f => f %>
<% end %>
_form.html.erb:
<%= render 'error_messages' %>
<%= render #form_partial, :f => f %>
<p class="drop-down">
<%= f.label :draft, 'Status' %>
<%= f.select(:draft, options_for_select([["Published", 0], ["Draft", 1]], (#post.new_record? ? 0: #post.draft))) %>
</p>
<%= f.hidden_field :user_id, :value => #post.user_id || current_user.id %>
<%= f.hidden_field :post_type, :value => #post.post_type || params[:post_type] %>
<p class="button"><%= f.submit "Post", :disable_with => 'Posting...' %></p>
_image_form.html.erb (#form_partial):
<p><%= f.file_field :image %></p>
So what it really going on please?
Your image uploader class was not loaded into your current rails server thread. Reload rails server and it should work fine =).
Make sure you use - mount_uploader :image, ImageUploader in your model like here -
class CarImage < ActiveRecord::Base
belongs_to :car
mount_uploader :image, ImageUploader
end
Regards
Robbie
I experienced the some problem and the cause is (probably always) that the UploadedFile object has been sent to the attribute carrierwave was mounted on. The db adapter cannot serialize this object and will therefore throw this error.
Make sure that:
the uploader has been properly mounted
you don't use write_attribute to write the uploaded file (which was the cause of my problem). Use the accessor instead: model.send('image=', params[:model][:image]). Uglier, but better.
Make sure in your model:
mount_uploader :image, ImageLoader
Remember that :image must be the string/text type.
I came across this post because I had the same error you described, but restarting the server didn't resolve it (as suggested by other answers). In my case, the problem was caused because I used mount_uploader before attr_accessible. By switching them I solved the problem.
I had a similar problem.
Solution was changing:
attr_accessible :title, :body, :user_id, :draft, :post_type, :image
belongs_to :user
mount_uploader :image_url, ImageUploader
to:
attr_accessible :title, :body, :user_id, :draft, :post_type, :image_url
belongs_to :user
mount_uploader :image_url, ImageUploader