frostbite frostbite - 15 days ago 9
SQL Question

Relation passed to #or must be structurally compatible. Incompatible values: [:references]

I have two queries, I need an

or
between them, i.e. I want results that are returned by either the first or the second query.

First query is a simple
where()
which gets all available items.

@items = @items.where(available: true)


Second includes a
join()
and gives the current user's items.

@items = @items.joins(:orders).where(orders: { user_id: current_user.id})


I tried to combine these with Rails'
or()
method in various forms, including:

@items = @items.joins(:orders).where(orders: { user_id: current_user.id})
.or(@items.joins(:orders).where(available: true))


But I keep running into this error and I'm not sure how to fix it.

Relation passed to #or must be structurally compatible. Incompatible values: [:references]

Answer

There is a known issue about it on Github.

According to this comment you might want to override the structurally_incompatible_values_for_or to overcome the issue:

def structurally_incompatible_values_for_or(other)
  Relation::SINGLE_VALUE_METHODS.reject { |m| send("#{m}_value") == other.send("#{m}_value") } +
    (Relation::MULTI_VALUE_METHODS - [:eager_load, :references, :extending]).reject { |m| send("#{m}_values") == other.send("#{m}_values") } +
    (Relation::CLAUSE_METHODS - [:having, :where]).reject { |m| send("#{m}_clause") == other.send("#{m}_clause") }
end

Also there is always an option to use SQL:

@items.joins(:orders).where("orders.user_id = #{current_user.id} OR items.available = true")