I can't figure out how to make this query work. I'm looking to get all the user ids of addresses who have a user that is an admin.
Address
.near([#address.latitude, #address.longitude], 5)
.where(addressable_type: 'User')
.joins(:addressable)
.where('addressable.is_admin = ?', true)
.pluck(:id)
Address.rb
class Address < ApplicationRecord
belongs_to :addressable, polymorphic: true
User.rb
class User < ApplicationRecord
has_one :address, :as => :addressable, dependent: :destroy
You cannot directly join the addressable relation as the addressable entities could belong to different models. You could try something like this:
Address
.near([#address.latitude, #address.longitude], 5)
.where(addressable_type: 'User')
.joins("INNER JOIN users on users.id = addresses.addressable_id")
.merge(User.admin)
.pluck(:id)
.merge can be used to invoke scopes of joined tables. Here, User model would have a scope called admin which would return admin users.
Related
Apologies for the terrible title!
Background
Users can have many Organisations
Organisations can have many Users
UserOrganisations is the join model and stores data about a specific user in a specific organisation.
class Organisation < ApplicationRecord
has_many :user_organisations, dependent: :destroy
has_many :users, through: :user_organisations
end
class User < ApplicationRecord
has_many :user_organisations, dependent: :destroy
has_many :organisations, through: :user_organisations
end
class UserOrganisation < ApplicationRecord
belongs_to :user
belongs_to :organisation
end
Problem
I want to get all users that belong to a specific organisation, excluding users which have a specific attribute and including or eager loading the joining UserOrganisation record.
At the moment I'm calling
class User < ApplicationRecord
scope :super_users, -> { where(super_user: true) }
end
#organistion.users.excluding(User.super_users)
I want to be able to reference values from the specific UserOrganistion.where(user_id: user.id, organisation_id: #organistion.id)
Is there a way of doing it this way around or do I need to do #organisation.user_organisations.joins(:users).merge(User.not_super_users)
I think you want do something like this:
SELECT u.*
FROM users u
JOIN user_organisations uo ON u.id = uo.user_id
JOIN organisations o ON o.id = uo.organisation_id
WHERE o.id = some_organisation_id
AND u.super_admin = false
and the equivalent AR query can be:
Organisation.find_by(id: some_organisation_id).users.where(admin: false)
or
Organisation.find_by(id: some_organisation_id).users.where.not(admin: true)
I have 3 models Account, Plan and User (And I can not modify the relations model structure, but add scopes or methods)
Account
belongs_to :plan
Plan
belongs_to :user
User
has_may :plans
I want to know if EXISTS an account with a specific user_id
Account.exists?…….. //here is my problem
I would join the database tables by using joins which results in a INNER JOIN in SQL and than add a condition for the user_id in question:
Account.joins(plan: :user).where(users: { id: user_id }).exists?
Read about joins in the Rails Guides.
You can create indirect associations which link Account and User through the Plan model:
class Account < ApplicationRecord
belongs_to :plan
has_one :user, through: :plan
end
class Plan < ApplicationRecord
belongs_to :user
end
class User < ApplicationRecord
has_may :plans
has_many :accounts, through: :plans
end
This will let you query:
Account.joins(:user)
.where(users: { id: user_id })
.exists?
ActiveRecord will automatically handle joining through the plans table.
See the Rails guides:
The has_many :through Association
The has_one :through Association
Specifying Conditions on the Joined Tables
I have the following models:
class Conversation < ActiveRecord::Base
belongs_to :sender, foreign_key: :sender_id, polymorphic: true
belongs_to :receiver, foreign_key: :receiver_id, polymorphic: true
.
class Owner < ActiveRecord::Base
.
class Provider < ActiveRecord::Base
.
class Account < ActiveRecord::Base
has_one :provider, dependent: :destroy
has_many :owners, dependent: :destroy
So in a Conversation, sender can be an Owner or a Provider. With this in mind, I can make queries like:
Conversation.includes(sender: :account).limit 5
This works as intended. The problem is when I want to use a where clause in associated model Account. I want to filter conversations which associated account's country is 'US'. Something like this:
Conversation.includes(sender: :account).where('accounts.country' => 'US').limit 5
But this wont work, I get the error ActiveRecord::EagerLoadPolymorphicError: Cannot eagerly load the polymorphic association :sender
What is the correct way of doing this kind of query?
I've also tried to use joins, but I get the same error.
I've found myself a solution, in case anyone else is interested. I ended up using joins with a SQL query:
Conversation.joins("LEFT JOIN owners ON owners.id = conversations.sender_id AND conversations.sender_type = 'Owner'
LEFT JOIN providers ON providers.id = conversations.sender_id AND conversations.sender_type = 'Provider'
LEFT JOIN accounts ON accounts.id = owners.account_id OR accounts.id = providers.account_id").
where('accounts.country' => 'US').limit 5
I've got the an has_one association:
has_one association user -> customer models
will the user have the customer_id or customer will have the user_id attribute?
other question: into my _form i'd like to have a select/option with all the users that hasn't associated with a customer which is the best way to do that?
thanks a lot.
The _id field is always in the model with the belongs_to, and refers to the other table name.
class Customer < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_one :customer
end
In this case, the customers table will have a user_id field.
For the second question, missing values are found in SQL using outer joins.
The SQL you want would be
select
from users
left outer join customers on users.id = customers.user_id
where customers.id is null
In ActiveRecord, add a scope to your User class.
In Rails 3.x:
class User < ActiveRecord::Base
has_one :customer
scope :missing_customer,
includes(:customer).where("customers.id is null")
end
In Rails 2.3.x:
class User < ActiveRecord::Base
named_scope :missing_customer,
{ :joins => "left outer join customers on users.id = customers.user_id",
:conditions => "customers.id is null" }
end
I need to query joining tables without using the primary key(id).
class User < ActiveRecord::Base
has_one :participant
end
class Participant < ActiveRecord::Base
belongs_to :user
end
The User has 'id' and 'name'.
The Participant has 'user_id' which is User.id
I am trying to find the Participant.id by querying with User.name
What I have tried is,
participant_id = Participant.all :joins => :users, :conditions => {:name => "Susie"}
If you're just looking for a specific user's participant id, you could just go:
User.find_by_name("Susie").participant.id
Since your user has a has_one relation to Participant(which belongs to it -- so basically a one-to-one) you can just go call participant on user. ActiveRecord takes care of the join magicks for you
Try the following:
class User < ActiveRecord::Base
has_one :participant
end
class Participant < ActiveRecord::Base
belongs_to :user
scope :foo, lambda {|name|
joins(:users).
where("name = ?", name)
}
end
If you're taking user input you're going to want to probably fix joins so it uses sanitize_sql_array. See here also for some query goodness