undefined method `image' for Album - ruby-on-rails

I am currently trying to display photos in an album.
This is the error that I receive (image below):
These are the current specs so far:
Album Model
class Album < ApplicationRecord
has_many :photos, dependent: :destroy
validates :title, presence: true
validates :description, presence: true
end
Photo Model
class Photo < ApplicationRecord
belongs_to :album
validates :name, presence: true
validates :image, attachment_presence: true
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
Photo Controller
class PhotosController < ApplicationController
def create
#album = Album.find(params[:album_id])
#photo = #album.photos.create(photo_params)
redirect_to album_path(#album)
end
def destroy
#album = Album.find(params[:album_id])
#photo = #album.photos(params[:id])
#photo.destroy
redirect_to album_path(#album)
end
private
def photo_params
params.require(:photo).permit(:name,:image)
end
end
View Folder - Photos/_photos.html.erb - where the error is generated from
<p>
<strong>Name:</strong>
<%= photo.name %>
</p>
<p>
<%= image_tag #album.image.url(:medium) %>
</p>
How do I fix this error?
Please let me know if more information is needed.
Thank you.

Instead of this line
<%= image_tag #album.image.url(:medium) %>
try this
<%= image_tag photo.image.url(:medium) %>

Related

How can I make my polymorphic model work?

I've got two models User and Image as polymorphic association because I want my image model to reuse in other models.
class User < ApplicationRecord
has_one :cart
has_many :images, as: :imageable, dependent: :destroy
accepts_nested_attributes_for :images
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
before_validation :set_name, on: :create
validates :name, presence: true
private
def set_name
self.name = "person#{rand(1000)}" if self.name.blank?
end
end
class Image < ApplicationRecord
mount_uploader :image, ImageUploader
belongs_to :imageable, polymorphic: true
end
And I made Image polymorphic: true and use carrierwave gem for creating uploader `mount_uploader mount_uploader :image, ImageUploader in Image model:image
class ImageUploader < CarrierWave::Uploader::Base
end
and I permit :image parameters to each model: User and Good,
module Admin
class UsersController < BaseController
before_action :set_admin_user, only: [:show, :edit, :update, :destroy]
def users_list
#admin_users = User.all.preload(:images).where(admin: true)
end
def show
end
def edit
end
def update
if #user.images.update(admin_user_params)
redirect_to admin_users_list_path, notice: 'User was successfully updated'
else
flash[:alert] = 'User was not updated'
end
end
def destroy
end
private
def set_admin_user
#user = User.find(params[:id])
end
def admin_user_params
params.require(:user).permit(:name, :email, images_attributes: [:image])
end
end
end
In my view form I've got the next code:
<%= form_for [:admin, #user], html: { multipart: true } do |f| %>
<%= f.label 'Name', class: 'form-group' %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.fields_for :images_attributes do |i| %>
<%= i.label :image %>
<%= i.file_field :image %>
<% end %>
<%= f.label 'Email', class: 'form-group' %>
<%= f.text_field :email, class: 'form-control' %>
<%= f.submit class: 'btn btn-oultline-primary' %>
<% end %>
but when I want to update user for exampletry to upload the image I've got the next:
Here is what I have as response
I can't saveupload my image. Why is that? I expect to have an insert into db but it doesn't happen and in db I've got no attached images.
Since you are adding multiple images, change your form to:
<%= i.file_field :image, multiple: true, name: "images_attributes[image][]" %>
And in the controller:
def edit
#image = #user.images.build
end
def update
if #user.images.update(admin_user_params)
create_user_images
redirect_to admin_users_list_path, notice: 'User was successfully updated'
else
flash[:alert] = 'User was not updated'
end
end
private
def admin_user_params
params.require(:user).permit(:name, :email, images_attributes: [:id, :user_id, :image])
end
def create_user_images
if params[:images_attributes]
params[:images_attributes]['image'].each do |i|
#image = #user.images.create!(:image => i)
end
end
end
Let me know if you still have problems after the edits :)

Polymorpic paperclip working strange with Rails 5

