Carrierwave - How to reference a model's image from a different model - ruby-on-rails

I have a User model and a Project model. The User model has a PhotoUploader as a carrierwave uploader, and the Project model has a LogoUploader as a carrierwave uploader.
I also have a Poster model that references a User or a Project. With this Poster I can make a post with an User or a Project, in the same way (showing a name, a description and a image).
The problem is that I want to reference a photo from an User or a logo from a Project, using a string attribute like "image", that is an Uploader object from carrierwave.
I don't want to duplicate images.
How can I do this? Is this the right way to do it?

Polymorphic Association is what you need. http://guides.rubyonrails.org/association_basics.html#polymorphic-associations
http://railscasts.com/episodes/154-polymorphic-association-revised
models/media.rb
class Media < ActiveRecord::Base
attr_accessible :content
belongs_to :mediable, polymorphic: true
end
models/user.rb
class User < ActiveRecord::Base
attr_accessible :content, :name
has_many :medias, as: :mediable
end
models/project.rb
class Project < ActiveRecord::Base
attr_accessible :content, :name
has_many :medias, as: :mediable
end
routes.rb
resources :users do
resources :medias
end
resources :projects do
resources :medias
end
when you save a media to user, you'll create a new media row:
id mediable_type mediable_id some_other_field
1 User 1 something here
then you can call current_user.medias

Related

How to acess has_many_through file urls of file uploaded using carrierwave in rails

How can I access the url of the file which is present in the related model and uploaded by using carrier wave.
I have three Models like:
class ThreeDModel < ApplicationRecord
has_many :three_d_model_animations
has_many :animations, through: :three_d_model_animations
end
2nd
class Animation < ApplicationRecord
has_many :three_d_model_animations
has_many :three_d_models, through: :three_d_model_animations
mount_uploader :video, AnimationVideoUploader
validates_presence_of :video
end
3rd
class ThreeDModelAnimation < ApplicationRecord
belongs_to :animation
belongs_to :three_d_model
validates_presence_of :animation_file
mount_uploader :animation_file, ThreeDModelAnimationUploader
end
so, now I want to access the url of the video which is present in the Animation model uploaded using carrier wave,along with the fields in the ThreeDModelAnimation and url of the aimation file.
Because if go with the joins and select query the url to the files will be lost. please tell me how to acheive it without loosing the file_url to the file.
Thanks in advance

Rails - Paperclip ROLLBACK due to associations

I have 3 models. The question, answer and photo. I am using paperclip to save images. Questions and answers can have multiple images.
However, I get ROLLBACK when saving images for answer model. I don't get ROLLBACK when saving images for question model. I think I have a problem with model associations.
#photo model
class Photo < ApplicationRecord
belongs_to :question
belongs_to :answer
has_attached_file :image :path => ":rails_root/public/img/:filename", validate_media_type: false
do_not_validate_attachment_file_type :image
end
#answer model
class Answer < ApplicationRecord
belongs_to :question
has_many :photos
end
#question model
class Question < ApplicationRecord
has_many :answers
has_many :photos
end
My Controller :
p.answers.each do |a|
new_answer = q.answers.create(body: a[:body])
if a[:images]
a[:images].each do |e|
new_answer.photos.create(image: URI.parse('www.abc.com/'+e))
end
end
end
Any thoughts?
Since rails 5 the belongs_to associations are by default required.
There are two possible solutions, either write
belongs_to :question, optional: true
in your Photo model, or, as you are saving them through the nested association (a bit like a nested-form), you have to clearly indicate which association is the inverse of which.
So in your answer class, specify the inverse of the :photos association
has_many :photos, inverse_of: :answer
(to allow rails to correctly check that the belongs_to is set correctly)

2 different Model share 1 unique Photo Model

Hello Rails Community !
I don't know how to structure my different models.
I have 2 differents models : cars and house
Theses models can have multiple photos.
My questions are :
Is it possible to use 1 photo model for the cars and house or I need to create 1 cars_photos model and 1 house_photos model
If it's possible, how can I generate my Photo model ?
=> Option 1
rails g model Photo name:string, description:text car:references house:references
Car.rb
has_many :photos
House.rb
has_many :photos
Photo.rb
belongs_to :car
belongs_to :house
The problem with this option is that a photo will have to be linked with a car AND with a house. Witch is not good.
=> I want a photo be linked with a car OR with a house
I don't know how to proceed...
Thx !
This is almost the exact prototypical polymorphic association from the Rails guides
$ rails g model Photo name:string description:text imageable:references{polymorphic}:index
Produces this migration file
class CreatePhotos < ActiveRecord::Migration[5.1]
def change
create_table :photos do |t|
t.string :name
t.text :description
t.references :imageable, polymorphic: true
t.timestamps
end
end
end
t.references :imageable, polymorphic: true is going to give you two columns on your photos table: imageable_id:integer which will be the id column of the associated object, and imageable_type:string which will be the stringified class name of the associated object. This allows photos to interface with and belong to any model on one association.
Then your models should look like this
class Photo < ApplicationRecord
belongs_to :imageable, polymorphic: true
end
class Car < ApplicationRecord
has_many :photos, as: :imageable
end
class House < ApplicationRecord
has_many :photos, as: :imageable
end
You can add a Photo to a Car with Car.find(params[:car_id]).photos.create and assign a Car to a Photo with Photo.new imageable: Car.find(params[:car_id])
Yes, you can reuse photos for both cars and house.
There are two major gems
for photo uploading: paperclip and carrierwave.
Have a look at them before you continue with your modeling!

