travis-ci
significantly optimize #without_role Imagine a big production application with millions of users. The previous version generates 3 queries for `User.without_role(:admin)`: 1) For `user.all` in [`#all_except`](https://github.com/RolifyCommunity/rolify/blob/<a class=hub.com/RolifyCommunity/rolify/commit/<a class="double-link" href="https://git"><a class=hub.com/RolifyCommunity/rolify/commit/522c0d7d84a70dd3576b569edf19f9f6cb118a61">522c0d7d8/lib/rolify/adapters/active_record/role_adapter.rb#L83): ```sql SELECT "users".* FROM "users" ``` 2) For `self.with_role(role_name, resource)` in [`#without_role`](https://github.com/RolifyCommunity/rolify/blob/522c0d7d84a70dd3576b569edf19f9f6cb118a61/lib/rolify/finders.rb#L8): ```sql SELECT "users".* FROM "users" INNER JOIN "users_roles" ON "users_roles"."user_id" = "users"."id" INNER JOIN "roles" ON "roles"."id" = "users_roles"."role_id" WHERE (((roles.name = 'admin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL))) ``` 3) For `user.where(prime_key => (user.all - excluded_obj).map(&prime_key))` in [`#all_except`](https://github.com/RolifyCommunity/rolify/blob/522c0d7d84a70dd3576b569edf19f9f6cb118a61/lib/rolify/adapters/active_record/role_adapter.rb#L83): ```sql SELECT "users".* FROM "users" WHERE "users"."id" IN (1, 2, ..., N) ``` where `N` is a number of users without the `admin` role. While a number of values in the `IN` clause for the third query can be huge there is even a worse problem. First, `user.all - excluded_obj` creates an `Array` of users and thenĀ `(user.all - excluded_obj).map(&prime_key)` calls a primary key method on every object in this array. From tests --- Before (3 queries): ```sql SELECT "customers".* FROM "customers" SELECT "customers".* FROM "customers" INNER JOIN "customers_privileges" ON "customers_privileges"."customer_id" = "customers"."id" INNER JOIN "privileges" ON "privileges"."id" = "customers_privileges"."privilege_id" WHERE (((privileges.name = 'admin') AND (privileges.resource_type IS NULL) AND (privileges.resource_id IS NULL))) SELECT "customers".* FROM "customers" WHERE "customers"."id" IN (2, 3, 4) ... (continued)
3 of 3 new or added lines in 2 files covered. (100.0%)
1767 of 1892 relevant lines covered (93.39%)
567.53 hits per line