view:
<div class="kitchen_settings">
<%= form_for #kitchen, :html => { :multipart => true, "data-ajax" => false} do |f| %>
<%= f.text_field :title,placeholder: "#{current_user.fullname}'s Kitchen", autofocus: true %>
<%= f.text_field :bio, placeholder: 'something about your kitchen' %>
<%= f.fields_for :picture do |photo| %>
<%= photo.file_field :avatar %>
<% end %>
<%= f.submit %>
<% end %>
kitchen_controller.rb
class KitchensController < ApplicationController
before_action :authenticate_user!
def new
#kitchen = Kitchen.new
#kitchen.build_picture
end
def create
#kitchen = current_user.build_kitchen(kitchen_params)
respond_to do |format|
if #kitchen.save
format.html { redirect_to dashboard_path, notice: 'Kitchen was successfully created.' }
format.json { render :show, status: :created, location: dashboard_path }
else
format.html { render :new }
format.json { render json: #kitchen.errors, status: :unprocessable_entity }
end
end
end
def show
#kitchen = Kitchen.find (params[:id])
end
private
def kitchen_params
params.require(:kitchen).permit(:title,:bio, picture_attributes: [:avatar])
end
end
kitchen.rb
class Kitchen < ApplicationRecord
belongs_to :user
has_one :picture, as: :imageable, dependent: :destroy
accepts_nested_attributes_for :picture
end
picture.rb
class Picture < ApplicationRecord
belongs_to :imageable, polymorphic: true
has_attached_file :avatar, styles: { medium: "300x300>", thumb: "100x100"}, default_url: "/assets/:style/missing.png"
validates_attachment :avatar, :presence => true,
:content_type => { :content_type => ["image/jpeg", "image/gif", "image/png"] },
:size => { :in => 0..500.kilobytes }
end
And its giving me this error
I wanted polymorphic picture model. I decided to deal with polymorphic picture association but its just rollbacks always... Stuck. I've attached the image from the console. Thanks!!
Debugged it using binding.pry
In Rails 5, whenever we define a belongs_to association, it is required to have the associated record present by default after this change.To change this behavior i managed to do it this way:
picture.rb
class Picture < ApplicationRecord
belongs_to :imageable, polymorphic: true, optional: true
has_attached_file :avatar, styles: { medium: "300x300>", thumb: "100x100"}, default_url: "/assets/:style/missing.png"
validates_attachment :avatar, :presence => true,
:content_type => { :content_type => ["image/jpeg", "image/gif", "image/png"] },
:size => { :in => 0..500.kilobytes }
end
There is a problem with you validation of imageable in image.rb
When you store kitchen alongwith image in single go. Imageable validation is failed for image as kitchen is not created yet. That's why it's rollback.
To confirm it you can remove the validation temporarily.
You need to use inverse_of to make this work
in image.rb
belongs_to :imageable, polymorphic: true , inverse_of: :image
in kitchen.rb
has_one :picture, as: :imageable, dependent: :destroy,inverse_of: :imageable
I added inverse_of in both the associations. It tells rails that these associations are inverse to each other so if any of it's set then don't make a query to fetch the other.
In this way if you set any association then other will be set automatically and validation won't fail.
Here is a nice blog for inverse_of usage.

Nested models with simple_form and paperclip

[This maybe a simple issue, but I just can't find a solution]
I'm trying to update an existing record with new data and add some image(s) to that record (via paperclip), however, my code doesn't show the paperclip field at all.
I've followed this example and also tried with this solutions, but nothing works.
I have two, models Hotel and HotelImage.
hotel.rb
class Hotel < ActiveRecord::Base
extend FriendlyId
friendly_id :slug_candidates, use: :slugged
validates :name, presence: true
validates :location, presence: true
has_many :hotel_images
accepts_nested_attributes_for :hotel_images
def slug_candidates
[
[:name, :location],
]
end
end
hotel_image.rb
class HotelImage < ActiveRecord::Base
belongs_to :hotel
#rails generate paperclip hotel_image 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
edit.html.erb
<%= simple_form_for #hotel, :url => admin_hotel_path, method: :put, html: { multipart: true } do |f| %>
<%= f.error_notification %>
<%= f.input :name %>
<%= f.input :location %>
<%= f.simple_fields_for :hotel_images do |ff| %>
<%= ff.input :image, as: :file %>
<% end %>
<%= f.button :submit %>
<% end %>
hotels_controller.rb
#other code
def update
#hotel = Hotel.friendly.find(params[:slug])
if #hotel.update(hotel_params)
redirect_to admin_hotels_path, notice: 'Hotel was successfully updated.'
else
render :edit
end
end
private
def hotel_params
params.require(:hotel).permit(:name, :location, :admin_id, hotel_images_attributes: [:hotel_id, :image])
end
Here's the print screen of the form, where you can see that the paperclip field is missing:
However, when I change f.simple_fields_for :hotel_images to, for example, f.simple_fields_for :foobars, the paperclip field is shown:
Note: the name and location attributes update just fine.
def update
#hotel = Hotel.friendly.find(params[:slug])
if #hotel.update(hotel_params)
redirect_to admin_hotels_path, notice: 'Hotel was successfully updated.'
else
render :edit
end
end
def edit
#hotel_images = #hotel.hotel_images.present? ? #hotel.hotel_images : #hotel.hotel_images.build
end
Try this code

Rails nested form: update creates multiple records

I have menu model and photos model where the menu has has_many relationship with photo. For the image upload, I'm using paperclip. I was able to build a nested_form that creates photo and other attributes in photos table. However, when I update, the record gets duplicated in photos table and the new photo selected in the update form will not be uploaded. Appreciate your help.
menu model
class Menu < ActiveRecord::Base
has_many :photos, :dependent => :destroy
accepts_nested_attributes_for :photos, reject_if: :all_blank, allow_destroy: true
end
photo model
class Photo < ActiveRecord::Base
belongs_to :menu
has_attached_file :image,
:styles => { :thumb => "100x100#", :medium => "300x300#", :large => "600x400>" },
:url => "/assets/menus/photos/images/:id/:style/:basename.:extension",
:path => "#{Rails.root}/public/assets/menus/photos/images/:id/:style/:basename.:extension"
validates_attachment :image, content_type: { content_type: ["image/jpg", "image/jpeg", "image/png", "image/gif"] }
end
form.html.haml
= simple_form_for #menu do |f|
= f.simple_fields_for :photos do |photo|
= render 'photo_fields', f: photo
_photo_field.html.haml
.nested-fields
= f.file_field :image
= f.input :main_flag, as: :hidden, input_html: { value: "true" }
= f.input :user_id, as: :hidden, input_html: { value: "1"}
menus_controller.rb
class MenusController < ApplicationController
...
def update
#menu = Menu.find(params[:id])
if #menu.update(menu_params)
if params[:image]
#menu.photos.destroy
#menu.photos.build(menu_params)
end
flash[:success]= 'Menu was successfully updated'
redirect_to brand_menus_path(#menu.brand_id)
else
render 'index'
end
end
private
def menu_params
params.require(:menu).permit(:name, :price, :brand_id, :category_id, :description,
photos_attributes: [:user_id, :image, :main_flag])
end
This is very common problem with the strong_parameters when using with nested_params. Whitelisting the :id in the photos_attributes should fix your problem
def menu_params
params.require(:menu).permit(:name, :price, :brand_id, :category_id, :description,
photos_attributes: [ :id, :user_id, :image, :main_flag])
end

Paperclip will delete current image even though it's not changed on update

I'm using Paperclip to let my users upload images.
It works pretty well with separated single resources. I can add, edit, and delete all images without any extra effort using a RESTFUL structure.
But I have some difficulties while working with nested attributes.
I have 2 models called Article and Headline.
I'm using an Article form in my view to create an associated instance of Headline. So I'm using accepts_nested_attributes_for with ActiveRecord. I've set up everything related to this. I'm using fields_for in my form view. Strong parameters settings are all done. Everything works great with adding a NEW article with its headline. I also have a title field which updates appropriately.
<%= f.fields_for :headline do |r| %>
<%= r.label :title %>
<%= r.text_field :title %>
<%= r.label :image, "Headline image" %>
<%= r.file_field :image %>
<% end %>
But when I UPDATE an article without any change of the Headline's image, the Headline's image disappears.
As I know and experience, Paperclip doesn't update image files unless they are changed. That's the expected behavior. But in this case, it overwrites the nested model's attribute even though it shouldn't.
I think there must be a workaround for this?
Article.rb:
class Article < ActiveRecord::Base
after_commit :expire_caches
scope :desc, ->{ order(created_at: :desc)}
scope :with_images, -> {where.not(image_file_name: nil)}
before_validation :set_default_category
acts_as_taggable
attr_accessor :is_headline
has_attached_file :image, default_url: "default_:style.png",
:styles => { :large=>"700", :medium => "296", :thumb => "150", mini_thumb: "50x50>", :absolute_thumb=>"150x150#" },
:s3_host_name => 's3-eu-west-1.amazonaws.com',
:path => "articles_images/:id/:style/:basename.:extension"
#validates :title, presence: true
belongs_to :category
belongs_to :user
validates :title, :content, presence: true
validates :content, length: {minimum: 10}
validates :category_id, presence: true
validates :cihan_url, uniqueness: true, allow_nil: true
has_many :galleries, dependent: :destroy
has_one :headline, dependent: :destroy
has_one :ad, dependent: :destroy
has_many :videos
accepts_nested_attributes_for :headline
def self.main_page
where(main_page: true).with_images.desc
end
def to_param
"#{self.id}-#{self.title.parameterize}"
end
private
def set_default_category
self.category = Category.uncategorized if self.category.blank?
end
def expire_caches
Rails.cache.clear
end
end
Headline.rb:
class Headline < ActiveRecord::Base
after_commit :expire_caches
has_attached_file :image, default_url: "default_:style.png",
:styles => { :large=>"600", :medium => "300x300>", :thumb => "150x150>", :absolute_thumb=>"150x150#" },
:s3_host_name => 's3-eu-west-1.amazonaws.com',
:path => "headline_images/:id/:style/:basename.:extension"
belongs_to :article
private
def expire_caches
Rails.cache.clear
end
end
From articles_controller:
def set_article
#article = Article.find(params[:id])
end
def update
if #article.update(article_params)
redirect_to [:admin, #article], flash: {success: "<i class=\"icon-ok\"></i> Haber başarıyla düzenlendi.".html_safe}
else
render action: 'edit'
end
end
def article_params
params.require(:article).permit(:title, :content, :publish_date, :category_id, :active, :tag_list, :main_page, :extra_title, :image, :is_headline, headline_attributes: [:title, :counter, :order, :image])
end

Resources