compact_flags 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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,5 @@
1
+ module CompactFlags
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace CompactFlags
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module CompactFlags
2
+ VERSION = '1.0.1'
3
+ end
@@ -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: []