Paperclip not saving images on posts - ruby-on-rails

Trying to learn rails etc by making a simple forum. I want users to be able to add an image to a post they create, but when I try it, it doesn't seem to add/save the picture. Paperclip is installed properly, as is ImageMagick. This is the code.
(btw I'm using .haml)
Edit: Changed .permit to (:image_file) so I can post now, but it doesn't attach the image.
Post Model
class Post < ActiveRecord::Base
has_many :comments
belongs_to :user
has_attached_file :image, styles: {large: "600x600>", medium: "300x300>", thumb: "100x100#"}
validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/
end
Form for posting
= simple_form_for #post, html: { multipart: true } do |f|
= f.input :title
= f.input :content
= f.file_field :image
= f.submit
Post Params
def post_params
params.require(:post).permit(:title, :content, :image_file)
end
Post Output
#post_content
%h1= #post.title
%p= #post.content
=image_tag #post.image.url(:medium)
Post 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 show
end
def new
#post = current_user.posts.build
end
def create
#post = current_user.posts.build(post_params)
if #post.save
redirect_to #post
else
render 'new'
end
end
def edit
end
def update
if #post.update(post_params)
redirect_to #post
else
render 'edit'
end
end
def destroy
#post.destroy
redirect_to root_path
end
private
def find_post
#post = Post.find(params[:id])
end
def post_params
params.require(:post).permit(:title, :content, :image_file)
end
end

Related

Multi-Step Form debugging Rails - ActionController::ParameterMissing

I understand that this issue has been raised several times, but I can't find to find a way around..
I am using this solution to create a multi-step form without the Wicked gem:
Best way to make Multi-Steps form in Rails 5
It seems that I am able to create a product when I use binding.pry and enter the needed commands inside my rails console.
However, the app in itself does not function and I can't manage to work around it..
Two issues throw the ActionController::ParameterMissing error:
1) First, anytime I intend to press the back_button it raises ParameterMissing error (see at the end for exact error message).
2) When I get to the last_step of the form, it displays all the needed information, but will neither create nor save new products (also ParameterMissing).
Here is my code:
Routes
get 'products/new', to: 'products#new', as: 'new_product'
post 'products', to: 'products#create', as: 'create_new_product'
resources :categories, only: [:index, :show, :new, :edit, :destroy] do
resources :sub_categories, only: [:index, :show, :new, :edit, :destroy]
resources :products, only: [:index, :show, :destroy]
end
Products Controller
class ProductsController < ApplicationController
skip_after_action :verify_authorized, except: :index, unless: :skip_pundit?
skip_after_action :verify_policy_scoped, only: :index, unless: :skip_pundit?
before_action :set_category, only: [:index, :show]
def new
session[:product_params] ||= {}
authorize #product = Product.new(session[:product_params])
#product.current_step = session[:product_step]
#product.user = current_user
end
def create
session[:product_params].deep_merge!(params_product) if params_product
authorize #product = Product.new(session[:product_params])
#product.current_step = session[:product_step]
#product.user = current_user
if #product.valid?
if params[:back_button]
#product.previous_step
elsif #product.last_step?
if #product.all_valid?
#product.save!
flash[:notice] = 'Your product was created successfully'
redirect_to newest_products_path && return
end
else
#product.next_step
end
end
session[:product_step] = #product.current_step
if #product.new_record?
return render :new
else
session[:product_step] = session[:product_params] = nil
end
end
private
def set_category
authorize #category = Category.find(params[:category_id])
end
def params_product
params.require(:product).permit(:name, :price, :description, :category, :category_id,
:sub_category, :sub_category_id, :user, :user_id, :id)
end
end
Product Model
class Product < ApplicationRecord
attr_writer :current_step
belongs_to :user, optional: true
belongs_to :sub_category
belongs_to :category, inverse_of: :products
validates :category, presence: true
validates_presence_of :name, :category_id, if: lambda { |e| e.current_step == "card" }
validates_presence_of :sub_category_id, :description, :price, if: lambda { |e| e.current_step == "details" }
def current_step
#current_step || steps.first
end
def steps
%w[card details confirmation]
end
def next_step
self.current_step = steps[steps.index(current_step) + 1]
end
def previous_step
self.current_step = steps[steps.index(current_step) - 1]
end
def first_step?
current_step == steps.first
end
def last_step?
current_step == steps.last
end
def all_valid?
steps.all? do |step|
self.current_step = step
valid?
end
end
end
New Products View
<%= form_for #product, url: create_new_product_path do |f| %>
<%= render "#{#product.current_step}_step", :f => f %>
<div class="bottom-signup">
<%= f.submit "Continue" unless #product.last_step? %>
<%= f.submit "Submit Product" if #product.last_step? %>
<%= f.submit "Back", :name => "back_button" unless #product.first_step? %>
</div>
<% end %>
Here is the exact error that is thrown by ActionController:
ActionController::ParameterMissing in ProductsController#create
param is missing or the value is empty: product
#around ligne (96)
95 def params_product
96 params.require(:product).permit(:name, :price, :description, :category, :category_id,
97 :sub_category, :sub_category_id, :user, :user_id, :id)
98 end
And finally, here is what appears if I raise params.inspect:
params.inspect
=> "<ActionController::Parameters {\"utf8\"=>\"✓\", \"authenticity_token\"=>\"AHfNwkeFOWBeEup+fCCvfZv1RowuP/YULHjo8kTnzer5YNCY7lMYAKzrrWJBVMcfOO+P1GmZGgi9PDpa/09rzw==\", \"commit\"=>\"Submit Product\", \"controller\"=>\"products\", \"action\"=>\"create\"} permitted: false>"
If someone understands where I'm wrong, I'd be more than glad to discuss it!
Thanks in advance.
Best,
Ist

