bitfields 0.1.4 → 0.1.5

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.
data/README.markdown CHANGED
@@ -38,6 +38,10 @@ Update all users
38
38
  Delete the shop when a user is no longer a seller
39
39
  before_save :delete_shop, :if => lambda{|u| u.changes['seller'] == [true, false]}
40
40
 
41
+ TODO
42
+ ====
43
+ - convenient named scope `User.with_bitfields(:xxx=>true, :yy=>false)`
44
+
41
45
  Author
42
46
  ======
43
47
  [Michael Grosser](http://pragmatig.wordpress.com)
data/Rakefile CHANGED
@@ -1,16 +1,11 @@
1
- require 'spec/rake/spectask'
2
- Spec::Rake::SpecTask.new {|t| t.spec_opts = ['--color']}
1
+ require "rspec/core/rake_task"
2
+ RSpec::Core::RakeTask.new(:spec) do |t|
3
+ t.rspec_opts = '--backtrace --color'
4
+ end
3
5
 
4
6
  task :default do
5
- # test with 2.x
6
- puts `VERSION='~>2' rake spec`
7
-
8
- # gem 'activerecord', '>=3' did not work for me, but just require gets the right version...
9
- require 'active_record'
10
- if ActiveRecord::VERSION::MAJOR >= 3
11
- puts `rake spec`
12
- else
13
- 'install rails 3 to get full test coverage...'
7
+ [2,3].each do |version|
8
+ sh "VERSION='~>#{version}' rake spec" rescue nil
14
9
  end
15
10
  end
16
11
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.4
1
+ 0.1.5
data/benchmark/1.rb ADDED
@@ -0,0 +1,144 @@
1
+ bit_counts = [2,3,4,5,6,7,8,9,10,11,12,13,14]
2
+ record_counts = (1..20).to_a.map{|i| i * 50_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
+ # puts sql[0..100]
84
+ time = benchmark do
85
+ User.count sql
86
+ end
87
+ puts "#{bit_count} -> #{time}"
88
+ [bit_count, time]
89
+ end
90
+ Hash[result]
91
+ end
92
+
93
+ #determines a unique color based on a name
94
+ def color_for(name)
95
+ name = name.inspect + "some randomness for fun"
96
+ hash = (name.hash % 1_000_000_000).to_s #get a hash of a constant size
97
+ colors = [hash[0..1], hash[2..3], hash[4..5]].map{|c| c.to_f / 100.0 * 16} #use 3 parts of the hash to get numbers from 0 to 15.99
98
+ palette = ('0'..'9').to_a + ('a'..'f').to_a #hex values 0..f
99
+ colors.map{|c| palette[c.floor].to_s * 2} * '' #each color is duplicated and the joined
100
+ end
101
+
102
+ connect(database)
103
+ create_model_table(bit_counts, use_index)
104
+ class User < ActiveRecord::Base
105
+ end
106
+ create_model_fields(bit_counts)
107
+
108
+ puts "creating test data"
109
+ last = 0
110
+
111
+ graphs = {:bit => {}, :in => {}}
112
+ data = record_counts.map do |record_count|
113
+ create(bit_counts, record_count-last)
114
+ puts User.count
115
+ last = record_count
116
+
117
+ puts "testing with #{record_count} records -- bit_operator"
118
+ graphs[:bit][record_count] = test_speed(bit_counts, :bit_operator)
119
+
120
+ puts "testing with #{record_count} records -- in_list"
121
+ graphs[:in][record_count] = test_speed(bit_counts, :in_list)
122
+
123
+ end
124
+
125
+ colors = {:bit => '00xx00', :in => 'xx0000'}
126
+ alpha_num = (('0'..'9').to_a + ('a'..'f').to_a).reverse
127
+ title = "bit-operator vs IN() -- #{use_index ? 'with' : 'without'} index"
128
+ url = GoogleChart::LineChart.new('600x500', title, false) do |line|
129
+ max = 0
130
+ graphs.each do |type, line_data|
131
+ bit_counts.each do |bit_count|
132
+ data = record_counts.map{|rc| line_data[rc][bit_count] }
133
+ name = "#{bit_count}bits (#{type})"
134
+ color = colors[type].sub('xx', alpha_num[bit_count]*2)
135
+ line.data(name, data, color)
136
+ max = [data.max, max].max
137
+ end
138
+ end
139
+
140
+ line.axis :x, :labels => record_counts.map{|c|"#{c/1000}K"}
141
+ line.axis :y, :labels => ['0', "%.3f" % [max*100]]
142
+ end.to_url
143
+
144
+ puts url
data/bitfields.gemspec CHANGED
@@ -1,45 +1,44 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{bitfields}
8
- s.version = "0.1.4"
8
+ s.version = "0.1.5"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Michael Grosser"]
12
- s.date = %q{2010-04-25}
12
+ s.date = %q{2011-01-19}
13
13
  s.email = %q{grosser.michael@gmail.com}
14
14
  s.extra_rdoc_files = [
15
15
  "README.markdown"
16
16
  ]
17
17
  s.files = [
18
18
  "README.markdown",
19
- "Rakefile",
20
- "VERSION",
21
- "bitfields.gemspec",
22
- "lib/bitfields.rb",
23
- "spec/bitfields_spec.rb",
24
- "spec/database.rb",
25
- "spec/spec_helper.rb"
19
+ "Rakefile",
20
+ "VERSION",
21
+ "benchmark/1.rb",
22
+ "bitfields.gemspec",
23
+ "lib/bitfields.rb",
24
+ "spec/bitfields_spec.rb",
25
+ "spec/database.rb",
26
+ "spec/spec_helper.rb"
26
27
  ]
27
28
  s.homepage = %q{http://github.com/grosser/bitfields}
28
- s.rdoc_options = ["--charset=UTF-8"]
29
29
  s.require_paths = ["lib"]
30
- s.rubygems_version = %q{1.3.6}
30
+ s.rubygems_version = %q{1.4.2}
31
31
  s.summary = %q{Save migrations and columns by storing multiple booleans in a single integer.}
32
32
  s.test_files = [
33
- "spec/spec_helper.rb",
34
- "spec/bitfields_spec.rb",
35
- "spec/database.rb"
33
+ "spec/bitfields_spec.rb",
34
+ "spec/database.rb",
35
+ "spec/spec_helper.rb"
36
36
  ]
37
37
 
38
38
  if s.respond_to? :specification_version then
39
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
40
39
  s.specification_version = 3
41
40
 
42
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
41
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
43
42
  else
44
43
  end
45
44
  else
data/lib/bitfields.rb CHANGED
@@ -58,20 +58,20 @@ module Bitfields
58
58
  found.first
59
59
  end
60
60
 
61
- def bitfield_sql(bit_values)
62
- bits = group_bits_by_column(bit_values)
63
- bits.map{|column, bit_values| bitfield_sql_by_column(column, bit_values) } * ' AND '
61
+ def bitfield_sql(bit_values, options={})
62
+ bits = group_bits_by_column(bit_values).sort_by{|c,v| c.to_s }
63
+ bits.map{|column, bit_values| bitfield_sql_by_column(column, bit_values, options) } * ' AND '
64
64
  end
65
65
 
66
66
  def set_bitfield_sql(bit_values)
67
- columns = group_bits_by_column(bit_values)
68
- columns.map{|column, bit_values| set_bitfield_sql_by_column(column, bit_values) } * ', '
67
+ bits = group_bits_by_column(bit_values).sort_by{|c,v| c.to_s }
68
+ bits.map{|column, bit_values| set_bitfield_sql_by_column(column, bit_values) } * ', '
69
69
  end
70
70
 
71
71
  private
72
72
 
73
- def bitfield_sql_by_column(column, bit_values)
74
- mode = (bitfield_options[column][:query_mode] || :in_list)
73
+ def bitfield_sql_by_column(column, bit_values, options={})
74
+ mode = options[:query_mode] || (bitfield_options[column][:query_mode] || :in_list)
75
75
  case mode
76
76
  when :in_list then
77
77
  max = (bitfields[column].values.max * 2) - 1
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitfields
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
4
+ hash: 17
5
+ prerelease:
5
6
  segments:
6
7
  - 0
7
8
  - 1
8
- - 4
9
- version: 0.1.4
9
+ - 5
10
+ version: 0.1.5
10
11
  platform: ruby
11
12
  authors:
12
13
  - Michael Grosser
@@ -14,7 +15,7 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-04-25 00:00:00 +02:00
18
+ date: 2011-01-19 00:00:00 +01:00
18
19
  default_executable:
19
20
  dependencies: []
20
21
 
@@ -30,6 +31,7 @@ files:
30
31
  - README.markdown
31
32
  - Rakefile
32
33
  - VERSION
34
+ - benchmark/1.rb
33
35
  - bitfields.gemspec
34
36
  - lib/bitfields.rb
35
37
  - spec/bitfields_spec.rb
@@ -40,32 +42,36 @@ homepage: http://github.com/grosser/bitfields
40
42
  licenses: []
41
43
 
42
44
  post_install_message:
43
- rdoc_options:
44
- - --charset=UTF-8
45
+ rdoc_options: []
46
+
45
47
  require_paths:
46
48
  - lib
47
49
  required_ruby_version: !ruby/object:Gem::Requirement
50
+ none: false
48
51
  requirements:
49
52
  - - ">="
50
53
  - !ruby/object:Gem::Version
54
+ hash: 3
51
55
  segments:
52
56
  - 0
53
57
  version: "0"
54
58
  required_rubygems_version: !ruby/object:Gem::Requirement
59
+ none: false
55
60
  requirements:
56
61
  - - ">="
57
62
  - !ruby/object:Gem::Version
63
+ hash: 3
58
64
  segments:
59
65
  - 0
60
66
  version: "0"
61
67
  requirements: []
62
68
 
63
69
  rubyforge_project:
64
- rubygems_version: 1.3.6
70
+ rubygems_version: 1.4.2
65
71
  signing_key:
66
72
  specification_version: 3
67
73
  summary: Save migrations and columns by storing multiple booleans in a single integer.
68
74
  test_files:
69
- - spec/spec_helper.rb
70
75
  - spec/bitfields_spec.rb
71
76
  - spec/database.rb
77
+ - spec/spec_helper.rb