Rails 3 - select data from 3 tables - mysql

I have these 3 models:
class Car < ActiveRecord::Base
belongs_to :user
has_many :car_styles
has_many :styles, :through => :car_styles
end
class CarStyle < ActiveRecord::Base
belongs_to :car
belongs_to :style
end
class UserStyle < ActiveRecord::Base
belongs_to :style
belongs_to :user
end
class User < ActiveRecord::Base
has_many :cars
has_many :car_styles
has_many :styles, :through => :car_styles
end
I have logged-in a user (current_user). I am trying to select all cars, where car style_id are the same like user style_id -- how can I do that?
Thanks for help in advance
EDIT: schema:
cars
-id
-user_id
car_styles
-car_id
-style_id
user_styles
-user_id
-style_id
Every user has saved favorite styles - doesn't matter how much (but approximately ±5). Every photo has added a styles as well - and again doesn't matter how much.
And I would like to select all cars from table Cars, which have the same styles, as the current_user has added.

I think what you're saying here is you have three main models:
Car, User and Style
CarStyle and UserStyle are joins right?
If so, you should be able to say:
Car.joins(:styles => [:users]).where(:users => {:id => current_user.id })
If not, could you update the question with your schema?

Related

Rails where query for has_and_belongs_to_many

I have workshops table and categories table.
Workshop model:
has_many :workshop_categories, dependent: :destroy
has_many :categories, through: :workshop_categories
Category model:
has_many :workshop_categories, dependent: :destroy
has_many :workshops, through: :workshop_categories
And I have a WorkshopCategory model:
class WorkshopCategory < ActiveRecord::Base
belongs_to :workshop
belongs_to :category
end
I want to query active (active is a scope) workshops depending on categories. Tried this in workshop model:
def self.browse(params)
workshops = Workshop.active.order( "created_at DESC" )
workshops = workshops.joins(:categories).where(:categories => { :id => params[:category]}) if params[:category].present?
workshops
end
But I get this error:
ActiveRecord::StatementInvalid (PG::AmbiguousColumn: ERROR: column reference "id" is ambiguous
What is the proper way of this query? Everything that I can find on the internet is outdated.
This issue is because both categories and workshops has a column id
You need to do something like:
workshops.joins(:categories).where('category.id = ?', ...)
Notice how it now specifies which id you're referring to.

Rails 4 many-to-many querying both ways

I have a many-to-many relationship between two models - Teams and Tournaments.
When I query to get teams participation in a tournament by calling #tournament.teams i get the expected results.
When I'm trying it the other way around by calling #team.tournaments, to get a list of tournaments in which the team is participation I'm getting the following error:
Mysql2::Error: Unknown column 'tournaments.team_id' in 'where clause': SELECT `tournaments`.* FROM `tournaments` WHERE `tournaments`.`team_id` = 2
How can I make this work? I suppose it's a simple fix, but I'm just a beginner and can't seem to figure it out myself.
EDIT:
Team model:
class Team < ActiveRecord::Base
has_many :user_teams
has_many :users, :through => :user_teams
has_many :teams_in_tournaments
has_many :tournaments, :through => :teams_in_tournaments
has_many :tournaments
belongs_to :team_leader, class_name: "User"
has_many :matches
end
Tournament model:
class Tournament < ActiveRecord::Base
has_many :teams_in_tournaments
has_many :teams, :through => :teams_in_tournaments
belongs_to :organizer, class_name: "User"
has_one :rule, :dependent => :destroy
accepts_nested_attributes_for :rule
has_many :matches, :dependent => :destroy
belongs_to :winner, class_name: "Team"
end

Rails - having difficulty with group, user, owner, member associations

I've looked everywhere and have been unable to find exactly what I'm looking for. I have an idea of what I need, but am unable to put 2 and 2 together.
I need to allow users to create groups and allow other users to join the groups.
Any user can create a group.
Any user can send a request to join another group.
A user can CREATE only ONE group, but can BELONG to MANY groups.
The creator of the group is the owner of the group.
All of the members and the owner are regular users with no special permissions.
The group creator/owner can add/remove other group members.
This code isn't proper, but this is the idea:
class Group < ActiveRecord::Base
has_one :owner, :class_name => "user"
has_many :members, :class_name => "user"
end
class User < ActiveRecord::Base
belongs_to :groups
has_one :group, :class_name "user"
end
I believe I need a has_many :through association, but am unsure about how to implement it. How do I build my models/controllers/migrations in order to represent the association within the parameters above?
I would suggest as well using a join table as follows:
class Membership < ActiveRecord::Base
belongs_to :group
belongs_to :user
end
class Group < ActiveRecord::Base
belongs_to :owner, class_name: "User"
has_many :members, through: :memberships, source: :user
has_many :memberships
end
class User < ActiveRecord::Base
has_one :owned_group, foreign_key: "owner_id", class_name: "Group"
has_many :groups, through: :memberships
has_many :memberships
end
Migrations are as follows:
class CreateMemberships < ActiveRecord::Migration
def change
create_table :memberships do |t|
t.references :user
t.references :group
t.timestamps null: false
end
end
end
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.timestamps null: false
end
end
end
class CreateGroups < ActiveRecord::Migration
def change
create_table :groups do |t|
t.references :owner
t.timestamps null: false
end
end
end
Modern Rails applications use has_many through: instead of HABTM.
class User < ActiveRecord::Base
has_many :groups, through: :user_groups
end
class Group < ActiveRecord::Base
has_one :owner, through: :user_groups, source: :user
has_many :members, through: :user_groups, source: :user
end
class UserGroups < ActiveRecord::Base
validates :owner, uniqueness: true
belongs_to :member, class_name: 'User'
belongs_to :group
belongs_to :owner, class_name: 'User'
end
Adding source on has_many and has_one allows you to write Group.find(id).members and Group.find(id).owner. Validate the uniqueness of a group owner on the join.
http://guides.rubyonrails.org/association_basics.html#the-types-of-associations
The main types you could use in this case and depend on your requirements are
has_many :groups, through: join_table
where the join table would reference both the user and the group by having user_id and group_id. This allows you to have additional information related to the group membership, maybe you want a join date or a membership id or something like that.
has_and_belongs_to_many :groups
which is implemented in a similar fashion but bypassess the join model and would simply give you a list of groups/users on either side of the relationship
Polymorphic relationships wouldn't really come into play unless you were planning on having maybe different types of memberships, maybe groups, or organizations or something that would require similar, but separate database tables.

Rails Active Record, get related record from has_many :through relationship with where clause on through record

I have a relationship set up with a has_many :through.
class Physician < ActiveRecord::Base
has_many :appointments
has_many :patients, through: :appointments
end
class Appointment < ActiveRecord::Base
belongs_to :physician
belongs_to :patient
# physician_id, patient_id
end
class Patient < ActiveRecord::Base
has_many :appointments
has_many :physicians, through: :appointments
end
How can I get all patients for a given physician where the appointment's role is equal to PI or G2?
I've tried Physician.find(50).appointments.where('role = ? or role = ?', 'PI', 'G2').patients
Edit:
I'm getting undefined method from the above. Shouldn't I be able to get the through's related records? In Physician.find(50).appointments.where('role = ? or role = ?', 'PI', 'G2') there should be an appointments method but there is not.
Since you want Patient objects back, start with that model. You want to add WHERE clauses on both Appointments and Physicians, so join on those associations. Use the Hash form of where to reference the joined tables.
Patient.joins(:physician).
joins(:appointments).
where(appointments: {role: ["PI", "G2"]}).
where(physicians: {id: physician_id}).uniq
Update
Consider adding scopes to your models that you can reuse:
class Patient < ActiveRecord::Base
scope :for_physician, ->(physician_id) do
joins(:physicians).
where(physicians: {id: physician_id}
end
scope :for_roles, ->(roles) do
joins(:appointments).
merge(Appointment.for_roles(roles))
end
end
class Appointment < ActiveRecord::Base
scope :for_roles, ->(roles) do
where(role: roles)
end
end
Then you can put them together like this
Patient.for_physician(50).for_roles(["PI", "G2"]).uniq

Rails 4: Displaying tables related with user_id

I am trying to create a resume builder. Inside the resume, I would like to display the first corresponding Job title to a specific User in the show.html.erb.
I first made sure that Jobs has the user_id foreign key..
Schema
create_table "jobs", force: true do |t|
t.string "title"
t.string "company"
t.date "date_start"
t.date "date_end"
t.boolean "current"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "user_id"
t.integer "career_id"
end
..and the relationships are like so:
User Model
class User < ActiveRecord::Base
has_one :career
has_many :jobs, through: :career
end
Job Model
class Job < ActiveRecord::Base
belongs_to :user
has_many :descriptions
end
Controller
def show
#user = User.find(1)
end
What is the best way to go about this? I was able to display other elements such as Name and Contacts on the same Show View page. I have tried a ton of different lines but currently have this...
Show View
<%= #user.jobs.first.title %>
Your Job model has belongs_to :user, which would mean your jobs table needs a user_id attribute.
I don't know how your Career model looks like, but it seems you don't need
has_many :jobs, through: :career
if you're tying the job directly to the user via user_id (which should be added to your jobs table). In other words,
has_many :jobs
might just work. However, if you need to stick to Career, then make sure that
class Career < ActiveRecord::Base
belongs_to :user
has_many :jobs
end
And then, from your view do:
<%= #user.jobs.first.title %>
Join Table
What you're looking at is a has_many :through relationship:
As such, you'll be better with the following setup -
#app/models/user.rb
class User < ActiveRecord::Base
#fields id | etc | etc | etc | created_at | updated_at
has_many :careers
has_many :jobs, through: :careers
end
#app/models/career.rb
class Career < ActiveRecord::Base
#fields id | job_id | career_id | created_at | updated_at
belongs_to :job
belongs_to :career
end
#app/models/job.rb
class Job < ActiveRecord::Base
#fields id | title | created_at | updated_at
has_many :careers
has_many :users, through: :careers
end
This will give you the ability to call the following:
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def show
#user = User.find
end
end
#app/views/users/show.html.erb
<%= #user.jobs.first.title %>