web-dev-qa-db-fra.com

La relation passée à #ou doit être structurellement compatible. Valeurs incompatibles: [: références]

J'ai deux requêtes, j'ai besoin d'un or entre elles, c'est-à-dire que je veux des résultats qui sont retournés par la première ou la deuxième requête.

La première requête est une simple where() qui obtient tous les éléments disponibles.

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

La seconde inclut une join() et donne les éléments de l'utilisateur actuel.

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

J'ai essayé de les combiner avec la méthode or() de Rails sous différentes formes, notamment:

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

Mais je continue à rencontrer cette erreur et je ne sais pas comment la corriger.

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

Il y a un problème connu à ce sujet sur Github .

Selon ce commentaire vous voudrez peut-être remplacer le structurally_incompatible_values_for_or pour surmonter le problème:

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

De plus, il y a toujours une option pour utiliser SQL:

@items
  .joins(:orders)
  .where(
    "orders.user_id = ? OR items.available = true",
    current_user.id
  )
19
Andrey Deineko

Vous pouvez écrire la requête de cette bonne façon pour éviter les erreurs

@items = @items.joins(:orders).where("items.available = ? OR orders.user_id = ?", true, current_user.id)

J'espère que cela pourra aider!

8
Rajdeep Singh