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'
Related
I have two tables bookmarks and categories. These models have a HABTM relationship.
Everything works as it should but I only want to allow users who created a category to be able to edit them. I have this set up on the bookmarks okay but is there a way to do it using the relationship between bookmarks and categories or do I just set it up the same way as bookmarks? which is having a user_id in the categories table.
Assuming you have 2 join tables:
user.rb
has_many :categories, :through => :user_categories
category.rb
has_many :users, :through => :user_categories
has_many :bookmarks, :through => :bookmark_categories
def is_editable_by?(user)
user.category.include? self
end
bookmark.rb
has_many :categories, :through => :bookmark_categories
has_many :users, :through => :categories
your_view.html.erb
if category.is_editable_by? current_user
<%= link_to "edit", edit_category_path, category %>
end
If the intention is
a) only the user who created the bookmark can edit them
Then we need to have a separate column user_id in bookmark model to store the creator of the bookmark and allow access similar to category.
b) the user who created the category can edit any bookmarks under that category, then we can just use the associated to get the users with permissions.
bookmark.rb
Class BookMark < ActiveRecord::Base
has_many :categories, :through => :bookmark_categories
has_many :users, :through => :categories
end
and we can just say bookmark.users.include?(current_user) then allow edit only if this condition satisfies.
I have the #user variable, and i have resources table, and then I have a favorites table which is merely user_id and resource_id
#user.resources.each works obviously
#user.favorites.first.resource works fine, except i want all of the resources.
#user.favorites.resources does not work
resource.rb
belongs_to :category
belongs_to :user
has_many :favorites
has_many :resource_tags
has_many :tags, :through => :resource_tags
user.rb
has_many :resources
has_many :favorites
favorite.rb
belongs_to :resource
belongs_to :user
Try:
#user.favorites.includes(:resource).collect(&:resource)
That should eager load the resource from all the User's favorites and then the collect should return them as an Array.
Hi I am really new to rails and I am trying to create a products ratings model.
So there's users (name, email, pw)
Users has a list of products that the user has rated. With a rating (1-10) and a comment.
Each product has its description, a list of the users who rated them, the rating and the comment.
How should I create the relationship? Should I have 3 models, user, rating, product, or can I get by with just user and product?
Also what would be the :has_many .etc relationship look like?
Here's what I would do
class User
has_many :ratings
has_many :products, :through => :ratings
end
class Product
has_many :ratings
has_many :users, :through => :ratings
end
class Rating
belongs_to :user
belongs_to :product
end
This way if you wanted to get all the users that have rated a product, you can say product.users.
This would a great case for a has_many :through =>
User Model.
User has_many :ratings
User has_many :products, :though => :ratings
Rating Model.
belongs_to :user
belongs_to :product
Product Model.
Product has_many :ratings
Product has_many :users, :through => ratings
n.b. this is now considered superior to has_and_belongs_to_many which many folks consider to be basically deprecated at this point.
Personally I've never liked using has_many_and_belongs_to, both as it works and also because of the frequent re-work to turn it into has_many, :through as soon as an additional attribute is desired on the join model (ratings in this case).
Actually you want a rating 'level' so you already have a case for the has_many, :through !
I have got a Database like this:
users
-id
user_cars
-user_id
-car_id
cars
-id
-model
-color
So a user can have multiple cars, and detailed information about the cars are in a big cars table. I also created the models with the relationships.
class User
has_many :user_cars
class User_car
belongs_to :user
belongs_to :cars
class Car
has_many :user_cars
Now I want to access the information for all the cars for one user. My first approach would be to get at least one information (i.e. color) from the cars table.
I tried this one, just as an example for accessing the middle table:
#user_id = current_user.user_cars.find(1).user_id
works! But when I try to access the cars table I always get an error.
#color = current_user.user_cars.cars.find(1).color
undefined method `cars' for #<ActiveRecord::Relation:0xaf92e8c>
So I think Im doin something easy very wrong...
When I know how to get access to the third table, I have to do it in that fashion, that I only get results for the user and not just only the first entry, maybe you guys can help me with that aswell. Thanks!
The issue in your example by the way is that belongs_to should be singular. Also, your order was wrong.
#color = current_user.user_cars.find_by_car_id(1).car.color
You should rewrite this to use a has_many through association:
class User
has_many :user_cars
has_many :cars, :through => :user_cars
class UserCar
belongs_to :user
belongs_to :car
You can then access the cars by doing:
current_user.cars
And the color by doing:
#color = current_user.cars.find_by_car_id(1).color
EDIT
After some debugging, it turns out that the Car model has a class property. Class is a reserved word in ruby. Be careful with naming your attributes!
Without has_many :through associations:
#color = current_user.user_cars.where(:car_id => 1).first.color
With them:
class User < ActiveRecord::Base
has_many :user_cars, :foreign_key => :user_id, :class_name => "UserCar", :inverse_of => :user
has_many :cars, :through => :user_cars
end
class UserCar < ActiveRecord::Base
belongs_to :user
belongs_to :car
end
class Car < ActiveRecord::Base
has_many :user_cars, :foreign_key => :car_id, :class_name => "UserCar", :inverse_of => :car
has_many :cars, :through => :user_cars
end
#color = current_user.cars.find(1).color
http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association
:through defines a shortcut
:inverse_of defines a method (association) which represents current model in :class_name model
:class_name defines which model should be represented by :user_cars
:foreign_key tells which column in the target model's table represents current model (in table user_cars (or users_cars, depends on how you define the association, i think it should be user_cars in this example.. and users_cars for has_and_belongs_to_many)
Details on those are in the link above.
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.