I am trying to make my image_maps get destroyed when either a product or image is deleted. Here is the code.
class ImageMap < ActiveRecord::Base
belongs_to :imageable, :polymorphic => true
belongs_to :image
end
class Product < ActiveRecord::Base
has_many :image_maps, :as => :imageable
has_many :images, :through => :image_maps
end
class Image < ActiveRecord::Base
has_many :image_maps, :as => :imageable, :dependent => :destroy
end
Right now the image_maps do not get destroyed when you delete an image and i still need to figure out how to get it to work for products too.
I think that your dependent should go to the ImageMap model.
If i remember correctly, this is what Rails checks on the associated models to see whether they need to be destroyed.
Related
I have a tags model that I'd like to be polymorphic, but I don't want five records for a tag of "video" for example, I want to create the tag once and be able to use it on a variety of models. I've ready some of the questions here about doing that, but I'm not quite getting how to make it work.
So I've got:
class Tag < ActiveRecord::Base
belongs_to :tagable, :polymorphic => true
end
and
class Post < ActiveRecord::Base
has_many :tags, :through => :tag_assignments
end
and
class TagAssignment < ActiveRecord::Base
has_many :tags, :as => :taggable
end
Seems to me that should work, but... reading all the questions here I know I need a :source => option in there somewhere to tie it all together, but I'm just not following exactly how to do it. Can anyone help?
You have to redo your models as follows:
class Tag < ActiveRecord::Base
has_many :tag_assignments
end
class TagAssignment < ActiveRecord::Base
belongs_to :tagable, :polymorphic => true
belongs_to :tag
end
class Post < ActiveRecord::Base
has_many :tag_assignments, :as => :tagable
has_many :tags, :through => :tag_assignments
end
Now given a post you can get its tags as follows:
post.tags
Note
You should consider using the acts-as-taggable-on gem for your use case.
I building a photo sharing web application using Rails 3.1. I just want to verify that I got the associations right.
Some context: A User has many Share. A Share has one User (i.e the "sharer"), one Photoand many Receiver. A Receiveris a arbitrary User.
The reason why I'm using a through association is simply because I want to store additional data for each receiver of the shared photo.
class Photo < ActiveRecord::Base
has_many :shares
end
class Receiver < ActiveRecord::Base
belongs_to :share
belongs_to :user
end
class Share < ActiveRecord::Base
belongs_to :photo
belongs_to :user
has_many :receivers
has_many :users, :through => :receivers
end
class User < ActiveRecord::Base
has_many :receivers
has_many :shares, :through => :receivers
end
Retreiving a User shared photos could then be performed using the shares class method?
User.first.shares
# => [<#Share:0x000>, ...]
Retreiving a User received shares could then be performed using the receivers class method?
User.first.receivers
# => [<#Receiver:0x000>, ...]
Did I get this right?
I did something similar a while ago, I didn't test this code, so play around with it and see if it actually is what you need, it may point you in the right direction though.
If yours work I don't see the point of changing it, this code is a bit more complex but you dont have a Receiver model, everything goes through the Share model.
class User < ActiveRecord::Base
has_many :shares_links, :class_name => "Share", :foreign_key => :sharing_id, :dependent => :destroy
has_many :receiver_links, :class_name => "Share", :foreign_key => :shared_to_id, :dependent => :destroy
has_many :shares, :through => :shares_links
has_many :receivers, :through => :receiver_links
end
class Share < ActiveRecord::Base
belongs_to :sharing, :validate => true, :class_name => "User", :foreign_key => :sharing_id
belongs_to :shared_to, :validate => true, :class_name => "User", :foreign_key => :shared_to_id
has_one :photo
end
class Photo < ActiveRecord::Base
belongs_to :photo
end
User.first.shares
User.first.receivers
User.first.receivers.first.photo
This is how my RoR app is setup
note.rb
belongs_to :user
has_many :note_categories
has_many :categories, :through => :note_categories
category.rb
has_many :note_categories
has_many :notes, :through => :note_categories
I want to make it so that when a user deletes a note, the corresponding entry in the note_categories table is deleted as well. Do I use :dependent => :destroy to do that?
Also, if I wanted to make it so that if a user deletes a note, and that means that there are no more notes with the category it had, the category itself was deleted, how would I do that? Thanks for reading.
I want to make it so that when a user
deletes a note, the corresponding
entry in the note_categories table is
deleted as well. Do I use :dependent
=> :destroy to do that?
Yes, that's correct.
Also, if I wanted to make it so that
if a user deletes a note, and that
means that there are no more notes
with the category it had, the category
itself was deleted, how would I do
that?
You use an after_destroy callback.
class Note < ActiveRecord::Base
belongs_to :user
has_many :note_categories, :dependent => :destroy
has_many :categories, :through => :note_categories
end
class Category < ActiveRecord::Base
has_many :note_categories, :dependent => :destroy
has_many :notes, :through => :note_categories
end
class NoteCategory < ActiveRecord::Base
belongs_to :note
belongs_to :category
after_destroy { category.destroy if category.notes.empty? }
end
Please bear with me for a moment as I try to explain exactly what I would like to achieve.
In my Ruby on Rails application I have a model called Page.
It represents a web page.
I would like to enable the user to arbitrarily attach components to the page. Some examples of "components" would be Picture, PictureCollection, Video, VideoCollection, Background, Audio, Form, Comments.
Currently I have a direct relationship between Page and Picture like this:
class Page < ActiveRecord::Base
has_many :pictures, :as => :imageable, :dependent => :destroy
end
class Picture < ActiveRecord::Base
belongs_to :imageable, :polymorphic => true
end
This relationship enables the user to associate an arbitrary number of Pictures to the page. Now if I want to provide multiple collections i would need an additional model:
class PictureCollection < ActiveRecord::Base
belongs_to :collectionable, :polymorphic => true
has_many :pictures, :as => :imageable, :dependent => :destroy
end
And alter Page to reference the new model:
class Page < ActiveRecord::Base
has_many :picture_collections, :as => :collectionable, :dependent => :destroy
end
Now it would be possible for the user to add any number of image collections to the page.
However this is still very static in term of the :picture_collections reference in the Page model. If I add another "component", for example :video_collections, I would need to declare another reference in page for that component type.
So my question is this:
Do I need to add a new reference for each component type, or is there some other way? In Actionscript/Java I would declare an interface Component and make all components implement that interface, then I could just have a single attribute :components which contains all of the dynamically associated model objects.
This is Rails, and I'm sure there is a great way to achieve this, but its a tricky one to Google. Perhaps you good people have some wise suggestions. Thanks in advance for taking the time to read and answer this.
I believe you can use just
class Page < ActiveRecord::Base
has_many :components, :as => :attachable, :dependent => :destroy
end
class Picture < ActiveRecord::Base
belongs_to :attachable, :polymorphic => true
end
class PictureCollection < ActiveRecord::Base
belongs_to :attachable, :polymorphic => true
has_many :pictures, :as => :imageable, :dependent => :destroy
end
and so on...
I'm slightly confused about a polymorphic association I've got. I need an Article model to have a header image, and many images, but I want to have a single Image model. To make matters even more confusing, the Image model is polymorphic (to allow other resources to have many images).
I'm using this association in my Article model:
class Article < ActiveRecord::Base
has_one :header_image, :as => :imageable
has_many :images, :as => :imageable
end
Is this possible? Thanks.
I tried this, but then header_image returns one of the images. Simply because the images table doesn't specify a different image use type (header_image vs. normal image). It simply says: imageable_type = Image for both uses. So if there's no information stored about the use type, ActiveRecord cannot differentiate.
Yep. That's totally possible.
You might need to specify the class name for header_image, as it can't be inferred. Include :dependent => :destroy too, to ensure that the images are destroyed if the article is removed
class Article < ActiveRecord::Base
has_one :header_image, :as => :imageable, :class_name => 'Image', :dependent => :destroy
has_many :images, :as => :imageable, :dependent => :destroy
end
then on the other end...
class Image < ActiveRecord::Base
belongs_to :imageable, :polymorphic => true
end