Maybe is simple problem that I don't see, but is a bit tricky to me right now
What I need is know which projects a user had bet.
I want to do something like:
some_user.bets.projects
my models are:
class User < ActiveRecord::Base
has_many :bets
end
class Project < ActiveRecord::Base
has_many :bets
end
class Bet < ActiveRecord::Base
belongs_to :user
belongs_to :project
end
So, just to be clear, starting from a user instance, how can I know which projects a user had bet.
In sql will be something like
select projects.name from users
inner join bets
on bets.user_id = users.id
inner join projects
on bets.project_id = projects.id
where users.id = 1;
how to make it work?
Update your User and Project classes as follows:
class User < ActiveRecord::Base
has_many :bets
has_many :projects, :through => :bets
end
class Project < ActiveRecord::Base
has_many :bets
has_many :users, :through => :bets
end
Then you can do this:
user = User.first # Find a user
projects = user.projects # and return the projects that have bets
Related
I have three models
class Boat < ActiveRecord::Base
belongs_to :captain
has_many :boat_classifications
has_many :classifications, through: :boat_classifications
end
class Classification < ActiveRecord::Base
has_many :boat_classifications
has_many :boats, through: :boat_classifications
end
class BoatClassification < ActiveRecord::Base
belongs_to :boat
belongs_to :classification
end
I'm trying to write a simple ActiveRecord query to find all the boats of type sailboat. Something like Boat.where(classifications: "Sailboat")
I think this could work:
Boat.joins(:classifications).where(classifications: { name: 'Sailboat' }) # name or whatever field contains Sailboat
Generates this query:
SELECT `boats`.* FROM `boats` INNER JOIN `boat_classifications` ON `boat_classifications`.`boat_id` = `boats`.`id` INNER JOIN `classifications` ON `classifications`.`id` = `boat_classifications`.`classification_id` WHERE `classification`.`name` = 'Sailboat'
I think you want something like this:
Boat.includes(:classifications).where(classifications: {id: Classification.sailboats})
For this to work, you also need a scope on Classification like this:
def self.sailboats
where(name: "Sailboat")
end
I'm modeling a lessons table, the lesson belongs to a user, the teacher and creator of the lesson, and also, the lesson can have many students, which are also users.
So it would be something like this
class Lesson < ActiveRecord::Base
belongs_to :user
has_many :users
end
I'd like to call the first user teacher, and the collection of users students, I've read the documentation at http://guides.rubyonrails.org/association_basics.html but I can't quite find what I want.
This should have what you want: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-belongs_to
I think you want the class_name option:
class Lesson < ActiveRecord::Base
belongs_to :teacher, class_name: "User"
has_many :students, class_name: "User"
end
In your current code, all users could be the "owner" (teacher) of a lesson, instead you should have two additional classes "student" and "teacher" both having a 1:1 relation to the "user" class.
This would fit better:
class Teacher < ActiveRecord::Base
has_one :user
end
class Student < ActiveRecord::Base
has_one :user
end
class Lesson < ActiveRecord::Base
belongs_to :teacher
has_many :students
end
I'm on rails 3.0 and trying to figure out what would be the proper way to setup a belong_to :through relationship (which) I know is not possible. Here's an example:
class ParentCompany < ActiveRecord::Base
has_many :subsidiaries
has_many :employees, :through => :subsidiaries
end
class Subsidiary < ActiveRecord::Base
belongs_to :parent_company
has_many :employees
end
class Employee < ActiveRecord::Base
belongs_to :subsidiary
belongs_to :parent_company, :through :subsidiary # <-- I know this is invalid
end
I know I can solve it by doing:
class Employee < ActiveRecord::Base
def parent_company
subsidiary.parent_company
end
end
However, I'd like to know if I can do the above via associations.
You can use delegate to accomplish this without using an association
class Employee < ActiveRecord::Base
belongs_to :subsidiary
delegate :parent_company, to: :subsidiary
end
There are Things in Places which I'm looking to find. One Thing could be in many different Places, and many Things can be in one Place.
class Thing < ActiveRecord::Base
has_and_belongs_to_many :places
end
class Place < ActiveRecord::Base
has_and_belongs_to_many :things
end
I want to record the Finds of my Users so that I know where they found what.
class Find < ActiveRecord::Base
belongs_to :user
belongs_to :places_thing # Is this depluralization correct?
end
class User < ActiveRecord::Base
has_many :finds
# Now, how can I link in the Things the user has found? Like this?
has_many :found_things_in_places, :class_name => :places_things, :through => :finds
has_many :things, :through => :thought_things_in_places
end
Does this seem right? is it efficient? Thanks.
I think you were on the right track, the big change I'd make is that rather than having a join table (places_things) you should make it a proper model. I decided to call this an existence.
The data only exists in one place, so it's properly normalized. These relationships are clear and will be easy to manage. I think it's efficient.
class Place < ActiveRecord::Base
has_many :existences
has_many :things, :through => :existences
end
class Thing < ActiveRecord::Base
has_many :existences
has_many :places, :through => :existences
end
class Existence < ActiveRecord::Base
belongs_to :place
belongs_to :thing
end
class Find < ActiveRecord::Base
belongs_to :user
belongs_to :existence
end
class User < ActiveRecord::Base
has_many :finds
has_many :existences, :through => :finds
has_many :things, :through => :existences
end
You'll need rails 3.1 to do the nested has many through's like we did in User.
BTW the correct association declaration should be: belongs_to :places_things
I have these tables and relationships:
user has_many projects
project has_many tasks
task has_many actions
I would like to build a scope that allows me to select all of the current users actions, regardless of what project or task they belong to.
Thanks
I don't think scopes are necessary for this if you use the nested_has_many_through plugin.
class User < ActiveRecord::Base
has_many :projects
has_many :tasks, :through => :projects
has_many :actions, :through => :tasks
end
class Project < ActiveRecord::Base
has_many :tasks
has_many :actions, :through => :tasks
end
User.first.actions
I found something that works.
In the Actions model:
def self.owned_by (user)
joins("join tasks on actions.task_id = tasks.id").
joins("join projects on tasks.list_id = projects.id").
where("projects.user_id = ?" , user.id)
end
From the console:
u=User.find(1)
Action.owned_by(u).count
=> 521 # which is correct
I'm mot sure if its the best way to do it as I'm a bit new to sql. I get the feeling it could be made more concise.
EDIT Slightly better
Action.joins(:task => [{:project => :user }]).where(:projects => {:user_id => user.id })