How can I specify a OR
condition on a joins
statement? Basically I don't want the joins
for where(:tenant_id => User.current_tenant
. If I try OR
condition I get the following error.
I get the following error.
Relation passed to #or must be structurally compatible. Incompatible values: [:joins] [catalog/explorer]
scope :public_service_templates, -> { joins(:miq_user_roles).where(miq_user_roles: { settings: nil}).or(where(:tenant_id => User.current_tenant)) }
CodePudding user response:
In rails 6, you can do the following:
scope :first_query, -> { joins(:miq_user_roles).where(miq_user_roles: { settings: nil }) }
scope :second_query, -> { where(:tenant_id => User.current_tenant)) }
scope :first_query_or_second_query, -> { first_query.or(self.second_query) }
Hope it helps
CodePudding user response:
The title says "IF" or "OR" so I am a bit unclear if you are looking for both templates where "miq_user_roles"."setttings" IS NULL OR "service_template"."tenant_id" = SOME_ID
or if you are looking for "miq_user_roles"."setttings" IS NULL
but if that is empty then return "service_template"."tenant_id" = SOME_ID
.
Assumptions
- You are looking for the former combined OR condition
- The reasoning is that
where(:tenant_id => User.current_tenant)
may not have a relationship withMiqUserRole
and thus thejoin
prohibits the return of the appropriate values.
If so just use left_joins
instead of joins
.
This will create an outer join and will make this part (miq_user_roles: { settings: nil}
) of the condition non impactful on this part where(:tenant_id => User.current_tenant)
); however you will still have to add the left_joins
to the second condition for structural compatibility.
e.g.
scope :public_service_templates,-> {
left_joins(:miq_user_roles)
.where(miq_user_roles: { settings: nil})
.or(left_joins(:miq_user_roles)
.where(:tenant_id => User.current_tenant))
}
Alternatively you could use Arel
for the condition which will allow the OR to be part of the single where clause (without needing to merge scopes) e.g.
scope :public_service_templates,-> {
left_joins(:miq_user_roles)
.where(
MiqUserRole.arel_table[:settings].eq(nil).or(
arel_table[:tenant_id].eq(User.current_tenant.id)
)
)
}
Additionally not sure what User.current_tenant
returns. Depending on implementation you need to pass an instance of User
to this call e.g.
scope :public_service_templates,->(user) {#...
then you would call as ServiceTemplate.public_service_templates(user)