bitfields 0.4.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fbae8863b34f3374742a6af0481aac9f284cf15b
4
+ data.tar.gz: 394e4e9db360d7eecfa030cf072047d3b687a768
5
+ SHA512:
6
+ metadata.gz: b32ed7e44546be81ae203e252564c3286bf80ba275de4b8a695ebe3b6d14017a4dca244469443f3edde593475ed89d97954a04314c0a3cca1f25167705c2c6b3
7
+ data.tar.gz: 7a63c7f78bb3d884fb9e88283ddc653d8963a1c347c17ec7b3f6a4efc27f345e8a8c5bf37027b4d5ff261e4cb65143c727532e6fc03e810625c95b4abe54af84
@@ -38,19 +38,6 @@ module Bitfields
38
38
  bitfields
39
39
  end
40
40
 
41
- def self.ar_3?
42
- defined?(ActiveRecord::VERSION::MAJOR) and ActiveRecord::VERSION::MAJOR >= 3
43
- end
44
-
45
- # AR 3+ -> :scope, below :named_scope
46
- def self.ar_scoping_method
47
- if ar_3?
48
- :scope
49
- else
50
- :named_scope
51
- end
52
- end
53
-
54
41
  module ClassMethods
55
42
  def bitfield(column, *args)
56
43
  column = column.to_sym
@@ -99,9 +86,8 @@ module Bitfields
99
86
  define_method("#{bit_name}=") { |value| set_bitfield_value(bit_name, value) }
100
87
 
101
88
  if options[:scopes] != false
102
- scoping_method = Bitfields.ar_scoping_method
103
- send scoping_method, bit_name, bitfield_scope_options(bit_name => true)
104
- send scoping_method, "not_#{bit_name}", bitfield_scope_options(bit_name => false)
89
+ scope bit_name, bitfield_scope_options(bit_name => true)
90
+ scope "not_#{bit_name}", bitfield_scope_options(bit_name => false)
105
91
  end
106
92
  end
107
93
 
@@ -109,13 +95,7 @@ module Bitfields
109
95
  end
110
96
 
111
97
  def bitfield_scope_options(bit_values)
112
- sql = bitfield_sql(bit_values)
113
-
114
- if Bitfields.ar_3?
115
- lambda { where(sql) }
116
- else
117
- {:conditions => sql}
118
- end
98
+ -> { where(bitfield_sql(bit_values)) }
119
99
  end
120
100
 
121
101
  def bitfield_sql_by_column(column, bit_values, options={})
@@ -167,6 +147,13 @@ module Bitfields
167
147
  Hash[self.class.bitfields[column.to_sym].map{|bit_name, _| [bit_name, bitfield_value(bit_name)]}]
168
148
  end
169
149
 
150
+ def bitfield_changes
151
+ self.class.bitfields.values.flat_map(&:keys).each_with_object({}) do |bit, changes|
152
+ old, current = bitfield_value_was(bit), bitfield_value(bit)
153
+ changes[bit.to_s] = [old, current] unless old == current
154
+ end
155
+ end
156
+
170
157
  private
171
158
 
172
159
  def bitfield_value(bit_name)
@@ -174,16 +161,17 @@ module Bitfields
174
161
  current_value & bit != 0
175
162
  end
176
163
 
164
+ def bitfield_value_was(bit_name)
165
+ column, bit, _ = bitfield_info(bit_name)
166
+ send("#{column}_was") & bit != 0
167
+ end
168
+
177
169
  def set_bitfield_value(bit_name, value)
178
170
  column, bit, current_value = bitfield_info(bit_name)
179
171
  new_value = TRUE_VALUES.include?(value)
180
172
  old_value = bitfield_value(bit_name)
181
173
  return if new_value == old_value
182
174
 
183
- if defined? changed_attributes
184
- send(:changed_attributes).merge!(bit_name.to_s => old_value)
185
- end
186
-
187
175
  # 8 + 1 == 9 // 8 + 8 == 8 // 1 - 8 == 1 // 8 - 8 == 0
188
176
  new_bits = if new_value then current_value | bit else (current_value | bit) - bit end
189
177
  send("#{column}=", new_bits)
@@ -6,16 +6,15 @@ RSpec::Matchers.define :have_a_bitfield do |field|
6
6
  klass.respond_to?("#{field}=")
7
7
  end
8
8
 
9
- failure_message_for_should do |klass|
9
+ failure_message do |klass|
10
10
  "expected #{expected.join} to be a bitfield property defined on #{klass}"
11
11
  end
12
12
 
13
- failure_message_for_should_not do |klass|
13
+ failure_message_when_negated do |klass|
14
14
  "expected #{expected.join} to NOT be a bitfield property defined on #{klass}"
15
15
  end
16
16
 
17
17
  description do
18
18
  "be a bitfield on #{expected}"
19
19
  end
20
-
21
20
  end
@@ -1,3 +1,3 @@
1
1
  module Bitfields
2
- Version = VERSION = "0.4.3"
2
+ Version = VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,75 +1,131 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitfields
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
5
- prerelease:
4
+ version: 0.5.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Michael Grosser
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-05-14 00:00:00.000000000 Z
13
- dependencies: []
11
+ date: 2015-01-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: wwtd
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bump
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
14
97
  description:
15
98
  email: michael@grosser.it
16
99
  executables: []
17
100
  extensions: []
18
101
  extra_rdoc_files: []
19
102
  files:
20
- - .travis.yml
21
- - Appraisals
22
- - Gemfile
23
- - Gemfile.lock
24
- - Rakefile
25
103
  - Readme.md
26
- - benchmark/bit_operator_vs_in.rb
27
- - bitfields.gemspec
28
- - gemfiles/activerecord_2.3.gemfile
29
- - gemfiles/activerecord_2.3.gemfile.lock
30
- - gemfiles/activerecord_3.0.gemfile
31
- - gemfiles/activerecord_3.0.gemfile.lock
32
- - gemfiles/activerecord_3.1.gemfile
33
- - gemfiles/activerecord_3.1.gemfile.lock
34
- - gemfiles/activerecord_3.2.gemfile
35
- - gemfiles/activerecord_3.2.gemfile.lock
36
- - gemfiles/activerecord_4.0.gemfile
37
- - gemfiles/activerecord_4.0.gemfile.lock
38
104
  - lib/bitfields.rb
39
105
  - lib/bitfields/rspec.rb
40
106
  - lib/bitfields/version.rb
41
- - spec/bitfields_spec.rb
42
- - spec/database.rb
43
- - spec/spec_helper.rb
44
- homepage: http://github.com/grosser/bitfields
107
+ homepage: https://github.com/grosser/bitfields
45
108
  licenses:
46
109
  - MIT
110
+ metadata: {}
47
111
  post_install_message:
48
112
  rdoc_options: []
49
113
  require_paths:
50
114
  - lib
51
115
  required_ruby_version: !ruby/object:Gem::Requirement
52
- none: false
53
116
  requirements:
54
- - - ! '>='
117
+ - - ">="
55
118
  - !ruby/object:Gem::Version
56
- version: '0'
57
- segments:
58
- - 0
59
- hash: 950427918472941761
119
+ version: 1.9.3
60
120
  required_rubygems_version: !ruby/object:Gem::Requirement
61
- none: false
62
121
  requirements:
63
- - - ! '>='
122
+ - - ">="
64
123
  - !ruby/object:Gem::Version
65
124
  version: '0'
66
- segments:
67
- - 0
68
- hash: 950427918472941761
69
125
  requirements: []
70
126
  rubyforge_project:
71
- rubygems_version: 1.8.25
127
+ rubygems_version: 2.2.2
72
128
  signing_key:
73
- specification_version: 3
129
+ specification_version: 4
74
130
  summary: Save migrations and columns by storing multiple booleans in a single integer
75
131
  test_files: []
