ActiveRecorded associated model back reference - ruby-on-rails

It is easy to associate a model to another using has_many/belongs_to methods. Let's suppose the following models:
class Movie < ActiveRecord::Base
has_many :actors
end
So, I can find the actors from a given movie instance. But now, given an actor instance obtained through the actors association, I'd like to find the movie instance related in the association. Some method like 'associated_instance' or 'back_association' that would make the following statement return true:
movie_instance.actors[0].**associated_instance** == movie_instance
Is there any built in way to do that?
Thanks

Assuming you have your relationships correctly defined, I'm guessing your encountering the situation where you want to effectively traverse an association but then traverse backwards eg.
movie.actors.movie
With a HABTM relationship rails doesn't build the .movie method for you on the actors collection, but what you can do is extend the association to include such a method:
class Movie < ActiveRecord::Base
has_and_belongs_to_many :actors do
def movie
proxy_owner
end
end
end
There is an excellent guide on association extensions by Mike Gunderloy on the Rails Guides site: http://guides.rubyonrails.org/association_basics.html#association-extensions
Hope I've stabbed at this question in the right direction :)

Yes you can do what you want using
movie_instance.actors[0].movie
The question still remains why you would want to do this as you already have it

...given an actor instance obtained
through the actors association...
If you're using the actors association, you already have the movie object. What is the problem that you're trying to solve here?
My suspicion is that if we finally get to the bottom of what you're trying to accomplish, the answer is going to be "read the docs on 'has_and_belongs_to_many' and/or 'has_many :through'."
Edit:
I just now noticed your clarification below (although movies and plots could be considered many-to-many as well, since they get recycled endlessly).
Assuming that you really are trying to use a many-to-one relationship, is the root of your problem that you forgot the following?
class Plot < ActiveRecord::Base
belongs_to :movie
end

Related

Missing touch option in Rails has_many relation

I have 2 Rails models: Book and Category, where a book belongs_to a category, a category has_many books.
The category name is shown in each book's page, and pages are cached.
If I change a category name (say, from 'Sci Fi' to 'Science Fiction'), then all corresponding book pages will be stale, and books need to be "touched" in order to trigger HTML regeneration.
It would seem to make sense to be able to do:
class Category << ActiveRecord::Base
has_many :books, touch: true
end
But the option is unavailable, I guess because the touch mechanism would instantiate each object, which could result in a major performance hit for has_many relationships.
To avoid that, I am using raw SQL as follows:
class Category << ActiveRecord::Base
has_many :books
after_update -> {
ActiveRecord::Base.connection.execute "UPDATE books SET updated_at='#{current_time_string}' WHERE category_id=#{id})"
}
end
Which is pretty terrible.
Is there a better way?
You can't use touch on has_many association, it works only with belongs_to, that's a fact.
If I understand correctly what you want, the answers with touch:true in the Book model won't work, because the Book object will not be updated when You change the Category model and the view will not regenerating.
So I think your solution is the best for that. (You can use also books.update_all(updated_at: Time.now))
As of Rails 6, there is a touch_all method available on ActiveRecord::Relation that handles this sort of thing with one query. There is a pretty good blog article on it here.
It is only available on the belongs_to method which should be in your books model. So you can still use it.

new to rails : relationships not setup right?

Right now I have some functionality working but its really ugly and I know there's a better way to do it.
Here's what I have right now in my User model:
def attending
dayseventsusers=self.days_events_users
daysevents=Array.new
events=Array.new
dayseventsusers.each do |deu|
daysevents<<DaysEvent.find(deu['days_events_id'])
end
daysevents.each do |de|
events<<Event.find(de['event_id'])
end
return events
end
I'm trying to get a list of events for a certain group of dayseventsusers records but I have to move through several relationships to accomplish this. What I'd really like to do is something like self.days_events_users.days_event.event, but I don't know if it can be this simple assuming my relationships are setup correctly.
User model
has_many :days_events_users
DaysEventsUsers model
belongs_to :user
belongs_to :days_event
DaysEvent
has_many :days_events_users
belongs_to :event
The days_events_users object belong to a single days_event, which belongs to a single event. Any suggestions are welcome!
Without having tested this, does the following work:
dayseventusers.collect(&:daysevent).collect(&:event)

