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
Related
i just started to do a sample webpage in ruby on rails.
i am getting an error "Post model missing required attr_accessor for 'image_file_name'" when i tried to post the image from a form.
my code is
routes.rb
Rails.application.routes.draw do
resources :posts
root 'posts#index'
end
posts_controll.rb
class PostsController < ApplicationController
def index
end
def new
#post = Post.new
end
def create
#post = Post.create(post_params)
redirect_to posts_path
end
private
def post_params
params.require(:post).permit(:image, :caption)
end
end
newhtml.erb
<%= simple_form_for #post do |f| %>
<%= f.input :image %>
<%= f.input :caption %>
<%= f.button :submit %>
<% end %>
post.rb
class Post < ActiveRecord::Base
validates :image, presence: true
has_attached_file :image, styles: { :medium => "640x" }
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
end
i didnt understand the error here. i think i have done all right.
please help me guys .
Im following this tutorial: https://www.devwalks.com/lets-build-instagram-in-rails-part-1/
To create a version of instagram. When I upload an image, add a caption and submit, it will redirect to the index page as expected but the data doesnt seem to have been saved. When I open the rails console and try to get the posts with Posts.first, it returns nil.
Controller:
class PostsController < ApplicationController
def index
end
def new
#post = Post.new
end
def create
#post =Post.create(post_params)
#post.save
redirect_to posts_path
end
private
def post_params
params.require(:post).permit(:image, :caption)
end
end
Model:
class Post < ActiveRecord::Base
validates :image, presence: true
has_attached_file :image, styles: { :medium => "640x"}
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
end
form:
<%= simple_form_for #post do |f| %>
<%= f.input :image %>
<%= f.input :caption %>
<%= f.button :submit %>
<% end %>
routes:
resources :posts
root 'posts#index'
Appreciate any ideas.
Thanks
I see a few problems here:
create will save so you don't need another #post.save.
create returns the new Post object, but you have to check if it has been saved successfully or not (via #post.persisted, or via if #post.save).
From 1 & 2, I believe your post was not saved, due to validation on image presence.
Now why it's happening? I guess your form has no multipart/form-data set that the image file was not submitted at all.
To add that to simple_form (paperclip README) :
<%= simple_form_for #post, html: { multipart: true } do |f| %>
I am trying to have an image uploader on my app using Paperclip, and my only problem is that I keep getting an Undefined Method error.
I have it set up on github, https://github.com/BBaughn1/savagelysaving
My User Controller:
class UserController < ApplicationController
def create
#user = User.create( user_params )
end
def destroy
#user.image = nil
#user.save
end
private
# Use strong_parameters for attribute whitelisting
# Be sure to update your create() and update() controller methods.
def user_params
params.require(:user).permit(:image)
end
end
Then my Show.html.erb file:
<div id="post_content">
<h1 class="title">
<%= #post.title %>
</h1>
<p class="date">
Submitted <%= time_ago_in_words(#post.created_at) %> Ago
<% if user_signed_in? %>
| <%= link_to 'Edit', edit_post_path(#post) %>
| <%= link_to "Delete", post_path(#post), method: :delete, data: { confirm: 'Are you sure?' } %>
<% end %>
</p>
<p class="body">
<%= #post.body %>
<%= image_tag #post.image.url(:medium) %>
</p>
<div id="comments">
<%= render 'disqus' %>
</div>
</div>
In my post.rb file:
class Post < ActiveRecord::Base
has_many :comments, dependent: :destroy
validates :title, presence: true, length: { minimum: 5 }
validates :body, presence: true
attr_accessor :image
has_attached_file :image, styles: { medium: "300x300>", thumb: "100x100#" }, default_url: "/images/:style/missing.png"
validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/
end
in my development.rb file:
Rails.application.configure do
***STUFF***
Paperclip.options[:command_path] = "/usr/local/bin/"
end
and posts controller:
class PostsController < ApplicationController
# before_action :find_post, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
#posts = Post.all.order('created_at DESC')
end
def new
#post = Post.new
attr_accessor :image
end
def create
attr_accessor :image
#post = Post.new(post_params)
if #post.save
redirect_to #post
else
render 'new'
end
end
def show
#post = Post.find(params[:id])
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
attr_accessor :image
if #post.update(params[:post].permit(:title, :body, :image))
redirect_to #post
else
render 'edit'
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
redirect_to root_path
end
private
def post_params
params.require(:post).permit(:title, :body, :image)
end
end
There is no avatar attribute in your user model but there is an image attribute in your post model.
If you remove below code from user model and move it to post model, the image upload will work
has_attached_file :image, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/
This should fix the bug.
I looked at your github to see if you made the same mistake I did. I think you forgot to add imagemagick to your development.rb file. When you install imagemagick on your local machine, it need to see where it's installed; which convert where show where. It might look like this Paperclip.options[:command_path] = "/usr/local/bin/" if not, just copy what it show you and edit what's in the quotes " ".
I hope that helps I know I was having some trouble getting it to work.
I have a rails app with a Project model and a nested Pictures model. Im using the Paperclip gem to upload images to the pictures model, and nested_form gem to nest the Picture model within the projects. Everything was working perfectly, the images were showing and the code seemed to be working fine, until suddenly after working on another part of the app, I started getting the error mentioned in the question title. Specifically, this line in my index page seems to be the issue: <%= link_to image_tag(project.pictures.first.image.url(:thumb)), project %> I cant seem to figure out the problem as it was working fine before. I even reverted back to a previous commit when it was working, and im still getting the same error. Im totally stumped. Any help would be highly appreciated!
Index:
<div id="pictures">
<% #projects.each do |project| %>
<div class="col-md-4">
<div class="box panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><%= project.title %></h3>
</div>
<div class="image">
<%= link_to image_tag(project.pictures.first.image.url(:thumb)), project %>
</div>
<div class="panel-body">
<p>
<strong>Progress:</strong>
<%= progress_bar 0.6, label: true, alternative: 'info', striped: true %>
</p>
<p>
<strong>Status:</strong>
<%= project.status %>
</p>
<p>
<strong>Phase:</strong>
<%= project.phase %>
</p>
<%= link_to 'Show', project %> |
<%= link_to 'Edit', edit_project_path(project) %> |
<%= link_to 'Destroy', project, method: :delete, data: { confirm: 'Are you sure?' } %>
</div>
</div>
</div>
<% end %>
</div>
Projects model:
class Project < ActiveRecord::Base
has_many :pictures, :dependent => :destroy
has_many :teams, :dependent => :destroy
accepts_nested_attributes_for :pictures, :reject_if => lambda { |a| a[:image].blank? }, allow_destroy: true
accepts_nested_attributes_for :teams, :reject_if => lambda { |a| a[:member].blank? }, allow_destroy: true
end
Pictures model:
class Picture < ActiveRecord::Base
belongs_to :project
has_attached_file :image,
path: ":rails_root/public/system/:attachment/:id/:style/:filename",
url: "/system/:attachment/:id/:style/:filename",
:styles => { :medium => "900x900>", :thumb => "300x300>" }
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
end
Projects controller:
class ProjectsController < ApplicationController
before_action :set_project, only: [:show, :edit, :update, :destroy]
respond_to :html
def index
#projects = Project.all
respond_with(#projects)
end
def show
respond_with(#project)
end
def new
#project = Project.new
#project.pictures.build
#project.teams.build
respond_with(#project)
end
def edit
end
def create
#project = Project.new(project_params)
if #project.save
flash[:notice] = "Successfully created project."
redirect_to #project
else
render :action => 'new'
end
end
def update
#project.update(project_params)
respond_with(#project)
end
def destroy
#project.destroy
respond_with(#project)
end
private
def set_project
#project = Project.find(params[:id])
end
def project_params
params.require(:project).permit(:id, :title, :description, :status, :phase, :location, :contractor, :designer, :area, :budget, :project_start, :construction_period, :expected_date, :picture_id, :image, pictures_attributes: [:id, :image, :_destroy], teams_attributes: [:project_id, :user_id, :id, :member, :role, :_destroy])
end
end
Pictures controller:
class PicturesController < ApplicationController
before_action :set_picture, only: [:show, :edit, :update, :destroy]
respond_to :html
def index
#pictures = Picture.all
respond_with(#pictures)
end
def show
respond_with(#picture)
end
def new
#picture = Picture.new
respond_with(#picture)
end
def edit
end
def create
#picture = Picture.new(picture_params)
#picture.save
respond_with(#picture)
end
def update
#picture.update(picture_params)
respond_with(#picture)
end
def destroy
#picture.destroy
respond_with(#picture)
end
private
def set_picture
#picture = Picture.find(params[:id])
end
def picture_params
params.require(:picture).permit(:image, :id, :project_id)
end
end
Most certainly, one of your projects has no pictures.
When you call project.pictures.first.image.url(:thumb) for each of your projects, you are getting all of its pictures, then the first one of those, and then the image for that first picture.
If your project has no pictures, then project.pictures is an empty set. When you call .first on an empty set, the result is nil. nil is an object, of class NilClass, and it has no method named image. Ensure that each one of your projects has at least one image and you will not see the error. Alternatively you can create an if statement around your link_to, so that you only evaluate that line if !project.pictures.empty?.
I'm working on a website that allows people who run bed and breakfast businesses to post their accommodations.
I would like to require that they include a "profile image" of the accommodation when they post it, but I also want to give them the option to add more images later (this will be developed after).
I thought the best thing to do would be to use the Paperclip gem and have a Accommodation and a Photo in my application, the later belonging to the first as an association.
A new Photo record is created when they create an Accommodation. It has both id and accommodation_id attributes. However, the image is never uploaded and none of the Paperclip attributes get set (image_file_name: nil, image_content_type: nil, image_file_size: nil), so I get Paperclip's "missing" photo.
Any ideas on this one? It's been keeping me stuck for a few days now.
Accommodation
models/accommodation.rb
class Accommodation < ActiveRecord::Base
validates_presence_of :title, :description, :photo, :thing, :location
attr_accessible :title, :description, :thing, :borough, :location, :spaces, :price
has_one :photo
end
controllers/accommodation_controller.erb
class AccommodationsController < ApplicationController
before_filter :login_required, :only => {:new, :edit}
uses_tiny_mce ( :options => {
:theme => 'advanced',
:theme_advanced_toolbar_location => 'top',
:theme_advanced_toolbar_align => 'left',
:theme_advanced_buttons1 => 'bold,italic,underline,bullist,numlist,separator,undo,redo',
:theme_advanced_buttons2 => '',
:theme_advanced_buttons3 => ''
})
def index
#accommodations = Accommodation.all
end
def show
#accommodation = Accommodation.find(params[:id])
end
def new
#accommodation = Accommodation.new
end
def create
#accommodation = Accommodation.new(params[:accommodation])
#accommodation.photo = Photo.new(params[:photo])
#accommodation.user_id = current_user.id
if #accommodation.save
flash[:notice] = "Successfully created your accommodation."
render :action => 'show'
else
render :action => 'new'
end
end
def edit
#accommodation = Accommodation.find(params[:id])
end
def update
#accommodation = Accommodation.find(params[:id])
if #accommodation.update_attributes(params[:accommodation])
flash[:notice] = "Successfully updated accommodation."
render :action => 'show'
else
render :action => 'edit'
end
end
def destroy
#accommodation = Accommodation.find(params[:id])
#accommodation.destroy
flash[:notice] = "Successfully destroyed accommodation."
redirect_to :inkeep
end
end
views/accommodations/_form.html.erb
<%= form_for #accommodation, :html => {:multipart => true} do |f| %>
<%= f.error_messages %>
<p>
Title<br />
<%= f.text_field :title, :size => 60 %>
</p>
<p>
Description<br />
<%= f.text_area :description, :rows => 17, :cols => 75, :class => "mceEditor" %>
</p>
<p>
Photo<br />
<%= f.file_field :photo %>
</p>
[... snip ...]
<p><%= f.submit %></p>
<% end %>
Photo
The controller and views are still the same as when Rails generated them.
models/photo.erb
class Photo < ActiveRecord::Base
attr_accessible :image_file_name, :image_content_type, :image_file_size
belongs_to :accommodation
has_attached_file :image,
:styles => {
:thumb=> "100x100#",
:small => "150x150>" }
end
To create an upload with paperclip, you need to use the name you provided for the has_attached_file line, on the model you defined it on. In your case, this will result in this view code:
<%= form_for #accommodation, :html => { :multipart => true } do |f| %>
<%= f.fields_for :photo do |photo_fields| %>
<p>
Photo<br />
<%= photo_fields.file_field :image %>
</p>
<% end %>
<% end %>
In the controller:
class AccommodationsController < ApplicationController
# also protect create and update actions!
before_filter :login_required, :only => [ :new, :create, :edit, :update ]
def new
# always make objects through their owner
#accommodation = current_user.accommodations.build
#accommodation.build_photo
end
def create
#accommodation = current_user.accommodations.build(params[:accommodation])
if #accommodation.save
# always redirect after successful save/update
redirect_to #accommodation
else
render :new
end
end
end
Tell Rails to handle the nested form:
class Accommodation
has_one :photo
accepts_nested_attributes :photo
attr_accessible :photo_attributes, :title, :description, :etc
end
And make sure to set the accessible attributes right in your photo model:
class Photo
attr_accessible :image # individual attributes such as image_file_name shouldn't be accessible
has_attached_file :image, :styles => "etc"
end
Be sure to watch your log files to spot things that are protected by attr_accessible, but still are in your form.