ruby on rails - form_with - Filtrado de consultas ActiveRecord en rieles
select rails helper (5)
Estoy acostumbrado a Django, donde puedes ejecutar múltiples métodos de filtro en querysets, es decir, Item.all.filter(foo="bar").filter(something="else")
.
Sin embargo, esto no es tan fácil de hacer en Rails. Item.find(:all, :conditions => ["foo = :foo", { :foo = bar }])
devuelve una matriz, lo que significa que esto no funcionará:
Item.find(:all, :conditions => ["foo = :foo", { :foo = ''bar'' }]).find(:all, :conditions => ["something = :something", { :something = ''else'' }])
Así que pensé que la mejor manera de "apilar" filtros es modificar la matriz de condiciones y luego ejecutar la consulta.
Así que se me ocurrió esta función:
def combine(array1,array2)
conditions = []
conditions[0] = (array1[0]+" AND "+array2[0]).to_s
conditions[1] = {}
conditions[1].merge!(array1[1])
conditions[1].merge!(array2[1])
return conditions
end
Uso:
array1 = ["foo =: foo", {: foo = ''bar''}] array2 = ["algo =: algo", {: algo = ''else''}] condiciones = combine (array1, array2) items = Item. find (: all,: condiciones => condiciones)
Esto ha funcionado bastante bien. Sin embargo, quiero poder combinar un número arbitrario de matrices, o básicamente, taquigrafía para escribir:
conditions = combine(combine(array1,array2),array3)
¿Alguien puede ayudarme con esto? Gracias por adelantado.
Creo que lo que quieres es esto: Alcance designado
Lo que quieres son ámbitos seleccionados:
class Item < ActiveRecord::Base
named_scope :by_author, lambda {|author| {:conditions => {:author_id => author.id}}}
named_scope :since, lambda {|timestamp| {:conditions => {:created_at => (timestamp .. Time.now.utc)}}}
named_scope :archived, :conditions => "archived_at IS NOT NULL"
named_scope :active, :conditions => {:archived_at => nil}
end
En sus controladores, use esto:
class ItemsController < ApplicationController
def index
@items = Item.by_author(current_user).since(2.weeks.ago)
@items = params[:archived] == "1" ? @items.archived : @items.active
end
end
El objeto devuelto es un proxy y la consulta SQL no se ejecutará hasta que realmente empiece a hacer algo real con la colección, como iterar (para visualizar) o cuando llame métodos Enumerable en el proxy.
No lo haría como tú propones.
Como find devuelve una matriz, puede usar métodos de matriz para filtrarla, por ejemplo:
Item.find(:all).select {|i| i.foo == bar }.select {|i| i.whatever > 23 }...
También puede lograr lo que desea con ámbitos con nombre.
Puedes (o al menos solía poder) filtrar como en Rails:
find(:all, :conditions => { :foo => ''foo'', :bar => ''bar'' })
donde: foo y: bar son nombres de campo en el registro activo. Parece que todo lo que necesitas hacer es pasar un hash de: field_name => value pairs.
Puedes echar un vistazo a Searchlogic .
ActiveRecord
el uso de las condiciones en los conjuntos de ActiveRecord
e incluso en las Arrays
.
Espero eso ayude.