@@ -1,19 +0,0 @@
1
- rvm:
2
- - 1.8.7
3
- - 1.9.3
4
- - 2.0.0
5
- gemfile:
6
- - gemfiles/activerecord_2.3.gemfile
7
- - gemfiles/activerecord_3.0.gemfile
8
- - gemfiles/activerecord_3.1.gemfile
9
- - gemfiles/activerecord_3.2.gemfile
10
- - gemfiles/activerecord_4.0.gemfile
11
- matrix:
12
- exclude:
13
- - rvm: 1.8.7
14
- gemfile: gemfiles/activerecord_4.0.gemfile
15
- - rvm: 2.0.0
16
- gemfile: gemfiles/activerecord_2.3.gemfile
17
- - rvm: 2.0.0
18
- gemfile: gemfiles/activerecord_3.0.gemfile
19
- script: rake spec
data/Appraisals DELETED
@@ -1,9 +0,0 @@
1
- ["2.3", "3.0", "3.1", "3.2"].each do |version|
2
- appraise "activerecord_#{version}" do
3
- gem "activerecord", "~> #{version}.0"
4
- end
5
- end
6
-
7
- appraise "activerecord_4.0" do
8
- gem "activerecord", "~> 4.0.0.rc"
9
- end
data/Gemfile DELETED
@@ -1,9 +0,0 @@
1
- source "https://rubygems.org"
2
- gemspec
3
-
4
- gem 'appraisal'
5
- gem 'activerecord'
6
- gem 'sqlite3'
7
- gem 'rake'
8
- gem 'rspec', '~>2'
9
- gem 'bump'
@@ -1,51 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- bitfields (0.4.3)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- activemodel (3.2.11)
10
- activesupport (= 3.2.11)
11
- builder (~> 3.0.0)
12
- activerecord (3.2.11)
13
- activemodel (= 3.2.11)
14
- activesupport (= 3.2.11)
15
- arel (~> 3.0.2)
16
- tzinfo (~> 0.3.29)
17
- activesupport (3.2.11)
18
- i18n (~> 0.6)
19
- multi_json (~> 1.0)
20
- appraisal (0.5.1)
21
- bundler
22
- rake
23
- arel (3.0.2)
24
- builder (3.0.4)
25
- bump (0.3.9)
26
- diff-lcs (1.1.3)
27
- i18n (0.6.1)
28
- multi_json (1.5.0)
29
- rake (10.0.3)
30
- rspec (2.12.0)
31
- rspec-core (~> 2.12.0)
32
- rspec-expectations (~> 2.12.0)
33
- rspec-mocks (~> 2.12.0)
34
- rspec-core (2.12.2)
35
- rspec-expectations (2.12.1)
36
- diff-lcs (~> 1.1.3)
37
- rspec-mocks (2.12.1)
38
- sqlite3 (1.3.7)
39
- tzinfo (0.3.35)
40
-
41
- PLATFORMS
42
- ruby
43
-
44
- DEPENDENCIES
45
- activerecord
46
- appraisal
47
- bitfields!
48
- bump
49
- rake
50
- rspec (~> 2)
51
- sqlite3
data/Rakefile DELETED
@@ -1,11 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "bump/tasks"
3
- require "appraisal"
4
-
5
- task :spec do
6
- sh "rspec spec/"
7
- end
8
-
9
- task :default do
10
- sh "bundle exec rake appraisal:install && bundle exec rake appraisal spec"
11
- end
@@ -1,137 +0,0 @@
1
- bit_counts = [2,3,4,6,8,10,12,14]
2
- record_counts = (1..10).to_a.map{|i| i * 100_000 }
3
- use_index = true
4
- database = ARGV[0]
5
-
6
- puts "running#{' with index' if use_index} on #{database}"
7
-
8
- $LOAD_PATH.unshift File.expand_path('lib')
9
- require 'rubygems'
10
- gem 'gchartrb'
11
- require 'google_chart'
12
- require 'active_record'
13
- require 'bitfields'
14
-
15
- def benchmark
16
- t = Time.now.to_f
17
- yield
18
- Time.now.to_f - t
19
- end
20
-
21
- def create(bit_counts, count)
22
- count.times do |i|
23
- columns = bit_counts.map do |bits_count|
24
- ["bit_#{bits_count}", rand(2**(bits_count-1))]
25
- end
26
- User.create!(Hash[columns])
27
- end
28
- end
29
-
30
- def connect(db)
31
- if db == 'mysql'
32
- puts 'using mysql'
33
- ActiveRecord::Base.establish_connection(
34
- :adapter => "mysql",
35
- :database => "bitfields_benchmark"
36
- )
37
- else
38
- puts 'using sqlite'
39
- ActiveRecord::Base.establish_connection(
40
- :adapter => "sqlite3",
41
- :database => ":memory:"
42
- )
43
- end
44
- end
45
-
46
- def create_model_table(bit_counts, use_index)
47
- ActiveRecord::Schema.define(:version => 2) do
48
- drop_table :users rescue nil
49
- create_table :users do |t|
50
- bit_counts.each do |bit_count|
51
- t.integer "bit_#{bit_count}", :default => 0, :null => false
52
- end
53
- end
54
-
55
- if use_index
56
- bit_counts.each do |bit_count|
57
- add_index :users, "bit_#{bit_count}"
58
- end
59
- end
60
- end
61
- end
62
-
63
- def create_model_fields(bit_counts)
64
- puts "creating model"
65
- User.class_eval do
66
- include Bitfields
67
-
68
- # this takes long for 15/20 bits, maybe needs to be optimized..
69
- bit_counts.each do |bits_count|
70
- bits = {}
71
- 0.upto(bits_count-1) do |bit|
72
- bits[2**bit] = "bit_#{bits_count}_#{bit}"
73
- end
74
-
75
- bitfield "bit_#{bits_count}", bits
76
- end
77
- end
78
- end
79
-
80
- def test_speed(bit_counts, query_mode)
81
- result = bit_counts.map do |bit_count|
82
- sql = User.bitfield_sql({"bit_#{bit_count}_1" => true}, :query_mode => query_mode)
83
- sql = "select SQL_NO_CACHE count(*) from users where #{sql}"
84
- # puts User.connection.select_all("EXPLAIN #{sql}").inspect
85
- # puts sql[0..100]
86
- time = benchmark do
87
- User.connection.execute sql
88
- end
89
- puts "#{bit_count} -> #{time}"
90
- [bit_count, time]
91
- end
92
- Hash[result]
93
- end
94
-
95
- connect(database)
96
- create_model_table(bit_counts, use_index)
97
- class User < ActiveRecord::Base
98
- end
99
- create_model_fields(bit_counts)
100
-
101
- puts "creating test data"
102
- last = 0
103
-
104
- # collect graph data
105
- graphs = {:bit => {}, :in => {}}
106
- record_counts.each do |record_count|
107
- create(bit_counts, record_count-last)
108
- last = record_count
109
-
110
- puts "testing with #{record_count} records -- bit_operator"
111
- graphs[:bit][record_count] = test_speed(bit_counts, :bit_operator)
112
-
113
- puts "testing with #{record_count} records -- in_list"
114
- graphs[:in][record_count] = test_speed(bit_counts, :in_list)
115
- end
116
-
117
- # print them
118
- colors = {:bit => 'xx0000', :in => '0000xx'}
119
- alpha_num = (('0'..'9').to_a + ('a'..'f').to_a).reverse
120
- title = "bit-operator vs IN -- #{use_index ? 'with' : 'without'} index"
121
- url = GoogleChart::LineChart.new('600x500', title, false) do |line|
122
- max_y = 0
123
- graphs.each do |type, line_data|
124
- bit_counts.each do |bit_count|
125
- data = record_counts.map{|rc| line_data[rc][bit_count] }
126
- name = "#{bit_count}bits (#{type})"
127
- color = colors[type].sub('xx', alpha_num[bit_counts.index(bit_count)]*2)
128
- line.data(name, data, color)
129
- max_y = [data.max, max_y].max
130
- end
131
- end
132
-
133
- line.axis :x, :labels => record_counts.map{|c|"#{c/1000}K"}
134
- line.axis :y, :labels => ['0', "%.3fms" % [max_y*1000]]
135
- end.to_url
136
-
137
- puts url
@@ -1,12 +0,0 @@
1
- $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2
- name = "bitfields"
3
- require "#{name}/version"
4
-
5
- Gem::Specification.new name, Bitfields::VERSION do |s|
6
- s.summary = "Save migrations and columns by storing multiple booleans in a single integer"
7
- s.authors = ["Michael Grosser"]
8
- s.email = "michael@grosser.it"
9
- s.homepage = "http://github.com/grosser/#{name}"
10
- s.files = `git ls-files`.split("\n")
11
- s.license = 'MIT'
12
- end
@@ -1,12 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "appraisal"
6
- gem "sqlite3"
7
- gem "rake"
8
- gem "rspec", "~>2"
9
- gem "bump"
10
- gem "activerecord", "~> 2.3.0"
11
-
12
- gemspec :path=>"../"
@@ -1,38 +0,0 @@
1
- PATH
2
- remote: /Users/mgrosser/code/tools/bitfields
3
- specs:
4
- bitfields (0.4.2)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- activerecord (2.3.15)
10
- activesupport (= 2.3.15)
11
- activesupport (2.3.15)
12
- appraisal (0.5.1)
13
- bundler
14
- rake
15
- bump (0.3.9)
16
- diff-lcs (1.1.3)
17
- rake (10.0.3)
18
- rspec (2.12.0)
19
- rspec-core (~> 2.12.0)
20
- rspec-expectations (~> 2.12.0)
21
- rspec-mocks (~> 2.12.0)
22
- rspec-core (2.12.2)
23
- rspec-expectations (2.12.1)
24
- diff-lcs (~> 1.1.3)
25
- rspec-mocks (2.12.1)
26
- sqlite3 (1.3.7)
27
-
28
- PLATFORMS
29
- ruby
30
-
31
- DEPENDENCIES
32
- activerecord (~> 2.3.0)
33
- appraisal
34
- bitfields!
35
- bump
36
- rake
37
- rspec (~> 2)
38
- sqlite3
@@ -1,12 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "appraisal"
6
- gem "sqlite3"
7
- gem "rake"
8
- gem "rspec", "~>2"
9
- gem "bump"
10
- gem "activerecord", "~> 3.0.0"
11
-
12
- gemspec :path=>"../"
@@ -1,49 +0,0 @@
1
- PATH
2
- remote: /Users/mgrosser/code/tools/bitfields
3
- specs:
4
- bitfields (0.4.2)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- activemodel (3.0.19)
10
- activesupport (= 3.0.19)
11
- builder (~> 2.1.2)
12
- i18n (~> 0.5.0)
13
- activerecord (3.0.19)
14
- activemodel (= 3.0.19)
15
- activesupport (= 3.0.19)
16
- arel (~> 2.0.10)
17
- tzinfo (~> 0.3.23)
18
- activesupport (3.0.19)
19
- appraisal (0.5.1)
20
- bundler
21
- rake
22
- arel (2.0.10)
23
- builder (2.1.2)
24
- bump (0.3.9)
25
- diff-lcs (1.1.3)
26
- i18n (0.5.0)
27
- rake (10.0.3)
28
- rspec (2.12.0)
29
- rspec-core (~> 2.12.0)
30
- rspec-expectations (~> 2.12.0)
31
- rspec-mocks (~> 2.12.0)
32
- rspec-core (2.12.2)
33
- rspec-expectations (2.12.1)
34
- diff-lcs (~> 1.1.3)
35
- rspec-mocks (2.12.1)
36
- sqlite3 (1.3.7)
37
- tzinfo (0.3.35)
38
-
39
- PLATFORMS
40
- ruby
41
-
42
- DEPENDENCIES
43
- activerecord (~> 3.0.0)
44
- appraisal
45
- bitfields!
46
- bump
47
- rake
48
- rspec (~> 2)
49
- sqlite3
@@ -1,12 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "appraisal"
6
- gem "sqlite3"
7
- gem "rake"
8
- gem "rspec", "~>2"
9
- gem "bump"
10
- gem "activerecord", "~> 3.1.0"
11
-
12
- gemspec :path=>"../"
@@ -1,51 +0,0 @@
1
- PATH
2
- remote: /Users/mgrosser/code/tools/bitfields
3
- specs:
4
- bitfields (0.4.2)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- activemodel (3.1.8)
10
- activesupport (= 3.1.8)
11
- builder (~> 3.0.0)
12
- i18n (~> 0.6)
13
- activerecord (3.1.8)
14
- activemodel (= 3.1.8)
15
- activesupport (= 3.1.8)
16
- arel (~> 2.2.3)
17
- tzinfo (~> 0.3.29)
18
- activesupport (3.1.8)
19
- multi_json (>= 1.0, < 1.3)
20
- appraisal (0.5.1)
21
- bundler
22
- rake
23
- arel (2.2.3)
24
- builder (3.0.4)
25
- bump (0.3.9)
26
- diff-lcs (1.1.3)
27
- i18n (0.6.1)
28
- multi_json (1.2.0)
29
- rake (10.0.3)
30
- rspec (2.12.0)
31
- rspec-core (~> 2.12.0)
32
- rspec-expectations (~> 2.12.0)
33
- rspec-mocks (~> 2.12.0)
34
- rspec-core (2.12.2)
35
- rspec-expectations (2.12.1)
36
- diff-lcs (~> 1.1.3)
37
- rspec-mocks (2.12.1)
38
- sqlite3 (1.3.7)
39
- tzinfo (0.3.35)
40
-
41
- PLATFORMS
42
- ruby
43
-
44
- DEPENDENCIES
45
- activerecord (~> 3.1.0)
46
- appraisal
47
- bitfields!
48
- bump
49
- rake
50
- rspec (~> 2)
51
- sqlite3
@@ -1,12 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "appraisal"
6
- gem "sqlite3"
7
- gem "rake"
8
- gem "rspec", "~>2"
9
- gem "bump"
10
- gem "activerecord", "~> 3.2.0"
11
-
12
- gemspec :path=>"../"
@@ -1,51 +0,0 @@
1
- PATH
2
- remote: /Users/mgrosser/code/tools/bitfields
3
- specs:
4
- bitfields (0.4.2)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- activemodel (3.2.11)
10
- activesupport (= 3.2.11)
11
- builder (~> 3.0.0)
12
- activerecord (3.2.11)
13
- activemodel (= 3.2.11)
14
- activesupport (= 3.2.11)
15
- arel (~> 3.0.2)
16
- tzinfo (~> 0.3.29)
17
- activesupport (3.2.11)
18
- i18n (~> 0.6)
19
- multi_json (~> 1.0)
20
- appraisal (0.5.1)
21
- bundler
22
- rake
23
- arel (3.0.2)
24
- builder (3.0.4)
25
- bump (0.3.9)
26
- diff-lcs (1.1.3)
27
- i18n (0.6.1)
28
- multi_json (1.5.0)
29
- rake (10.0.3)
30
- rspec (2.12.0)
31
- rspec-core (~> 2.12.0)
32
- rspec-expectations (~> 2.12.0)
33
- rspec-mocks (~> 2.12.0)
34
- rspec-core (2.12.2)
35
- rspec-expectations (2.12.1)
36
- diff-lcs (~> 1.1.3)
37
- rspec-mocks (2.12.1)
38
- sqlite3 (1.3.7)
39
- tzinfo (0.3.35)
40
-
41
- PLATFORMS
42
- ruby
43
-
44
- DEPENDENCIES
45
- activerecord (~> 3.2.0)
46
- appraisal
47
- bitfields!
48
- bump
49
- rake
50
- rspec (~> 2)
51
- sqlite3
@@ -1,12 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "appraisal"
6
- gem "sqlite3"
7
- gem "rake"
8
- gem "rspec", "~>2"
9
- gem "bump"
10
- gem "activerecord", "~> 4.0.0.rc"
11
-
12
- gemspec :path=>"../"
@@ -1,59 +0,0 @@
1
- PATH
2
- remote: /Users/mgrosser/code/tools/bitfields
3
- specs:
4
- bitfields (0.4.2)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- activemodel (4.0.0.rc1)
10
- activesupport (= 4.0.0.rc1)
11
- builder (~> 3.1.0)
12
- activerecord (4.0.0.rc1)
13
- activemodel (= 4.0.0.rc1)
14
- activerecord-deprecated_finders (~> 1.0.2)
15
- activesupport (= 4.0.0.rc1)
16
- arel (~> 4.0.0)
17
- activerecord-deprecated_finders (1.0.2)
18
- activesupport (4.0.0.rc1)
19
- i18n (~> 0.6, >= 0.6.4)
20
- minitest (~> 4.2)
21
- multi_json (~> 1.3)
22
- thread_safe (~> 0.1)
23
- tzinfo (~> 0.3.37)
24
- appraisal (0.5.2)
25
- bundler
26
- rake
27
- arel (4.0.0)
28
- atomic (1.1.9)
29
- builder (3.1.4)
30
- bump (0.4.1)
31
- diff-lcs (1.2.4)
32
- i18n (0.6.4)
33
- minitest (4.7.4)
34
- multi_json (1.7.3)
35
- rake (10.0.4)
36
- rspec (2.13.0)
37
- rspec-core (~> 2.13.0)
38
- rspec-expectations (~> 2.13.0)
39
- rspec-mocks (~> 2.13.0)
40
- rspec-core (2.13.1)
41
- rspec-expectations (2.13.0)
42
- diff-lcs (>= 1.1.3, < 2.0)
43
- rspec-mocks (2.13.1)
44
- sqlite3 (1.3.7)
45
- thread_safe (0.1.0)
46
- atomic
47
- tzinfo (0.3.37)
48
-
49
- PLATFORMS
50
- ruby
51
-
52
- DEPENDENCIES
53
- activerecord (~> 4.0.0.rc)
54
- appraisal
55
- bitfields!
56
- bump
57
- rake
58
- rspec (~> 2)
59
- sqlite3
@@ -1,450 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class User < ActiveRecord::Base
4
- include Bitfields
5
- bitfield :bits, 1 => :seller, 2 => :insane, 4 => :stupid
6
- end
7
-
8
- class UserWithBitfieldOptions < ActiveRecord::Base
9
- include Bitfields
10
- bitfield :bits, 1 => :seller, 2 => :insane, 4 => :stupid, :scopes => false
11
- end
12
-
13
- class MultiBitUser < ActiveRecord::Base
14
- self.table_name = 'users'
15
- include Bitfields
16
- bitfield :bits, 1 => :seller, 2 => :insane, 4 => :stupid
17
- bitfield :more_bits, 1 => :one, 2 => :two, 4 => :four
18
- end
19
-
20
- class UserWithoutScopes < ActiveRecord::Base
21
- self.table_name = 'users'
22
- include Bitfields
23
- bitfield :bits, 1 => :seller, 2 => :insane, 4 => :stupid, :scopes => false
24
- end
25
-
26
- class UserWithoutSetBitfield < ActiveRecord::Base
27
- self.table_name = 'users'
28
- include Bitfields
29
- end
30
-
31
- class InheritedUser < User
32
- end
33
-
34
- class GrandchildInheritedUser < InheritedUser
35
- end
36
-
37
- # other children should not disturb the inheritance
38
- class OtherInheritedUser < UserWithoutSetBitfield
39
- self.table_name = 'users'
40
- bitfield :bits, 1 => :seller_inherited
41
- end
42
-
43
- class InheritedUserWithoutSetBitfield < UserWithoutSetBitfield
44
- end
45
-
46
- class OverwrittenUser < User
47
- bitfield :bits, 1 => :seller_inherited
48
- end
49
-
50
- class BitOperatorMode < ActiveRecord::Base
51
- self.table_name = 'users'
52
- include Bitfields
53
- bitfield :bits, 1 => :seller, 2 => :insane, :query_mode => :bit_operator
54
- end
55
-
56
- class WithoutThePowerOfTwo < ActiveRecord::Base
57
- self.table_name = 'users'
58
- include Bitfields
59
- bitfield :bits, :seller, :insane, :stupid, :query_mode => :bit_operator
60
- end
61
-
62
- class WithoutThePowerOfTwoWithoutOptions < ActiveRecord::Base
63
- self.table_name = 'users'
64
- include Bitfields
65
- bitfield :bits, :seller, :insane
66
- end
67
-
68
- class CheckRaise < ActiveRecord::Base
69
- self.table_name = 'users'
70
- include Bitfields
71
- end
72
-
73
- class ManyBitsUser < User
74
- self.table_name = 'users'
75
- end
76
-
77
- class InitializedUser < User
78
- self.table_name = 'users'
79
- bitfield :bits, 1 => :seller, 2 => :insane, 4 => :stupid, :scopes => false
80
-
81
- after_initialize do
82
- self.seller = true
83
- self.insane = false
84
- end
85
- end
86
-
87
- describe Bitfields do
88
- before do
89
- User.delete_all
90
- end
91
-
92
- def pending_if(condition, &block)
93
- if condition
94
- pending(&block)
95
- else
96
- yield
97
- end
98
- end
99
-
100
- describe :bitfields do
101
- it "parses them correctly" do
102
- User.bitfields.should == {:bits => {:seller => 1, :insane => 2, :stupid => 4}}
103
- end
104
-
105
- it "is fast for huge number of bits" do
106
- bits = {}
107
- 0.upto(20) do |bit|
108
- bits[2**bit] = "my_bit_#{bit}"
109
- end
110
-
111
- Timeout.timeout(0.2) do
112
- ManyBitsUser.class_eval{ bitfield :bits, bits }
113
- end
114
- end
115
- end
116
-
117
- describe :bitfield_options do
118
- it "parses them correctly when not set" do
119
- User.bitfield_options.should == {:bits => {}}
120
- end
121
-
122
- it "parses them correctly when set" do
123
- UserWithBitfieldOptions.bitfield_options.should == {:bits => {:scopes => false}}
124
- end
125
- end
126
-
127
- describe :bitfield_column do
128
- it "raises a nice error when i use a unknown bitfield" do
129
- lambda{
130
- User.bitfield_column(:xxx)
131
- }.should raise_error(RuntimeError, 'Unknown bitfield xxx')
132
- end
133
- end
134
-
135
- describe :bitfield_values do
136
- it "contains all bits with values" do
137
- User.new.bitfield_values(:bits).should == {:insane=>false, :stupid=>false, :seller=>false}
138
- User.new(:bits => 15).bitfield_values(:bits).should == {:insane=>true, :stupid=>true, :seller=>true}
139
- end
140
- end
141
-
142
- describe 'attribute accessors' do
143
- it "has everything on false by default" do
144
- User.new.seller.should == false
145
- User.new.seller?.should == false
146
- end
147
-
148
- it "is true when set to true" do
149
- User.new(:seller => true).seller.should == true
150
- end
151
-
152
- it "is true when set to truthy" do
153
- User.new(:seller => 1).seller.should == true
154
- end
155
-
156
- it "is false when set to false" do
157
- User.new(:seller => false).seller.should == false
158
- end
159
-
160
- it "is false when set to falsy" do
161
- User.new(:seller => 'false').seller.should == false
162
- end
163
-
164
- it "stays true when set to true twice" do
165
- u = User.new
166
- u.seller = true
167
- u.seller = true
168
- u.seller.should == true
169
- u.bits.should == 1
170
- end
171
-
172
- it "stays false when set to false twice" do
173
- u = User.new(:bits => 3)
174
- u.seller = false
175
- u.seller = false
176
- u.seller.should == false
177
- u.bits.should == 2
178
- end
179
-
180
- it "changes the bits when setting to false" do
181
- user = User.new(:bits => 7)
182
- user.seller = false
183
- user.bits.should == 6
184
- end
185
-
186
- it "does not get negative when unsetting high bits" do
187
- user = User.new(:seller => true)
188
- user.stupid = false
189
- user.bits.should == 1
190
- end
191
-
192
- it "changes the bits when setting to true" do
193
- user = User.new(:bits => 2)
194
- user.seller = true
195
- user.bits.should == 3
196
- end
197
-
198
- it "does not get too high when setting high bits" do
199
- user = User.new(:bits => 7)
200
- user.seller = true
201
- user.bits.should == 7
202
- end
203
-
204
- describe 'changes' do
205
- it "has no changes by defaut" do
206
- User.new.changes.should == {}
207
- end
208
-
209
- it "records a change when setting" do
210
- User.new(:seller => true).changes.should == {'seller' => [false, true], 'bits' => [0,1]}
211
- end
212
-
213
- it "records a change when unsetting" do
214
- u = User.create!(:seller => true)
215
- u.seller = false
216
- u.changes.should == {'seller' => [true, false], 'bits' => [1,0]}
217
- end
218
-
219
- it "does not track duplicate changes" do
220
- User.create!(:seller => false).changes.should == {}
221
- end
222
- end
223
- end
224
-
225
- describe :bitfield_sql do
226
- it "includes true states" do
227
- User.bitfield_sql({:insane => true}, :query_mode => :in_list).should == 'users.bits IN (2,3,6,7)' # 2, 1+2, 2+4, 1+2+4
228
- end
229
-
230
- it "includes invalid states" do
231
- User.bitfield_sql({:insane => false}, :query_mode => :in_list).should == 'users.bits IN (0,1,4,5)' # 0, 1, 4, 4+1
232
- end
233
-
234
- it "can combine multiple fields" do
235
- User.bitfield_sql({:seller => true, :insane => true}, :query_mode => :in_list).should == 'users.bits IN (3,7)' # 1+2, 1+2+4
236
- end
237
-
238
- it "can combine multiple fields with different values" do
239
- User.bitfield_sql({:seller => true, :insane => false}, :query_mode => :in_list).should == 'users.bits IN (1,5)' # 1, 1+4
240
- end
241
-
242
- it "combines multiple columns into one sql" do
243
- sql = MultiBitUser.bitfield_sql({:seller => true, :insane => false, :one => true, :four => true}, :query_mode => :in_list)
244
- sql.should == 'users.bits IN (1,5) AND users.more_bits IN (5,7)' # 1, 1+4 AND 1+4, 1+2+4
245
- end
246
-
247
- it "produces working sql" do
248
- u1 = MultiBitUser.create!(:seller => true, :one => true)
249
- u2 = MultiBitUser.create!(:seller => true, :one => false)
250
- u3 = MultiBitUser.create!(:seller => false, :one => false)
251
- conditions = MultiBitUser.bitfield_sql({:seller => true, :one => false}, :query_mode => :in_list)
252
- result = if Bitfields.ar_3?
253
- MultiBitUser.where(conditions)
254
- else
255
- MultiBitUser.all(:conditions => conditions)
256
- end
257
- result.should == [u2]
258
- end
259
-
260
- describe 'with bit operator mode' do
261
- it "generates bit-operator sql" do
262
- BitOperatorMode.bitfield_sql(:seller => true).should == '(users.bits & 1) = 1'
263
- end
264
-
265
- it "generates sql for each bit" do
266
- BitOperatorMode.bitfield_sql(:seller => true, :insane => false).should == '(users.bits & 3) = 1'
267
- end
268
-
269
- it "generates working sql" do
270
- u1 = BitOperatorMode.create!(:seller => true, :insane => true)
271
- u2 = BitOperatorMode.create!(:seller => true, :insane => false)
272
- u3 = BitOperatorMode.create!(:seller => false, :insane => false)
273
-
274
- conditions = MultiBitUser.bitfield_sql(:seller => true, :insane => false)
275
- result = if Bitfields.ar_3?
276
- BitOperatorMode.where(conditions)
277
- else
278
- BitOperatorMode.all(:conditions => conditions)
279
- end
280
- result.should == [u2]
281
- end
282
- end
283
-
284
- describe 'without the power of two' do
285
- it 'uses correct bits' do
286
- u = WithoutThePowerOfTwo.create!(:seller => false, :insane => true, :stupid => true)
287
- u.bits.should == 6
288
- end
289
-
290
- it 'has all fields' do
291
- u = WithoutThePowerOfTwo.create!(:seller => false, :insane => true)
292
- u.seller.should == false
293
- u.insane.should == true
294
- WithoutThePowerOfTwo.bitfield_options.should == {:bits=>{:query_mode=>:bit_operator}}
295
- end
296
-
297
- it "can e built without options" do
298
- u = WithoutThePowerOfTwoWithoutOptions.create!(:seller => false, :insane => true)
299
- u.seller.should == false
300
- u.insane.should == true
301
- WithoutThePowerOfTwoWithoutOptions.bitfield_options.should == {:bits=>{}}
302
- end
303
- end
304
-
305
- it "checks that bitfields are unique" do
306
- lambda{
307
- CheckRaise.class_eval do
308
- bitfield :foo, :bar, :baz, :bar
309
- end
310
- }.should raise_error(Bitfields::DuplicateBitNameError)
311
- end
312
- end
313
-
314
- describe :set_bitfield_sql do
315
- it "sets a single bit" do
316
- User.set_bitfield_sql(:seller => true).should == 'bits = (bits | 1) - 0'
317
- end
318
-
319
- it "unsets a single bit" do
320
- User.set_bitfield_sql(:seller => false).should == 'bits = (bits | 1) - 1'
321
- end
322
-
323
- it "sets multiple bits" do
324
- User.set_bitfield_sql(:seller => true, :insane => true).should == 'bits = (bits | 3) - 0'
325
- end
326
-
327
- it "unsets multiple bits" do
328
- User.set_bitfield_sql(:seller => false, :insane => false).should == 'bits = (bits | 3) - 3'
329
- end
330
-
331
- it "sets and unsets in one command" do
332
- User.set_bitfield_sql(:seller => false, :insane => true).should == 'bits = (bits | 3) - 1'
333
- end
334
-
335
- it "sets and unsets for multiple columns in one sql" do
336
- sql = MultiBitUser.set_bitfield_sql(:seller => false, :insane => true, :one => true, :two => false)
337
- sql.should == "bits = (bits | 3) - 1, more_bits = (more_bits | 3) - 2"
338
- end
339
-
340
- it "produces working sql" do
341
- u = MultiBitUser.create!(:seller => true, :insane => true, :stupid => false, :one => true, :two => false, :four => false)
342
- sql = MultiBitUser.set_bitfield_sql(:seller => false, :insane => true, :one => true, :two => false)
343
- MultiBitUser.update_all(sql)
344
- u.reload
345
- u.seller.should == false
346
- u.insane.should == true
347
- u.stupid.should == false
348
- u.one.should == true
349
- u.two.should == false
350
- u.four.should == false
351
- end
352
- end
353
-
354
- describe 'named scopes' do
355
- before do
356
- @u1 = User.create!(:seller => true, :insane => false)
357
- @u2 = User.create!(:seller => true, :insane => true)
358
- end
359
-
360
- it "creates them when nothing was passed" do
361
- User.respond_to?(:seller).should == true
362
- User.respond_to?(:not_seller).should == true
363
- end
364
-
365
- it "does not create them when false was passed" do
366
- UserWithoutScopes.respond_to?(:seller).should == false
367
- UserWithoutScopes.respond_to?(:not_seller).should == false
368
- end
369
-
370
- it "produces working positive scopes" do
371
- User.insane.seller.to_a.should == [@u2]
372
- end
373
-
374
- it "produces working negative scopes" do
375
- User.not_insane.seller.to_a.should == [@u1]
376
- end
377
- end
378
-
379
- describe 'overwriting' do
380
- it "does not change base class" do
381
- OverwrittenUser.bitfields[:bits][:seller_inherited].should_not == nil
382
- User.bitfields[:bits][:seller_inherited].should == nil
383
- end
384
-
385
- it "has inherited methods" do
386
- User.respond_to?(:seller).should == true
387
- OverwrittenUser.respond_to?(:seller).should == true
388
- end
389
- end
390
-
391
- describe 'inheritance' do
392
- it "knows overwritten values and normal" do
393
- User.bitfields.should == {:bits=>{:seller=>1, :insane=>2, :stupid=>4}}
394
- OverwrittenUser.bitfields.should == {:bits=>{:seller_inherited=>1}}
395
- end
396
-
397
- it "knows overwritten values when overwriting" do
398
- OverwrittenUser.bitfield_column(:seller_inherited).should == :bits
399
- end
400
-
401
- it "does not know old values when overwriting" do
402
- expect{
403
- OverwrittenUser.bitfield_column(:seller)
404
- }.to raise_error
405
- end
406
-
407
- it "knows inherited values without overwriting" do
408
- InheritedUser.bitfield_column(:seller).should == :bits
409
- end
410
-
411
- it "has inherited scopes" do
412
- InheritedUser.should respond_to(:not_seller)
413
- end
414
-
415
- it "has inherited methods" do
416
- InheritedUser.new.should respond_to(:seller?)
417
- end
418
-
419
- it "knows grandchild inherited values without overwriting" do
420
- GrandchildInheritedUser.bitfield_column(:seller).should == :bits
421
- end
422
-
423
- it "inherits no bitfields for a user without bitfields set" do
424
- InheritedUserWithoutSetBitfield.bitfields.should be_nil
425
- end
426
- end
427
-
428
- describe 'initializers' do
429
- it "sets defaults" do
430
- pending_if(ActiveRecord::VERSION::MAJOR == 2) do
431
- InitializedUser.new.seller.should == true
432
- InitializedUser.new.insane.should == false
433
- end
434
- end
435
-
436
- it "can overwrite defaults in new" do
437
- pending_if(ActiveRecord::VERSION::MAJOR != 2) do
438
- InitializedUser.new(:seller => false).seller.should == false
439
- InitializedUser.new(:insane => true).insane.should == true
440
- end
441
- end
442
- end
443
-
444
- describe "rspec matchers" do
445
- subject { User.new }
446
-
447
- it { should have_a_bitfield :seller }
448
- it { should_not have_a_bitfield :pickle_eater }
449
- end
450
- end
@@ -1,16 +0,0 @@
1
- require 'active_record'
2
-
3
- # connect
4
- ActiveRecord::Base.establish_connection(
5
- :adapter => "sqlite3",
6
- :database => ":memory:"
7
- )
8
-
9
- # create tables
10
- ActiveRecord::Schema.verbose = false
11
- ActiveRecord::Schema.define(:version => 1) do
12
- create_table :users do |t|
13
- t.integer :bits, :default => 0, :null => false
14
- t.integer :more_bits, :default => 0, :null => false
15
- end
16
- end
@@ -1,14 +0,0 @@
1
- require 'rubygems'
2
- if ENV['VERSION']
3
- gem 'activerecord', ENV['VERSION']
4
- gem 'activesupport', ENV['VERSION']
5
- end
6
- $LOAD_PATH << 'lib'
7
- require 'bitfields/rspec'
8
- require 'bitfields'
9
- require 'timeout'
10
-
11
- require 'active_record'
12
- puts "Using ActiveRecord #{ActiveRecord::VERSION::STRING}"
13
-
14
- require File.expand_path('../database', __FILE__)