Rails app reviews are not saving to database

I am building a book review application from on online tutorial. I am trying to save a book review with a form. I have a book table and a reviews table. If the book review saves, I've told the review form to redirect to the book show page. If not, render 'new' again. I get zero errors when I try to save. It just puts me back on the new review page. I went into the console, and the reviews are not being saved. I don't know what's going on. Can someone help?
Here is my books controller:
class BooksController < ApplicationController
before_action :authenticate_user!, only: [:new, :edit, :index, :show]
def index
#books = Book.all
end
def new
#book = current_user.books.new
end
def create
#book = current_user.books.build(book_params)
if #book.save
redirect_to books_path
else
render 'new'
end
end
def show
#book = Book.find(params[:id])
end
def edit
#book = Book.find(params[:id])
end
def update
#book = Book.find(params[:id])
if #book.update(book_params)
redirect_to book_path(#book)
else
render "edit"
end
end
def destroy
#book = Book.find(params[:id])
#book.destroy
if #book.destroy
redirect_to books_path
else
render 'show_books_path'
end
end
private
def book_params
params.require(:book).permit(:title, :description, :author, :category_id, :book_img)
end
end
Here is my reviews controller:
class ReviewsController < ApplicationController
before_action :find_book
def new
#review = Review.new
end
def create
#review = Review.new(review_params)
#review.book_id = #book.id
#review.user_id = current_user.id
if #review.save
redirect_to book_path(#book)
else
render 'new'
end
end
def edit
end
def update
end
def destroy
end
private
def review_params
params.require(:review).permit(:rating, :comment)
end
def find_book
#book = Book.find(params[:book_id])
end
end
Here is my review model:
class Review < ApplicationRecord
belongs_to :books
belongs_to :users
end
Here is my book model:
class Book < ApplicationRecord
belongs_to :user
has_many :reviews
has_attached_file :book_img, styles: { book_index: "250x350>", book_show: "400x600>" }, default_url: "/images/:style/missing.png"
validates_attachment_content_type :book_img, content_type: /\Aimage\/.*\z/
end
I'm using a devise form. Here is what I have:
<%= simple_form_for([#book, #book.reviews.build]) do |f| %>
<p>Rating</p>
<%= f.input :rating, label: false, :class => "input" %>
<p>Comment</p>
<%= f.text_area :comment, label: false, :class => "input" %>
<%= f.button :submit, :class => "submit" %>
<% end %>
Here is my routes file:
Rails.application.routes.draw do
devise_for :users
resources :books do
resources :reviews
end
root "books#index"
end
I'm really not sure what's going on here. When I go into the console, the reviews are not being saved. Eventually, I want to display them, but I haven't gotten to that step. Any help would be very appreciated!
I see that in your Review model you have this:
class Review < ApplicationRecord
belongs_to :books
belongs_to :users
end
When it should be like this:
class Review < ApplicationRecord
belongs_to :book
belongs_to :user
end
belongs_to associations have to use the singular term

Rails-Simple Form and Devise current_user issue when using model associations

I am using Devise as my authentication system and simple form. I get a NoMethodError in Groups#show and an undefined method 'name' for nil:NilClass error. I use model associations to tie the groups and posts together. When I do puts post.user.name it correctly displays in my terminal but that line causes the above error and it's referencing Groups#show for some reason. Any thoughts?
Routes
resources :groups do
resources :posts
end
Group Model
class Group < ActiveRecord::Base
validates :user_id, presence: true
belongs_to :user
has_many :posts
has_many :comments
has_many :attachments
end
Post Model
class Post < ActiveRecord::Base
validates :user_id, presence: true
validates :caption, presence: true
belongs_to :user
belongs_to :group
has_many :comments, dependent: :destroy
end
Group Controller
class GroupsController < ApplicationController
before_action :authenticate_user!
def new
#group = current_user.groups.build
end
def create
#group = current_user.groups.build(group_params)
#group.user_id = current_user.id
if #group.save
redirect_to groups_path
else
render :new
end
end
...
private
def group_params
params.require(:group).permit(:group_name, :description, :user_id)
end
end
Posts Controller
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
before_action :owned_post, only: [:edit, :update, :destroy]
before_action :authenticate_user!
def index
#posts = Post.paginate(page: params[:page], per_page: 3).order('created_at DESC')
#post = current_user.posts.build
#attachments = Attachment.all
end
...
def new
#post = current_user.posts.build
end
def create
#post = current_user.posts.build(post_params)
#group = Group.find(params[:group_id])
#post.group_id = #group.id
if #post.save
redirect_to groups_path
else
render :new
end
end
...
private
def post_params
params.require(:post).permit(:caption, :user_id)
end
def set_post
#post = Post.find(params[:id])
end
def owned_post
unless current_user == #post.user
redirect_to root_path
end
end
end
groups/show.html.erb
<%= render "posts/index" %>
...
posts/_index.html.erb
<%= render 'posts/form' %>
<%= render 'posts/posts' %>
...
posts/_form.html.erb
<%= simple_form_for([#group, #group.posts.build]) do |f| %>
...
posts/_posts.html.erb
<% #group.posts.each do |post| %>
<%= puts post.user.name %> ISSUE
<%#<%= render 'posts/post', post: post %>
<% end %>
SOLUTION: After asking on Reddit Rails, a generous user offered a solution that works. Apparently the <%= simple_form_for([#group, #group.posts.build]) do |f| %> creates a new post and adds it to the groups.posts array and so this causes issues when it iterates over _posts.html.erb and there is no user. More information can be found here: https://www.reddit.com/r/rails/comments/4lygix/unidentified_method_for_nil_class_devise_and/
But replace the above simple_form line of code with <%= simple_form_for([#group, Post.new(group: #group)]) do |f| %> seemed to do the trick, as suggested by the generous user in the reddit link above.

syntax error, unexpected '\n', expecting :: or '[' or '.'

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.

How to download the files as a zip using carrierwave multiple file uploads?

I am working on multiple file upload where I am able to upload multiple files. Now my requirement is to download the files of a particular post id as a zip.
post.rb:
class Post < ActiveRecord::Base
has_many :post_attachments
accepts_nested_attributes_for :post_attachments
end
post_attahment.rb:
class PostAttachment < ActiveRecord::Base
mount_uploader :avatar, AvatarUploader
belongs_to :post
end
avatar_uploader.rb:
class AvatarUploader < CarrierWave::Uploader::Base
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
and this is my posts controller:
class PostsController < ApplicationController
before_action :set_post, only: [:show]
# GET /posts
# GET /posts.json
def index
#posts = Post.all
end
# GET /posts/1
# GET /posts/1.json
def show
#post_attachments = #post.post_attachments.all
end
# GET /posts/new
def new
#post = Post.new
#post_attachment = #post.post_attachments.build
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
params[:post_attachments]['avatar'].each do |a|
#post_attachment = #post.post_attachments.create!(:avatar => a, :post_id => #post.id)
end
format.html { redirect_to #post, notice: 'Post was successfully created.' }
else
format.html { render action: 'new' }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:title, post_attachments_attributes: [:id, :post_id, :avatar])
end
end
posts/show.html.erb:
<p>
<strong>Title:</strong>
<%= #post.title %>
</p>
<% #post_attachments.each do |p| %>
<%= image_tag p.avatar_url %>
<%= link_to "Edit Attachment", edit_post_attachment_path(p) %>
<% end %>
For single file upload I used download method in the controller as:
def download
respond_to do |format|
format.html {
if params[:post_id].nil?
redirect_to :back
else
begin
post= Post.find(params[:post_id])
attachment_file = File.join('public', post.avatar.url)
if File.exists?(attachment_file)
send_file attachment_file, :disposition => 'attachment'
else
redirect_to :back
end
rescue Exception => error
redirect_to :back
end
end
}
end
end
in model mount_uploader :avatar, AvatarUploader and in index:
<%= link_to image_tag("download.png"), download_post_path(post.id) %>
What should be the condition for multiple file download as a zip?

Resources