I have a User Model(:name, :password, :email), and Event model(:name, :etc) and Interest model (:name)
Then I created two join tables -> UsersInterests and EventsInterests; each not containing a primary key and only comprised of the user_id/interest_id and event_id/interest_id respectively.
I'm trying to use ActiveRecord to query a list all the events where the interest.id of EventsInterests= interest.id of UsersInterests
I'm using has_many and belongs_to relationships with the Nested Loop Plugin
My models look like so =>
user.rb
has_many :users_interests
has_many :interests, :through => :users_interests
event.rb
has_many :events_interests
has_many :interests, :through => :events_interests
interest.rb
belongs_to :users , :through => :users_interests
belongs_to :events , :through => :events_interests
users_interests.rb
belongs_to :users
belongs_to :interests
events_interests.rb
belongs_to :interests
belongs_to :events
If the #user= User.find(1), How would I query the events a user would be interested in?
I came up with this =>
#events.find(:all, :conditions => EventsInterests.interest_id = UsersInterests.interest_id) ??
but I get the error
undefined method `interest_id' for UsersInterests(user_id: integer, interest_id: integer):Class
umm..wtf? any help guys....I've been at this for like 4 days
First, hop into the console and make sure all of your relationships work:
User.first.events
User.first.interests
Events.first.users
Interests.first.users
Interests.first.events
# ... and so
Just to clarify, a User lists his Interests, and you want to get a list of the Events matching those interests?
User.first.interests.collect { |interest| interest.events }.uniq
Not particular efficient, but effective and easy to comprehend.
You could use User.first.interests_singular_ids to get the ids and pass that to a find() with interest_id IN(...) that list, too. I'm not sure how much faster it would be, though.
Related
I have a model of users and things
Users can have one leader and many followers which are other users. User can also have things
So I have these definitions which use a self join relationship:
class User < ActiveRecord::Base
has_many :things, dependent: :destroy
has_many :followers, :class_name => 'User', :foreign_key => 'leader_id'
belongs_to :leader, :class_name => 'User', :foreign_key => 'leader_id'
end
class Thing < ActiveRecord::Base
belongs_to :user
end
So I can query ask for a list of things that a user has by asking, for example User.first.things. I can also get a list of followers of a user with User.first.followers.
How do I get a list of things that a user's followers have. I think I might need to use a has_many through relationship but I can't seem to figure it out as I'm not sure how to deal with the fact that a Leader can have things through a 'follower' but also directly themselves
Thanks
Something like this:
def all_things
Thing.where(:user_id => followers.map(&:id).push(id))
end
It returns a scope so you should be able to continue the chain, for example:
User.first.all_things.visible
Update
If you are only interested in the followers' things without adding the user's things to the batch it is better is you do it directly with a has_many through:
has_many :followers_things, :through => :followers, :source => :things
Check this other SO thread
How about:
all_things = (your_user.followers.each { |f| f.things }).flatten
This should return an array containing things that belong to all your_user's followers.
I have 3 models: User, List, Following
I'm trying to implement a system, where
A user can create many lists (list contains photos, but it's not relevant in this question)
A user can follow lists created by other users
Here's how I'm trying to build this system:
First we have a database table of lists:
lists: id, user_id
And specifying the models like the following:
class User < ActiveRecord::Base
has_many :lists
end
class List < ActiveRecord::Base
belongs_to :user
end
We can do User.first.lists without problem.
Now my challenge comes when trying to create the followership. I'd like a user to be able to find
All the lists he's following
All the lists being followed that are created by him
All the users following his lists (or, equivalently, all "followers")
Here's the database table I'm trying to use to fulfill the above function:
followings: user_id, list_id, list_user_id
In this table definition, user_id specifies who's following the list, list_id specifies the list being followed, and list_user_id specifies the owner of the list being followed. list_user_id is used here to speed up the database lookups, so that we don't have to join lists table with users table.
And now I'm stuck. I tried to change the user model to the following:
class User < ActiveRecord::Base
has_many :lists
has_many :followings
# Works
has_many :following_lists, :through => :followings, :class_name => "List", :source => :list
# Doesn't work
has_many :followed_lists, :through => :followings, :class_name => "List", :source => :list, :conditions => {:list_user_id => self.id}
# Doesn't work
has_many :followers, :through => :followings, :class_name => "User", :source => :user
end
The first goal, "Find all the lists he's following", is done, through has_many :following_lists, without problem. However, it seems it's difficult to get "all lists being followed" and "all followers" of a user.
The problem is that there seems to be no way to specify the key to use for lookup in the followings table. For example, when looking for user A's followers, I'll need to find all rows in followings table where the list_user_id equals A.id, but has_many method doesn't provide an option to do this, nor does the condition :conditions => {:list_user_id => self.id} work (it'll complain undefined method 'id').
So..how would you deal with this situation? Is there a better way to design the tables, or can we actually work out something based on the current table definitions?
Btw, here's how Following model is defined:
class Following < ActiveRecord::Base
attr_accessible :list_id, :list_user_id, :user_id
belongs_to :user
belongs_to :list
belongs_to :list_user, :class_name => "User"
end
You are trying to get these 2 things:
1.) All the lists being followed that are created by him
2.) All the users following his lists (or, equivalently, all "followers")
Both of these are filtering on top of lists owned by the user. Therefore the associations with :through => followings are incorrect. Since that scopes the lists to ones you follow, not ones you own.
One way to do want you want would be like this:
def followed_lists
# This essentially limits your owned lists to ones with an entry in the followings table
lists.join(:followings).all
end
def users_following_owned_lists
lists.followers.all
end
You will need to add the followers association to the List AR.
class List < ActiveRecord::Base
has_many :followings
has_many :followers, :through => :followings, :class_name => "User", :source => :user
end
Note also that list_user_id on followings table is not really needed.
can anyone help me count the number of great grandchild records in a Rails app?
For example, I want to do something like the following:
class Country
has_many :states
has_many :cities, :through => :states
has_many :events, :through => :cities
end
class State
belongs_to :country
has_many :cities
has_many :events, :through => :cities
end
class City
has_one :country, :through => state
belongs_to :state
has_many :events
end
class Event
belongs_to :city, :counter_cache => true
has_one :state, :through => city, :counter_cache => true
has_one :country, :through => :state, :counter_cache => true
end
So I want to have access to the number of events for each city, for each state, and for each country.
I have City and State working, but don't seem to be able to get a counter_cache running on the great grandparent Country model.
Have I missed something? Is this possible? Is there a better way to do it?
I'd really appreciate some ideas from the community. Thanks!
Have you watched the counter cache railscasts episode? It might be helpful.
http://railscasts.com/episodes/23-counter-cache-column.
If you simply want to count several levels down, you can chain several statements to get your answer. However, this isn't going to be terribly efficient, because of the multiple DB calls to accomplish this, hence it would be better to cache the count, if you're going to be running this count often.
Here's an example of getting the count of all events in a country (untested), something like:
country = Country.find(params[:id])
number_of_events_in_country = 0
country.states.each{|s| s.cities.each{|c| number_of_events_in_country += c.events.count}}
If it's a grandparent relationship you can just use has_many through (as you have listed above), but you have a great grandparent relationship and this doesn't work for that.
One thing you could do (if you have a multiple levels of parent child relationships) is put a method in your Country class to parse it out.
class Country
has_many :states
has_many :cities, :through => :states
attr_accessor :events
def initialize
#events = Array.new
end
def get_events
self.states.each{|s| s.each{|c| c.each{|e| #events << e }}}
end
end
Then just call the get_events method and events will be populated with all the events associated to the first record.
usa = Country.first
usa.get_events
usa.events
I've been trying to figure this out. Just clicked on Jeff's answer's RailsCasts link and found this 6 yr old comment.
Basically, you can do what you want using the counter_culture gem's multi-level caching features by passing it an array of the parents, walking back up to the top. Obviously, be sure to add the corresponding columns as normal.
class Event
belongs_to :city
has_one :state, :through => city
has_one :country, :through => :state
counter_culture [:city, :state, :country]
end
I'm developing a website on Ruby on Rails with the search engine Sphinx (I'm using Thinking Sphinx). I have a model in which I want to make the searches and I'm using another models (I made the relationships in the models and in the tables) but I want to make additional INNER JOINS, so, I have something like this:
class Group < ActiveRecord::Base
belongs_to :person
has_many :categories, :dependent => :destroy
define_index do
indexes group_name
indexes person.fullnameindexes categories.category_name
indexes categories.category_name
end
end
It's ok to make something like this?
class Group < ActiveRecord::Base
belongs_to :person
has_many :categories, :dependent => :destroy
define_index do
indexes group_name
indexes person.fullnameindexes categories.category_name
indexes categories.category_name
indexes subcategories.subcategory_name #additional table
end
end
As you can see, I'm adding a new model (Subcategory) that has no relationship with the model Group, but it has a relationship with the model Category, is this ok? or what is the right way to do that?
Those are the links I'm following:
http://freelancing-god.github.com/ts/en/indexing.html
http://freelancing-gods.com/posts/a_concise_guide_to_using_thinking_sphinx
If subcategory is referenced in the Category model, you can do this:
indexes categories.subcategories.subcategory_name, :as => :subcategory_names
Thinking Sphinx will happily go through associations into deeper associations if you want it to.
I think the short answer to this is "no". ThinkingSphinx will try to reference an association on Group named subcategories, which won't exist, and you should get an error when indexing.
If Category has_many :subcategories, you can express this in Group with a :through option:
class Group < ActiveRecord::Base
belongs_to :person
has_many :categories, :dependent => :destroy
has_many :subcategories, :through => :categories
and then the index should recognize the association, though the docs point out that you need an explicit alias when doing this, so:
indexes subcategories.subcategory_name, :as => 'subcategory_name'
This is the structure of my database in Ruby on Rails:
user have many notes
notes have many categories
categories have many notes
The relationship between notes and categories is has_many :through, I have a model named NoteCategory and a note_categories table.
The note model has a date field, which represents the date the note was created.
I get the notes for the user with this line:
current_user.notes
How can I provide a date and get back the categories for all the user's notes that were created on that date? Thanks for reading.
edit: Forgot to mention that I also need the categories to be ordered by the created_at field of the note they are attached to.
edit 2: here are the actual associations
user.rb
has_many :notes
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
Given you have
class User
has_many :notes
has_many :categories, :through => :notes
end
class Note
has_many :categories # <-- source reflection
end
then use this finder:
user.categories.all(:order => 'notes.created_at')
or
user.categories.find :all, :order => 'notes.created_at'