/ / Rails gem Ransack -> search 'or condition' con 'is null' e un valore specifico (campo = x campo O IS NULL) - ruby-on-rails, arel, ransack

Rails gem Ransack -> search 'or condition' con 'is null' e un valore specifico (campo = x OR campo IS NULL) - ruby-on-rails, arel, ransack

Ho creato un sistema di supporto per i nostri sostenitori - programmato con ruby ​​on rails (Ruby 1.9.3 Rails 3.2)

C'è un modello di biglietto con a belongs_to associazione agli utenti (sostenitore).

Uso la gemma Ransack di Ernie per la ricerca. Quando il sostenitore cerca i propri biglietti (gestiti da tickets_controller.index), dovrebbe anche vedere i ticket non associati nel risultato della ricerca (visualizzazioni / biglietti / indice) (in combinazione con le altre condizioni di serach, ad esempio "data" o altro)

(In modo che possa prendere un biglietto aperto)

dichiarazione SQL prevista:

SELECT * FROM tickets WHERE ... AND (user_id=5 OR user_id IS NULL) AND ...

Provai user_id_null_or_user_id_eq nel modulo di ricerca della vista indice, ma ciò non funziona (nessun errore di metodo)

Come posso creare un predicato personalizzato (o un ransacker) per risolvere questo problema? (Grazie a @Magnuss per questo commento)

Sfortunatamente, non ho esperienza con Arel

Qualcosa di simile a:

ransacker :user_null_or_eq do
...
end

nel modello dei biglietti.

Spero che questo spieghi il problema in modo più dettagliato.

Grazie per qualsiasi aiuto.

risposte:

5 per risposta № 1

Ho anche dovuto capire questo e risposta @ TomGaiutato molto! Non hai davvero bisogno di creare un ransacker per questo problema, è necessario risolverlo usando il metodo build_grouping di ransack (che non è documentato da nessuna parte ...) e inserisci le condizioni di cui hai bisogno con "o" condition.

L'ho usato per cercare elementi da aggiungere a una gabbia ma volevo mostrare all'utente solo gli elementi che non sono già nella mia gabbia (e anche non assegnati ad alcuna altra gabbia), quindi nel mio controller:

   @search = Cage.ransack(params[:q])
@search.build_grouping({:m => "or", :storage_id_not_eq => @cage_item.id, :storage_id_null => true})
@results_count = @search.result(:distinct => true).length
@items = @search.result(:distinct => true).paginate(:per_page => 20, :page => params[:page] || 1)

@search.build_condition if @search.conditions.empty?
@search.build_sort if @search.sorts.empty?

Quindi quando stampo la query ransack è in esecuzione mostrerà:

 @search.result.to_sql
"SELECT `specimens`.* FROM `specimens`  WHERE (`specimens`.`deleted_at` IS NULL) AND ((`specimens`.`storage_id` != 183 OR `specimens`.`storage_id` IS NULL))"

e se aggiungo una query sul nome:

@search.result.to_sql
"SELECT `specimens`.* FROM `specimens`  WHERE (`specimens`.`deleted_at` IS NULL) AND ((`specimens`.`name` LIKE "%root%" AND (`specimens`.`storage_id` != 183 OR `specimens`.`storage_id` IS NULL)))"

Spero che questo aiuti te o qualcun altro che ha problemi nell'usare OR in condizioni di saccheggio invece che in AND.


1 per risposta № 2

Potresti creare i tuoi parametri di query come questo

q: {g: [ {m: "or", user_id_eq: 5, user_id_null: 1} ] }

dove questo:

user_id_null: 1

è solo un flag per cercare il valore null


0 per risposta № 3

OK - ecco la mia soluzione - ispirata al graywh (grazie mille): Ransack / temi / 290

È possibile aggiungere un nuovo nodo di raggruppamento -con un "o" -combinatore- all'oggetto di ransack.

Nella vista indice sono cambiato f.select :user_id_eq a select_tag ...

tickets_controller.index:

@q = Ticket.search(params[:q])
if params[:user_id_eq] && params[:user_id_eq]!=""
@q.build_grouping({:m => "or", :user_id_eq => params[:user_id_eq], :user_id_null => true})
end