Rails Association Terminology: Belongs_to and has_many

I have two questions about ActiveRecords:
1)
Let's say I have an application with several users, each one of which has a profile photo.
I would like users to be able to have the same profile photo as their friends: this leads to a 1-many relationship where one photo can be the profile photo of many users.
When I have to create the association in rails I have to write something like this:
class User < ActiveRecord::Base
belongs_to :photo
end
class Photo < ActiveRecord::Base
has_many :Users
end
Now this seems a bit weird to me since the photo belongs to multiple users in this case, rather than multiple users belonging to one photo.
I am doing this wrong or am I overthinking about the terminology of rails?
2)
New Case:
Let's say a user can have one profile photo. In this case the photo cannot be shared between users, as a consequence the relationship is of 1-to-1.
I also want to add a post entity which can contain a photo and this photo can be used by a user as a profile photo.
This is how the final implementation would look like:
class User < ActiveRecord::Base
has_one :photo
end
class Photo < ActiveRecord::Base
belongs_to :user
belongs_to :post
end
class Post < ActiveRecord::Base
has_one: Photo
end
By looking at the Rails Documentation it seems that the only way to create the one to one relationship as such is by putting the two foreign keys in the Photo table: one for Post and one for User.
However I would like to instead have one foreign key in the User table for Photo and one foreign key in the post table for Photo as well. In this case it seems that the implementation needs to be as such:
class User < ActiveRecord::Base
belongs_to :photo
end
class Photo < ActiveRecord::Base
has_one :user
has_one :post
end
class Post < ActiveRecord::Base
belongs_to: Photo
end
This also does not make much sense to me, semantically speaking. Again, am I going something wrong or am I overthinking this?
1)
#app/models/user.rb
class User < ActiveRecord::Base
has_one :photo
belongs_to :avatar, class_name: "Photo" #-> set this as the "avatar"
end
#app/models/photo.rb
class Photo < ActiveRecord::Base
belongs_to :user
end
The user can create a photo; he can define which avatar he uses:
#user = User.find x
#photo = #user.avatar
Whilst I still think it looks a little weird, I think it would work.
2)
polymorphic
#app/models/post.rb
class Post < ActiveRecord::Base
belongs_to :user
has_one :photo, as: :imageable
end
#app/models/user.rb
class User < ActiveRecord::Base
has_many :posts
has_one :photo, as: :imageable
belongs_to :avatar, class_name: "Photo"
end
#app/models/photo.rb
class Photo < ActiveRecord::Base
belongs_to :imageable, polymorphic: true #-> belongs to either post or user
end
In both cases, I would advocate using a foreign_key to define the avatar_id for the user.
This will mean a belongs_to association (not ideal), but will mean that you can upload as many images as you want, referencing one to be the avatar. You'll then be able to call the avatar method as required in your profile.
The best way to do this would be to use a join table / join model but that would be inefficient for what you're asking.

change type in polymorphic association in rails

I am new to rails and I'm using rails Polymorphic association and I ran into a problem
I have two models EmployeeTable and ProductTable. Both have some picture in Picture Model
class Picture < ActiveRecord::Base
belongs_to :imageable, polymorphic: true
end
class EmployeeTable < ActiveRecord::Base
has_many :pictures, as: :imageable
end
class ProductTable < ActiveRecord::Base
has_many :pictures, as: :imageable
end
there are two column in Picture imagable_id and imagable_type. When I create an entry in table it stores imagable_type as either "EmployeeTable" or "ProductTable". Can I change these name to any different Names like "employee" and "product".
Thanks in advance
To retreive the image_type without with table, you can add this method in your model. Changing the assosiated model name while saving will cause issues while querying
def neat_imageable_type
self.imageable_type.gsub("Table", "").downcase
end

Resources