attr_bitwise icon indicating copy to clipboard operation
attr_bitwise copied to clipboard

Querying data

Open hovancik opened this issue 8 years ago • 3 comments

How would I go about

return all users who can see at least english and french content

user 1 => en, fr, ca user 2 => en, fr user 3 => en

I wanna query users with both en and fr, so I wanna get user 1 and user 2

also nice would be opposite: users that do not have them.

hovancik avatar Jun 22 '16 12:06 hovancik

Hi @hovancik,

I assume that you have a User model with a language bitwise attribute ;)

here is the "SQL-way" :

class User
  include AttrBitwise

  attr_bitwise :languages,
    column_name: 'languages_value',
    mapping: [:fr, :en, :ca]

  scope :with_any_languages, lambda { |*types_sym|
    where(languages_value: bitwise_union(*types_sym, 'languages'))
  }

  scope :with_all_languages, lambda { |*types_sym|
    where(languages_value: bitwise_intersection(*types_sym, 'languages'))
  }

end

then, you can do :

# return all users who can see at least english and french content
users = User.with_any_languages(:fr, :en)

and the "Ruby way" :

class User
  include AttrBitwise

  attr_bitwise :languages,
    column_name: 'languages_value',
    mapping: [:fr, :en, :es]

  def any_languages?(*type_syms)
    type_syms.any? do |type_sym|
      language?(type_sym)
    end
  end

  def all_languages?(*type_syms)
    type_syms.all? do |type_sym|
      language?(type_sym)
    end
  end

end

then you can do :

# return all users who can see at least english and french content
users = User.any_languages?(:fr, :en)

I don't have any examples for negation for now.

Cheers,

charlypoly avatar Jun 22 '16 13:06 charlypoly

@wittydeveloper hi, I was using example from Readme. I was trying some queries and I could't get to understand how it works. After your answer I think I understand, but not sure, as I am getting some weird stuff.

So here is what I am doing ruby 2.3.0p0, attr_bitwise (0.0.4), Rails 4.2.6

class Customer < ActiveRecord::Base
  include AttrBitwise
  attr_bitwise :trust_level, mapping: %i{
    view_prices make_order cash_on_delivery pay_by_invoice mixit_delivery
  }
  scope :with_any_trust_levels, lambda { |*trust_levels_sym|
    where(trust_level_value: bitwise_union(*trust_levels_sym, 'trust_level'))
  }
  scope :with_all_trust_levels, lambda { |*trust_levels_sym|
    where(trust_level_value: bitwise_intersection(*trust_levels_sym, 'trust_level'))
  }
end

I am picking all possible trust_levels

Customer.first.trust_level_value
 => 31

Some queries and whether they are OK in my understanding:

Legit:

Customer.with_all_trust_levels(:make_order, :view_prices, :cash_on_delivery, :pay_by_invoice, :mixit_delivery)
  Customer Load (0.5ms)  SELECT "customers".* FROM "customers" WHERE "customers"."trust_level_value" = 31
#<ActiveRecord::Relation [#<Customer id: 1,

Legit:

Customer.with_all_trust_levels(:make_order, :view_prices, :cash_on_delivery, :pay_by_invoice)
  Customer Load (0.5ms)  SELECT "customers".* FROM "customers" WHERE "customers"."trust_level_value" IN (15, 31)
#<ActiveRecord::Relation [#<Customer id: 1,

Not legit? :

Customer.with_all_trust_levels(:make_order, :view_prices, :cash_on_delivery)
  Customer Load (0.4ms)  SELECT "customers".* FROM "customers" WHERE "customers"."trust_level_value" IN (7, 15, 23)
 => #<ActiveRecord::Relation []>
Customer.with_all_trust_levels(:make_order, :view_prices)
  Customer Load (0.4ms)  SELECT "customers".* FROM "customers" WHERE "customers"."trust_level_value" IN (3, 7, 11, 19)
 => #<ActiveRecord::Relation []>
Customer.with_all_trust_levels(:make_order)
  Customer Load (0.4ms)  SELECT "customers".* FROM "customers" WHERE "customers"."trust_level_value" IN (3, 2, 6, 10, 18)
 => #<ActiveRecord::Relation []>

And here, only first 3

Customer.first.trust_level_value
 => 7

ok:

2.3.0 :074 >   Customer.with_all_trust_levels(:make_order, :view_prices, :cash_on_delivery, :pay_by_invoice, :mixit_delivery)
  Customer Load (0.5ms)  SELECT "customers".* FROM "customers" WHERE "customers"."trust_level_value" = 31
 => #<ActiveRecord::Relation []>
2.3.0 :075 > Customer.with_all_trust_levels(:make_order, :view_prices, :cash_on_delivery, :pay_by_invoice)
  Customer Load (0.4ms)  SELECT "customers".* FROM "customers" WHERE "customers"."trust_level_value" IN (15, 31)
 => #<ActiveRecord::Relation []>
2.3.0 :077 > Customer.with_all_trust_levels(:make_order, :view_prices, :cash_on_delivery)
  Customer Load (0.4ms)  SELECT "customers".* FROM "customers" WHERE "customers"."trust_level_value" IN (7, 15, 23)
 => #<ActiveRecord::Relation [#<Customer id: 1]>
2.3.0 :078 > Customer.with_all_trust_levels(:make_order, :view_prices)
  Customer Load (0.4ms)  SELECT "customers".* FROM "customers" WHERE "customers"."trust_level_value" IN (3, 7, 11, 19)
 => #<ActiveRecord::Relation [#<Customer id: 1]>

not ok?

2.3.0 :079 > Customer.with_all_trust_levels(:make_order)
  Customer Load (0.4ms)  SELECT "customers".* FROM "customers" WHERE "customers"."trust_level_value" IN (3, 2, 6, 10, 18)
 => #<ActiveRecord::Relation []>

do I understand that correctly?

hovancik avatar Jun 22 '16 13:06 hovancik

and here is example when I use any.

Customer.first.trust_level
  Customer Load (0.4ms)  SELECT  "customers".* FROM "customers"  ORDER BY "customers"."id" ASC LIMIT 1
 => [:view_prices, :make_order, :cash_on_delivery]
2.3.0 :081 > Customer.first.trust_level_value
  Customer Load (0.4ms)  SELECT  "customers".* FROM "customers"  ORDER BY "customers"."id" ASC LIMIT 1
 => 7
2.3.0 :082 > Customer.with_any_trust_levels(:make_order)
  Customer Load (0.4ms)  SELECT "customers".* FROM "customers" WHERE "customers"."trust_level_value" IN (3, 2, 6, 10, 18)
 => #<ActiveRecord::Relation []>
2.3.0 :083 > Customer.with_any_trust_levels(:make_order)
  Customer Load (0.4ms)  SELECT "customers".* FROM "customers" WHERE "customers"."trust_level_value" IN (3, 2, 6, 10, 18)
 => #<ActiveRecord::Relation []>
2.3.0 :084 > Customer.with_any_trust_levels(:make_order, :view_prices)
  Customer Load (0.4ms)  SELECT "customers".* FROM "customers" WHERE "customers"."trust_level_value" IN (3, 2, 6, 10, 18, 1, 5, 9, 17)
 => #<ActiveRecord::Relation []>
2.3.0 :085 > Customer.with_any_trust_levels(:make_order, :view_prices,:cash_on_delivery)
  Customer Load (0.4ms)  SELECT "customers".* FROM "customers" WHERE "customers"."trust_level_value" IN (3, 2, 6, 10, 18, 1, 5, 9, 17, 4, 12, 20)
 => #<ActiveRecord::Relation []>
2.3.0 :086 > Customer.with_any_trust_levels(:make_order, :view_prices,:cash_on_delivery,:pay_by_invoice)
  Customer Load (0.4ms)  SELECT "customers".* FROM "customers" WHERE "customers"."trust_level_value" IN (3, 2, 6, 10, 18, 1, 5, 9, 17, 4, 12, 20, 8, 24)
 => #<ActiveRecord::Relation []>
2.3.0 :087 > Customer.with_any_trust_levels(:make_order, :view_prices,:cash_on_delivery,:pay_by_invoice,:mixit_delivery)
  Customer Load (0.4ms)  SELECT "customers".* FROM "customers" WHERE "customers"."trust_level_value" IN (3, 2, 6, 10, 18, 1, 5, 9, 17, 4, 12, 20, 8, 24, 16)
 => #<ActiveRecord::Relation []>

hovancik avatar Jun 22 '16 14:06 hovancik