class Article < ActiveRecord::Base
has_many :comments
belongs_to :category
end
Is there a class method for Article with which I can retrieve a list of associations? I know by looking at the model's code that Article is associated to Comment and Category. But is there a method to get these associations programmatically?
You want ActiveRecord::Reflection::ClassMethods#reflect_on_all_associations
So it would be:
Article.reflect_on_all_associations
And you can pass in an optional parameter to narrow the search down, so:
Article.reflect_on_all_associations(:has_many)
Article.reflect_on_all_associations(:belongs_to)
Keep in mind that if you want the list of all the names of the models you can do something like:
Article.reflect_on_all_associations(:belongs_to).map(&:name)
This will return a list of all the model names that belong to Article.
Related
If I have a class Category and a class Post, post belongs to a category then I make a t.belongs_to in Post migration, but do I have to necessarily declare a t.has_many in Category? If not, if I have to use just one, which is the best to choose?
Both belongs_to and has_many will just create an association method.
For example, use this:
class User
has_many :cars
end
if you want to be able to access cars from current user. Such as: current_user.cars.
Or use this:
class Car
belongs_to :user
end
if you want to be able to access user from the instance of car. For example: Car.lost_and_found.user.
In most cases, you will usually need both ways, so then use both.
No you don't need to. t.has_many is not available on migrations and also more importantly, doesn't do anything for the table. However, belongs_to actually translates to a foreign key in the table linking the relationship.
For all methods that exist for a create_table e.g. creating references which also an alias for belongs_to refer to this documentation:
http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/create_table#227-All-methods
I have two models, Student and Absence, with the relationship:
class Student < ActiveRecord::Base
has_many :absences
class Absence < ActiveRecord::Base
belongs_to :student
I want to see how many absences have been logged for each student, and show that total on the student's #show page. In the console, I'm able to query this by calling:
a = Student.find(1)
a.absences.size
However, I can't seem to get it to work in the app itself. Would the preferred way of querying this in the app be in the model or the controller?
This will never work, since you are calling association on the model, not instance. At first you should fetch a student and then count associated records:
Student.find(<id here>).absences.size
To aggregate this information for all students, you can add absence_count attribute accessor in Student model:
attr_accessor :absence_count
and then do something like this:
Student.includes(:absences).each{|s| s.absence_count = s.absences.size}
If you just need to output it in the view, then you can try the following:
Student.includes(:absences).each do |student|
puts student.absences.size
end
For example I have
class Order < ActiveRecord::Base
has_many :shippings
has_one :contact_information
belongs_to :shop
end
How to get an array of associated objects from Order. For example
Order.associations
# [:shipping, :contact_information, :shop]
Order.reflect_on_all_associations.map(&:class_name)
You can pass a type of relation as a parameter:
Order.reflect_on_all_associations(:has_one)
Read about ActiveRecord::Reflection::ClassMethods
EDIT
Just realised, you've asked about object's associated models.
So, having what I've already shown, you can simply do something along the following lines:
associated_models = Order.reflect_on_all_associations.map(&:class_name)
I was interested in creating a model that could stand alone but could also belong to another model. So for example: I have an Artist that has many Albums. In addition to having many tracks (which is irrelevant for this case) it also can have many Singles. Here's the catch. There are some instances where a single doesn't belong to an album and is just used for promo (aka a promo single). So I thought I'd approach it using a polymorphic association:
class Artist < ActiveRecord::Base
has_many :albums
has_many :singles, as: :singleable
end
class Album < ActiveRecord::Base
belongs_to :artist
has_many :singles, as: :singleable
end
class Single < ActiveRecord::Base
belongs_to :singleable, polymorphic: true
end
Not being entirely familiar with polymorphic associations I didn't know if this would be the correct way to setup what I had in mind of doing. Alternatively should I have created an entirely separate model called PromoSingle or create a dropdown that would define the single type?
I don't think this case actually needs a polymorphic association. It should work, yes, but you'll soon find yourself in situations when you need to perform complicated searches to get seemingly simple results.
Polymorphic association should be used when association is semantically the same, but may involve different objects. It's not the case here, an artist is the one who created the track. But the album isn't.
This can cause trouble at least if you ever decide to fetch specific artist's tracks. Here's what ActiveRecord would have to do with your structure (including internal operations):
Get list L1
Get an array A of album_ids, whose artist_id is X (a parameter)
Get all singles, whose singleable_type is "Album" and singleable_id is in the array of albums A, fetched before.
Get list L2
Get all singles, whose singleable_type is "Artist" and singleable_id is X.
Concatenate L1 and L2
Here is what I suggest you do.
class Artist < ActiveRecord::Base
has_many :albums
has_many :singles
end
class Album < ActiveRecord::Base
belongs_to :artist
has_many :singles
end
class Single < ActiveRecord::Base
belongs_to :artist
belongs_to :album
end
PromoSingles fit well here too. Just because association is defined doesn't mean it should be present: it only means "it might be present, there is a place where we can put it".
Should you absolutely need it to be present (not here, somewhere else), you'd use a validation to ensure.
Otherwise, you may have items that don't belong to anyone, or, technically, belong to nil (Ruby level) or NULL (DB level). It's not bad if it makes sense.
I am developing an application like the stackoverflow, which questions or articles have at less one tag. And one tags must have one or more articles.
So, I am doing this in migration in RoR. I am consider which relationship is suitable for both table. In article table, should use a "has_many", and in the tag table, should use "has_many".
But I am thinking is it necessary to add one more table in the middle, something like....
So, the first one is like that:
class Article < ActiveRecord::Base
has_many :tags
end
class Tag < ActiveRecord::Base
has_many :articles
end
or something like this:
class Article < ActiveRecord::Base
has_many :articleTagList
has_many :tags, :through => : articleTagLists
end
class Tag < ActiveRecord::Base
has_many :articleTagList
has_many :articles, :through => :articleTagLists
end
class ArticleTagList < ActiveRecord::Base
belongs_to :article
belongs_to :tag
end
Many-to-Many relationships in a normalized database will always need a third "look-up table."
If you denormalize you can get away with just having the tag id's in one field with a delimiter between them. But you also have to provide the logic to handle retrieval.
I'd personally just go with the normalized option.
If you don't want to store any information on the middle table (for example the name of the user who added tag X to the question Y), you can use the has_and_belongs_to_many:
http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_and_belongs_to_many
If you want to store something, you need to create the middle model, as your example. In your example, the ArticleTagList model should be called ArticlesTag and the database table should be articles_tags, by convention.