compact_flags 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +84 -0
- data/Rakefile +37 -0
- data/lib/compact_flags/engine.rb +5 -0
- data/lib/compact_flags/version.rb +3 -0
- data/lib/compact_flags.rb +69 -0
- metadata +55 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2ae649be5e24261937664a2a59eefd82bca91aeb
|
4
|
+
data.tar.gz: 352303d5bdb7711c09fd23f981bfa61b44dc818e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dd5a6e8a80712b55f348f9138913ad66a66ee0ed8dff6d7477dd1342cbc1e74b9d60b9811888b9381ed577872613cdc023742c8b1d92b684920e7a22b78768e3
|
7
|
+
data.tar.gz: 7965bf9098e8b13cd241017cf231ee5d4d948d8dfd9eaeef7a3cbbf611c665866e2db5a11384851906b4570ea3afc56727e7255c95c2ed515d05a28a24002322
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2017 Dr-Click
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
## Introduction
|
2
|
+
|
3
|
+
Ruby Gem to store many boolean flags in an integer column by utilizing bits Edit
|
4
|
+
Add topics
|
5
|
+
|
6
|
+
CompactFlags comes to serve models with several boolean flags. in large data volumes where the flags can be used to slice the data in several ways. queries tend to be heavier and more indexes are needed by time.
|
7
|
+
|
8
|
+
This Gem is made so it can store several flags in one integer attribute through bit wise operations. the attribute represents the state of each record. And is much more performant in database queries
|
9
|
+
|
10
|
+
## Compatible
|
11
|
+
|
12
|
+
Compatible with Rails 4 and 5
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem 'compact_flags'
|
18
|
+
|
19
|
+
```
|
20
|
+
Then run bundle to install the Gem:
|
21
|
+
```sh
|
22
|
+
bundle install
|
23
|
+
```
|
24
|
+
|
25
|
+
|
26
|
+
## Database Migrations
|
27
|
+
|
28
|
+
You need to add an integer column only to your model. which will be used later as the flags store, you can just use a migration that adds inter column like below:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
class AddRoles < ActiveRecord::Migration
|
32
|
+
def change
|
33
|
+
add_column :users, :roles, :integer, :null=>false, :default=>0
|
34
|
+
end
|
35
|
+
end
|
36
|
+
```
|
37
|
+
|
38
|
+
Now run migrations:
|
39
|
+
```sh
|
40
|
+
bundle exec rake db:migrate
|
41
|
+
```
|
42
|
+
|
43
|
+
## Usage example
|
44
|
+
|
45
|
+
After adding the gem and creating an integer column, for example: "roles" to your model, add the "compact_flags" lines passing the flags store column name, and the array of flags
|
46
|
+
|
47
|
+
class User < ActiveRecord::Base
|
48
|
+
compact_flags :roles => [:admin, :moderator, :editor]
|
49
|
+
end
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
# the corresponding getters and setters for all the boolean flags has been created
|
53
|
+
user = User.new
|
54
|
+
user.admin = true
|
55
|
+
user.admin? # <= will return true
|
56
|
+
user.moderator? # <= will return false
|
57
|
+
user.save
|
58
|
+
```
|
59
|
+
|
60
|
+
Scopes will also be automatically available for objects retrieval from the database.
|
61
|
+
Two names scopes will be available for each flag. with the plural name of the flag, and another one
|
62
|
+
preceded with "not_".
|
63
|
+
scopes gives a suitable flexibility because they can be used in a cascaded style to build complex conditions
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
User.admins # <= The pluralize of flag name
|
67
|
+
User.not_moderators # <= The pluralize of flag name with 'not_'
|
68
|
+
User.not_moderators.admins
|
69
|
+
```
|
70
|
+
|
71
|
+
Other methods are also available to return the relevant condition part as a string, for concatenation with a condition string. those comes with the in the form of _where_ and _where_not_
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
User.admin_value # => returns associated value to admin => 1
|
75
|
+
User.moderator_value # => returns associated value to moderator => 2
|
76
|
+
User.where_admin # => "(roles & 1) > 0"
|
77
|
+
User.where_not_admin # => "(roles & 1) = 0"
|
78
|
+
User.where_not_moderator # => "(roles & 2) = 0"
|
79
|
+
```
|
80
|
+
|
81
|
+
## Contributions
|
82
|
+
|
83
|
+
* Mahmoud Said aka modsaid (mahmoud@modsaid.com)
|
84
|
+
* Mostafa Ragab aka dr-click (ragab.mostafa@gmail.com)
|
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'CompactFlags'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
|
21
|
+
load 'rails/tasks/statistics.rake'
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
require 'bundler/gem_tasks'
|
26
|
+
|
27
|
+
require 'rake/testtask'
|
28
|
+
|
29
|
+
Rake::TestTask.new(:test) do |t|
|
30
|
+
t.libs << 'lib'
|
31
|
+
t.libs << 'test'
|
32
|
+
t.pattern = 'test/**/*_test.rb'
|
33
|
+
t.verbose = false
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
task default: :test
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "compact_flags/engine"
|
2
|
+
|
3
|
+
module CompactFlags
|
4
|
+
module HasFlags
|
5
|
+
MAX_FLAGS_MAPPING = 0xFFFFFFFF
|
6
|
+
MAX_FLAGS_COUNT = 31
|
7
|
+
|
8
|
+
def self.included(base)
|
9
|
+
base.extend ClassMethods
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def compact_flags(*args)
|
14
|
+
mapping = args.first
|
15
|
+
store_column = mapping.keys.first
|
16
|
+
flags = mapping[store_column]
|
17
|
+
|
18
|
+
raise "No flags defined" if flags.blank?
|
19
|
+
raise "Too many flags, maximum flags count (#{MAX_FLAGS_COUNT})" if flags.size > MAX_FLAGS_COUNT
|
20
|
+
|
21
|
+
@@flags ||={}
|
22
|
+
@@store_columns ||={}
|
23
|
+
i=0
|
24
|
+
|
25
|
+
flags.each do |flag|
|
26
|
+
@@flags[flag] = 1 << i
|
27
|
+
@@store_columns[flag] = store_column
|
28
|
+
i += 1
|
29
|
+
|
30
|
+
# Define instance getter
|
31
|
+
define_method "#{flag}" do
|
32
|
+
return (@@flags[flag] & self.send(store_column)) > 0
|
33
|
+
end
|
34
|
+
|
35
|
+
alias_method "#{flag}?", "#{flag}"
|
36
|
+
|
37
|
+
# Define instance setter
|
38
|
+
define_method "#{flag}=" do |val|
|
39
|
+
self.send("#{store_column}=", (val ?
|
40
|
+
self.send(store_column) | @@flags[flag] :
|
41
|
+
self.send(store_column) & (MAX_FLAGS_MAPPING ^ @@flags[flag]) ))
|
42
|
+
end
|
43
|
+
|
44
|
+
# named scopes to be used in conditions
|
45
|
+
scope "#{flag}".pluralize.to_sym, -> {where("(#{@@store_columns[flag]} & #{@@flags[flag]}) > 0")}
|
46
|
+
scope "not_#{flag}".pluralize.to_sym, -> {where("(#{@@store_columns[flag]} & #{@@flags[flag]}) = 0")}
|
47
|
+
end
|
48
|
+
|
49
|
+
class << self
|
50
|
+
@@flags.each do |key, value|
|
51
|
+
define_method "#{key}_value" do
|
52
|
+
return value
|
53
|
+
end
|
54
|
+
|
55
|
+
define_method "where_#{key}" do
|
56
|
+
return "(#{@@store_columns[key]} & #{@@flags[key]}) > 0"
|
57
|
+
end
|
58
|
+
|
59
|
+
define_method "where_not_#{key}" do
|
60
|
+
return "(#{@@store_columns[key]} & #{@@flags[key]}) = 0"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
ActiveRecord::Base.send :include, CompactFlags::HasFlags
|
metadata
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: compact_flags
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dr-Click
|
8
|
+
- ModSaid
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2017-03-13 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Ruby Gem to store many boolean flags in an integer column by utilizing
|
15
|
+
bits, CompactFlags comes to serve models with several boolean flags. in large data
|
16
|
+
volumes where the flags can be used to slice the data in several ways. queries tend
|
17
|
+
to be heavier and more indexes are needed by time.
|
18
|
+
email:
|
19
|
+
- ragab.mostafa@gmail.com
|
20
|
+
- mahmoud@modsaid.com
|
21
|
+
executables: []
|
22
|
+
extensions: []
|
23
|
+
extra_rdoc_files: []
|
24
|
+
files:
|
25
|
+
- MIT-LICENSE
|
26
|
+
- README.md
|
27
|
+
- Rakefile
|
28
|
+
- lib/compact_flags.rb
|
29
|
+
- lib/compact_flags/engine.rb
|
30
|
+
- lib/compact_flags/version.rb
|
31
|
+
homepage: https://github.com/dr-click/compact-flags
|
32
|
+
licenses:
|
33
|
+
- MIT
|
34
|
+
metadata: {}
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
requirements: []
|
50
|
+
rubyforge_project:
|
51
|
+
rubygems_version: 2.5.1
|
52
|
+
signing_key:
|
53
|
+
specification_version: 4
|
54
|
+
summary: Ruby Gem to store many boolean flags in an integer column by utilizing bits
|
55
|
+
test_files: []
|