Scope of the rails find_by_id method

Suppose I have a rails app with two models Person and House. Each Person object has a House_id property.
I would like to define the following method inside of my Person model:
def locate_house
current_house_id = house.find_by_id(person)
end
But I am getting an undefined variable error for house, how can I ensure that this is within scope?
You are trying to rewrite something already built into rails. Use a belongs_to relationship:
class Person < ActiveRecord::Base
belongs_to :house
end
Then you can just do:
person.house
To get the associated house.
Your model--House--is a ruby constant that requires capitalization
def locate_house
current_house_id = House.find_by_id(person)
end
House is a constant and needs a capital letter like someone else said, look at Rails Guides regarding relationships between Active Record Models. There are many possible realtionships, has many is probably what you are looking for. Since, in reality, a person can have multiple houses.

How do you create a has_many association with multiple types?

I have the following:
a Link model
a LinkItem model, which I want to be of the following type
a comment
a tag
...
I am using this code:
Link model
class Link < ActiveRecord::Base
has_many :link_items
end
LinkItem model
class LinkItem < ActiveRecord::Base
belongs_to :link
end
class Comment < LinkItem
end
class Tag < LinkItem
end
Now I don't know how to tell Rails that my LinkItem model is supposed to be polymorphic. I've read the Rails Guide on asociations and other tutorials, but these just describe how to create a belongs_to association to multiple other models, not the other way around.
So my question would be:
How do I create a has_many association where the associated instances can be of different types? Or would it be better to create seperate models for comments, tags, etc. and just associate each of them individually with my Link model?
EDIT
Actually my code works.
I just tried using a 'type'-column (instead of 'link_item_type') in my database and rails automatically used it to save/determine the correct subclass of my LinkItems (thanks Wizard of Ogz for the hint)
However I still can't access the subclasses of LinkItem without referencing a LinkItem first. Is this some kind of lazyloading?
If you are looking for polymorphic association nicholaides has the right way .
If you are looking for has_meny polymorphic association , check out the answer to "Setting up a polymorphic has_many :through relationship".
This is called a polymorphic association. Here is some documentation.
I just dealt with what I think is the same issue.
My filename for my model was wrong. I initially created it with one name (ex. link_tag.rb), and then changed the name of the class (ex. from LinkTag to Tag) on the fly without changing the name of the file (ex. tag.rb).
When I renamed the file correctly, it worked as expected.
In summary, the name of the file needed to match the name of the class.
I know this post is a little old, but maybe that will help someone someday!
I user polymorphic associations a lot!
I would first watch this RailsCast and then the documentation suggested by nicholaides.
It perfectly explains how to create both sides of the association.

Rails 3 - A model with a one to one relationship to itself - do I need belongs_to

I have a model named Person. It has two properties - name and parent_person_id
A person will always have a parent person.
Should I be using belongs_to in the model? If so, what are the advantages of doing so.
class Person < ActiveRecord::Base
belongs_to :person
end
I've not tried this code out yet, it seems a bit wrong my normal mysql ways.
I'm looking for opinions here more than anything, I'm quite new to the rails and want to make sure I'm doing things properly, doing things 'the Rails way'.
I'd suggest using a gem like ancestry for a tree structure like that. It gives you your association plus lots of utility methods (finding parent, children, siblings, retrieving a subtree).
If you don't want that, then in your belongs_to association has to look like this:
belongs_to :person, :foreign_key => "parent_person_id"
since without that option, rails would look for a foreign key of person_id and, not finding that, light your CPU on fire throw an error message.
Yes, you would need that belongs_to since this is what will tell rails about this relationship.

Resources