module ActiveRecord class Base class << self # old style group find like PItem.find_group_by( :i_company => [45,45,45], :i_itemno => [1,2,3], :i_size => [0,0,0] ) # leads to a sql statement in the form of 'SELECT * FROM table WHERE ((i_company, i_itemno, i_size) IN ((45, 1, 0), (45, 2, 0), (45, 3, 0)))' def find_group_by(args) fail 'no hash given, use Table.all() instead' if args.nil? || args.empty? || (not args.is_a?(Hash)) fail 'args is not a hash of arrays' if args.select { |k,v| k.is_a?(Symbol) || v.is_a?(Array) }.size != args.size conditions = ( args.is_a?(Hash) && args[:conditions] ) || args tuple_size = conditions.size array_size = 0 conditions.each do |k,v| array_size = v.size unless array_size > 0 fail 'not all arrays are of the same size' unless v.size == array_size end symbols = conditions.keys values = Array.new(array_size) { Array.new(tuple_size) } # to recurse is golden, to transpose ... divine! i = 0 (array_size*tuple_size).times do values[i/tuple_size][i%tuple_size] = conditions.values[i%tuple_size][i/tuple_size] i += 1 end return where_tuple(symbols, values) end # not really compatible to the rest of ActiveRecord but it works # provide parameters like this: symbols_tuple = [ :col1, :col2, :col3 ] # and values_tuples = [ [1, 4, 7], [2, 5, 8], [3, 6, 9]] def where_tuple(symbols_tuple, values_tuples) if symbols_tuple.nil? || symbols_tuple.size == 0 || (not symbols_tuple.is_a?(Array)) || (not symbols_tuple.select { |s| not s.is_a?(Symbol) }.empty?) fail 'no symbols given or not every entry is a symbol' end tuple_size = symbols_tuple.size #fail "don't use this method if you're not looking for tuples." if tuple_size < 2 if values_tuples.nil? || values_tuples.size == 0 || (not values_tuples.is_a?(Array)) || (not values_tuples.select { |s| not s.is_a?(Array) }.empty?) fail 'no values given or not every value is an array' end tuple_part = "(#{(['?']*tuple_size).join(',')})" in_stmt = "(#{([tuple_part]*values_tuples.size).join(', ')})" stmt = "(#{symbols_tuple.map { |sym| sym.to_s }.join(', ')}) IN #{in_stmt}" res = where(stmt, *(values_tuples.flatten!)) return res end end # end of class << self end # end of class Base end