So I have these files
deal.rb
class Deal < ApplicationRecord
has_many :images, as: :imageable, dependent: :destroy
#there is more code after this
end
image.rb
class Image < ApplicationRecord
belongs_to :imageable, polymorphic: true
belongs_to :deal
has_attached_file :attachment, styles: { thumb: "100x100!", medium: "200x200!" }
validates_attachment_content_type :attachment, content_type: /\Aimage\/.*\z/
end
deals_controller.rb
module Admins
class DealsController < BaseController
before_action :find_deal, only: [:edit, :update, :destroy]
def index
#deals = Deal.includes(:images)
end
def new
#deal = Deal.new
end
def edit
end
def create
#deal = Deal.new(deal_params.merge(created_by: current_user.id))
if #deal.save
flash[:success] = t('.success')
redirect_to admins_deals_url
else
flash.now[:warning] = t('.failure')
render :new
end
end
def update
if #deal.update(deal_params)
flash[:success] = t('.success')
redirect_to admins_deals_url
else
flash.now[:warning] = #deal.errors[:base].to_sentence
render :edit
end
end
def destroy
if #deal.destroy
flash[:success] = t('.success')
redirect_to admins_deals_url
else
flash.now[:warning] = t('.failure')
render :index
end
end
private
def deal_params
params.require(:deal).permit(:title, :description, :price, :discounted_price, :quantity, :publish_date, images_attributes: [:id, :attachment, :_destroy])
end
def find_deal
#deal = Deal.find_by(id: params[:id])
unless #deal
flash[:warning] = t('deals.not_found')
redirect_to admins_deals_path
end
end
end
end
application_controller.rb
class ApplicationController < ActionController::Base
helper_method :current_user, :current_cart
def current_user
#current_user ||= User.find_by(id: current_user_id)
end
def current_user_id
cookies.signed[:user_id] || session[:user_id]
end
def current_cart
#current_cart ||= (current_user.addressed_cart || current_user.cart) if current_user
end
end
EDIT:
Although I don't think application_controller has anything to do with the error
I am creating a deal with nested image attributes. I am using paperclip to upload the images. But I am getting these errors. I don't have any idea what the errors even mean. Here is an image to show the errors.
Here is the pastebin link
errors on terminal on creating deal
This appears to be a validation error. Try this for your validation:
validates_attachment_content_type :attachment, :content_type => /image/
Or for other variations you can see Validate Attachment Content Type Paperclip
UPDATE after testing your code seems this was a validation error because Paperclip creates an image but doesn't know about the belongs_to association. You can make it optional because by default rails 5 requires the belongs_to id field.
class Image < ApplicationRecord
belongs_to :imageable, polymorphic: true
belongs_to :deal, optional: true
has_attached_file :attachment, styles: { thumb: "100x100!", medium: "200x200!" }
validates_attachment_content_type :attachment, content_type: /\Aimage\/.*\z/
end
Related
I recently created a profile page for the users of the app am developing but along the way i noticed that the URL for the story originally is a little different from the same story on the users page. e.g normal url is "http://localhost:3000/genres/action/stories/37" while it is "http://localhost:3000/genres/absurdist/stories/37", meanwhile the story originally belongs to "action genre" and not "absurdist". Meanwhile, the two urls directs to the normal story page.
genre.rb
class Genre < ApplicationRecord
belongs_to :user
has_many :stories, dependent: :destroy
is_impressionable
extend FriendlyId
friendly_id :name, use: :slugged
def should_generate_new_friendly_id?
name_changed?
end
end
story.rb
class Story < ApplicationRecord
belongs_to :genre
belongs_to :user
has_many :episodes, dependent: :destroy
is_impressionable
extend FriendlyId
friendly_id :title, use: :slugged
def should_generate_new_friendly_id?
title_changed?
end
has_attached_file :image, size: { less_than: 1.megabyte }, styles: { medium: "300x300#", wide: "200x400#" }
validates_attachment_content_type :image, content_type: /\Aimage\/.*\z/
scope :of_followed_users, -> (following_users) { where user_id: following_users }
end
profiles_controller
class ProfilesController < ApplicationController
before_action :find_user
before_action :find_genre
before_action :owned_profile, only: [:edit, :update]
before_action :authenticate_user!
def show
#stories = User.find_by(user_name: params[:user_name]).stories.order('created_at DESC')
impressionist(#user)
end
def edit
end
def update
if #user.update(profile_params)
flash[:success] = 'Your profile has been updated.'
redirect_to profile_path(#user.user_name)
else
#user.errors.full_messages
flash[:error] = #user.errors.full_messages
render :edit
end
end
private
def profile_params
params.require(:user).permit(:avatar, :bio)
end
def find_user
#user = User.find_by(user_name: params[:user_name])
end
def find_genre
#genre = Genre.friendly.find_by(params[:slug])
end
def owned_profile
#user = User.find_by(user_name: params[:user_name])
unless current_user == #user
flash[:alert] = "That profile does not belong to you"
redirect_to root_path
end
end
end
profiles show
<div class="container my-5">
<div class="card-columns clearfix">
<%= render #user.stories %>
</div>
</div>
My App allows a user to create an Event and people can RSVP to the event. The app worked well before adding the Friendly_id gem, it works well as far as creating a new Event, but the RSVPs do not work as when you click submit you get an error. Please look at my code and see if there is anything that I am missing. Thank you in advance.
Event Model
class Event < ApplicationRecord
extend FriendlyId
friendly_id :eventname, use: [:slugged, :finders]
belongs_to :user
def should_generate_new_friendly_id?
eventname_changed?
end
has_attached_file :image, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/placeholder.png"
validates_attachment_content_type :image, content_type: /\Aimage\/.*\z/
validates :eventname, presence: true
has_many :rsvps, dependent: :destroy
end'
Rsvp Model
class Rsvp < ApplicationRecord
extend FriendlyId
friendly_id :eventname, use: [:slugged, :finders]
belongs_to :event
end
Events Controller
class EventsController < ApplicationController
before_filter :authenticate_user!, except: [:show]
def index
#events = current_user.events.all
end
def show
#event = Event.friendly.find(params[:id])
end
def new
#event = current_user.events.build
end
def create
#event = current_user.events.build(event_params)
#event.user = current_user
respond_to do |format|
if #event.save
format.html { redirect_to #event, notice: "Successfully created" }
else
format.html { render "new" }
end
end
end
def edit
#event = Event.friendly.find(params[:id])
end
def update
#event = Event.friendly.find(params[:id])
if #event.update(event_params)
redirect_to #event
else
render 'edit'
end
end
def destroy
#event = Event.friendly.find(params[:id])
#event.destroy
redirect_to events_path
end
private
def event_params
params.require(:event).permit(:eventname, :date, :time, :venue, :description, :image)
end
end
Rsvp Controller
class RsvpsController < ApplicationController
def index
event = Event.friendly.find(params[:event_id])
#rsvps = event.rsvps
end
def new
event = Event.friendly.find(params[:event_id])
#rsvp = event.rsvps.friendly.build
respond_to do |format|
format.html
end
end
def create
event = Event.friendly.find(params[:event_id])
#rsvp = event.rsvps.build(rsvp_params)
respond_to do |format|
if #rsvp.save
format.html { redirect_to "/thanks" }
format.js
else
format.html { render :new }
format.js
end
end
end
def thanks
render params[:page]
end
private
def rsvp_params
params.require(:rsvp).permit(:status, :name, :message)
end
end
Routes
resources :events do
resources :rsvps
end
show event:
http://127.0.0.1:3000/events/birthday
create rsvp for event:
http://127.0.0.1:3000/events/3/rsvps/new
After submit error shows on:
http://127.0.0.1:3000/events/birthday/rsvps
Screenshot of Error I get
I managed to resolve this issue by updating the following:
class Rsvp < ApplicationRecord
belongs_to :event
end
changed this:
new_event_rsvp_path(event_id: #event.id)
to this:
new_event_rsvp_path(#event)
Creating new RSVP now shows in the Friendly_id way:
http://127.0.0.1:3000/events/birthday/rsvps/new
I am fairly new to Rails, and I am following an online tutorial that has you build a book review app. Everything seems to work except for when I submit a review. When I do, I get this error:
undefined method `book_id=' for nil:NilClass
Here is my reviews controller:
class ReviewsController < ApplicationController
before_action :find_book
def new
#review = Review.new
end
def create
#reivew = 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
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 :book
belongs_to :user
end
Here is my Book model:
class Book < ApplicationRecord
belongs_to :user
belongs_to :category
has_many :reviews
has_attached_file :book_img, styles: { book_index: "250x350>", book_show: "325x475>" }, default_url: "/images/:style/missing.png"
validates_attachment_content_type :book_img, content_type: /\Aimage\/.*\z/
end
I feel like I've been reading help forums for the past two hours. I'm stuck. Any help would be very appreciated!
There's a typo in review in your create action.
Change the following line
#reivew = Review.new(review_params)
to
#review = Review.new(review_params)
The reason for the error is that #review is nil and you can't call the method book_id on a nil object.
I have an Album model and a child Picture model, whereby a file upload is handled by carrierwave.
The app runs as intended, however fails when I try to write an integration test for the upload.
From the development log, working parameters for this appear as follows:
Parameters: ..., "images"=>[#<ActionDispatch::Http::UploadedFile:0x007f8a42be2c78>...
During the integration test, im getting parameters as follows:
Parameters: ..., "images"=>["#<ActionDispatch::Http::UploadedFile:0x00000004706fd0>"...
As you can see, in the test scenario, #<ActionDispatch::Http::UploadedFile is being passed through as a string (confirmed with byebug), which is causing the test to fail.
How do I get the test to pass this as the object?
Integration Test
require 'test_helper'
class AlbumsCreationTest < ActionDispatch::IntegrationTest
def setup
#user = users(:archer)
#file ||= File.open(File.expand_path(Rails.root + 'test/fixtures/cat1.jpg', __FILE__))
#testfile ||= uploaded_file_object(PicturesUploader, :image, #file)
end
test "should create new album with valid info" do
log_in_as(#user)
assert_difference 'Album.count', 1 do #This assertion fails
post user_albums_path(#user), album: { title: 'test',
description: 'test',
}, images: [#testfile]
end
assert_redirected_to #user
end
end
from test_helper.rb
# Upload File (Carrierwave) Ref: http://nicholshayes.co.uk/blog/?p=405
def uploaded_file_object(klass, attribute, file, content_type = 'image/jpeg')
filename = File.basename(file.path)
klass_label = klass.to_s.underscore
ActionDispatch::Http::UploadedFile.new(
tempfile: file,
filename: filename,
head: %Q{Content-Disposition: form-data; name="#{klass_label}[#{attribute}]"; filename="#{filename}"},
type: content_type
)
end
Models
class Album < ActiveRecord::Base
belongs_to :user
has_many :pictures, dependent: :destroy
accepts_nested_attributes_for :pictures, allow_destroy: true
validates_presence_of :pictures
end
class Picture < ActiveRecord::Base
belongs_to :album
mount_uploader :image, PicturesUploader
validates_integrity_of :image
validates_processing_of :image
validates :image, presence: true,
file_size: { less_than: 10.megabytes }
end
Controller
class AlbumsController < ApplicationController
before_action :valid_user, only: [:new, :create, :edit, :update, :destroy]
def create
#album = current_user.albums.build(album_params)
if params[:images]
params[:images].each { |file|
debugger #file.class is String in integration test
#album.pictures.build(image: file)
}
end
if #album.save
# end
flash[:success] = "Album Created!"
redirect_to current_user
else
flash[:alert] = "Something went wrong."
render :new
end
end
private
def album_params
params.require(:album).permit(:user_id, :title, :description, :price,
pictures_attributes: [:id, :image, :image_cache, :_destroy])
end
def valid_user
#user = User.friendly.find(params[:user_id])
redirect_to(root_url) unless #user == current_user
end
end
Solved:
It appears that the uploaded_file_object method doesn't work at the integration test level.
I went back to using fixture_file_upload and everything works as intended.
When a user edits something in my application, they're forced to re-upload their image via paperclip even if they aren't changing it. Failing to do so will cause an error, since I validate_presence_of :image. This is quite annoying.
How can I make it so Paperclip won't update its attributes if a user simply doesn't supply a new image on an edit?
The photo controller is fresh out of Rails' scaffold generator. The rest of the source code is provided below.
models/accommodation.rb
class Accommodation < ActiveRecord::Base
attr_accessible :photo
validates_presence_of :photo
has_one :photo
has_many :notifications
belongs_to :user
accepts_nested_attributes_for :photo, :allow_destroy => true
end
controllers/accommodation_controller.rb
class AccommodationsController < ApplicationController
def index
#accommodations = Accommodation.all
end
def show
#accommodation = Accommodation.find(params[:id])
rescue ActiveRecord::RecordNotFound
flash[:error] = "Accommodation not found."
redirect_to :home
end
def new
#accommodation = current_user.accommodations.build
#accommodation.build_photo
end
def create
#accommodation = current_user.accommodations.build(params[:accommodation])
if #accommodation.save
flash[:notice] = "Successfully created your accommodation."
redirect_to #accommodation
else
#accommodation.build_photo
render :new
end
end
def edit
#accommodation = Accommodation.find(params[:id])
#accommodation.build_photo
rescue ActiveRecord::RecordNotFound
flash[:error] = "Accommodation not found."
redirect_to :home
end
def update
#accommodation = Accommodation.find(params[:id])
if #accommodation.update_attributes(params[:accommodation])
flash[:notice] = "Successfully updated accommodation."
redirect_to #accommodation
else
#accommodation.build_photo
render :edit
end
end
def destroy
#accommodation = Accommodation.find(params[:id])
#accommodation.destroy
flash[:notice] = "Successfully destroyed accommodation."
redirect_to :inkeep
end
end
models/photo.rb
class Photo < ActiveRecord::Base
attr_accessible :image, :primary
belongs_to :accommodation
has_attached_file :image,
:styles => {
:thumb=> "100x100#",
:small => "150x150>" }
end
You shouldn't need #accommodation.build_photo anywhere else than in new action.