bitswitch 1.0.5 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,7 +5,7 @@ require 'bitswitch/version'
5
5
 
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "bitswitch"
8
- gem.version = Bitswitch::VERSION
8
+ gem.version = KellyLSB::BitSwitch::VERSION
9
9
  gem.authors = ["Kelly Becker"]
10
10
  gem.email = ["kellylsbkr@gmail.com"]
11
11
  gem.description = "Have you ever wanted to store multiple true/false values in your database, but annoyed with how many fields your tables have, then BitSwitcher is good for you. By assigning a bit for each true/false you can store all your fields in one integer."
@@ -1,103 +1,176 @@
1
+ require 'bitswitch/version'
2
+
1
3
  class BitSwitch
2
4
 
3
- def initialize(n = 0, labels = {})
5
+ def initialize(input = 0, labels = {})
6
+
7
+ # Placeholder
8
+ @labels = {}
9
+ @val = 0
4
10
 
5
- if n.is_a?(Hash)
11
+ # Validate the value input
12
+ unless input.is_a?(Fixnum) || input.is_a?(Hash)
13
+ raise KellyLSB::BitSwitch::Error,
14
+ "BitSwitch: BitSwitch can only accept an instance of `Fixnum` or `Hash` as the first argument"
15
+ end
6
16
 
7
- # Set default values
8
- @labels = {}
9
- @val = 0
17
+ # Validate the labels input
18
+ unless labels.is_a?(Hash)
19
+ raise KellyLSB::BitSwitch::Error,
20
+ "BitSwitch: BitSwitch expected the second argument to be a `Hash`"
21
+ end
10
22
 
11
- if labels.empty?
12
- # Loop through the hash and set the switches
13
- i=0; n.each do |label, tf|
14
- self[i] = tf ? 1 : 0
15
- @labels[i] = label.to_s
16
- i += 1
23
+ # Validate hash value input
24
+ if input.is_a?(Hash)
25
+ input.each do |label, value|
26
+
27
+ # Require a String, Symbol or Fixnum value for input hash keys
28
+ unless label.is_a?(String) || label.is_a?(Symbol) || label.is_a?(Fixnum)
29
+ raise KellyLSB::BitSwitch::Error,
30
+ "BitSwitch: Input Hash keys must be a String, Symbol or Fixnum representation of the bit."
17
31
  end
18
- else
19
- # Set the switches
20
- @labels = labels
21
32
 
22
- n.each do |label, tf|
23
- self[label.to_s] = tf ? 1 : 0
33
+ # Require input hash values to be true or false
34
+ unless value === true || value === false
35
+ raise KellyLSB::BitSwitch::Error,
36
+ "BitSwitch: Input Hash values must be either true or false."
24
37
  end
25
38
  end
39
+ end
40
+
41
+ # Validate label hash format
42
+ labels.each do |bit, label|
26
43
 
27
- # Return the BitSwitch object
28
- return self
44
+ # Require label bits to be Fixnum
45
+ unless bit.is_a?(Fixnum)
46
+ raise KellyLSB::BitSwitch::Error,
47
+ "BitSwitch: Label Hash keys must be instances of Fixnum"
48
+ end
49
+
50
+ # Require labels to be Strings or Symbols
51
+ unless label.is_a?(String) || label.is_a?(Symbol)
52
+ raise KellyLSB::BitSwitch::Error,
53
+ "BitSwitch: Label Hash values must be either Symbols or Strings"
54
+ end
29
55
  end
30
56
 
31
- # Set labels and initial number
32
- @labels = labels
33
- @val = n
57
+ # Apply label hash into the instance variable and assume 0
58
+ @labels = labels.inject({}){|h, (k, v)|h.merge(k => v.to_sym)}
59
+ @val = input.is_a?(Hash) ? 0 : input
60
+
61
+ # Handle hash input
62
+ if input.is_a?(Hash)
63
+
64
+ # If no labels are set
65
+ # Loop through the input and set the values
66
+ input.each_with_index { |(label, value), index|
67
+ @labels[index] = label.to_sym
68
+ self[index] = value
69
+ } if @labels.empty?
70
+
71
+ # Otherwise just set
72
+ input.each { |label, value|
73
+ self[label] = value
74
+ } unless @labels.empty?
75
+ end
34
76
  end
35
77
 
36
- # Set a bit
78
+ # Set a bit (or label)
37
79
  def []=(bit, val)
38
- val = val == true if val.is_a?(TrueClass)
80
+
81
+ # Validate input label / bit
82
+ unless bit.is_a?(Symbol) || bit.is_a?(String) || bit.is_a?(Fixnum)
83
+ raise KellyLSB::BitSwitch::Error,
84
+ "BitSwitch (#{__method__}): Expected the key to be a Symbol, String or Fixnum"
85
+ end
86
+
87
+ # Validate input value
88
+ unless val === true || val === false || val.is_a?(Fixnum)
89
+ raise KellyLSB::BitSwitch::Error,
90
+ "BitSwitch (#{__method__}): Expected the value to be true, false or Fixnum"
91
+ end
92
+
93
+ # Convert numerical to boolean
39
94
  val = val > 0 if val.is_a?(Fixnum)
40
95
 
41
- # If a string representation of a bit was provided get the numerical
42
- bit = bit.to_s if bit.is_a?(Symbol)
43
- bit = @labels.invert[bit] if bit.is_a?(String)
96
+ # Get the numerical representation of the label
97
+ bit = @labels.invert[bit.to_sym] unless bit.is_a?(Fixnum)
44
98
 
45
99
  # If nil return false
46
- return false if bit.nil?
47
-
100
+ if bit.nil?
101
+ raise KellyLSB::BitSwitch::Error,
102
+ "BitSwitch (#{__method__}): There was no bit to match the requested label."
103
+ end
104
+
48
105
  # Set/Unset the bits
49
106
  @val |= 2 ** bit if val
50
107
  @val &= ~(2 ** bit) if !val && self[bit]
51
108
 
52
109
  # Return self
53
- return self
110
+ self
54
111
  end
55
-
112
+
56
113
  # Check a bit status
57
114
  def [](bit)
58
115
 
59
- # If a string representation of a bit was provided get the numerical
60
- bit = bit.to_s if bit.is_a?(Symbol)
61
- bit = @labels.invert[bit] if bit.is_a?(String)
116
+ # Validate input label / bit
117
+ unless bit.is_a?(Symbol) || bit.is_a?(String) || bit.is_a?(Fixnum)
118
+ raise KellyLSB::BitSwitch::Error,
119
+ "BitSwitch (#{__method__}): Expected the key to be a Symbol, String or Fixnum"
120
+ end
121
+
122
+ # Get the numerical representation of the label
123
+ bit = @labels.invert[bit.to_sym] unless bit.is_a?(Fixnum)
62
124
 
63
125
  # If nil return false
64
- return false if bit.nil?
126
+ if bit.nil?
127
+ raise KellyLSB::BitSwitch::Error,
128
+ "BitSwitch (#{__method__}): There was no bit to match the requested label."
129
+ end
65
130
 
66
- # Check if the bit it set
131
+ # Check if the bit was set
67
132
  (2 ** bit) & @val > 0
68
133
  end
69
-
134
+
70
135
  # Set an integer
71
- def set=(n)
72
- return false unless n.is_a?(Fixnum)
73
- @val = n
136
+ def set=(input)
137
+
138
+ # Validate input
139
+ unless input.is_a?(Fixnum)
140
+ raise KellyLSB::BitSwitch::Error,
141
+ "BitSwitch (#{__method__}): Expected value to be a Fixnum"
142
+ end
143
+
144
+ # Set the value
145
+ @val = input
146
+
147
+ # Return self
148
+ self
74
149
  end
75
150
 
76
151
  def labels(hash = {}, reset = false)
77
152
 
78
- # If reset is false then merge the labels
79
- unless reset
80
- @labels.merge!(hash)
81
- return self
82
- end
83
-
84
- # Set a whole new label hash
85
- @labels = hash
153
+ # Either merge or overwrite labels
154
+ @labels.merge!(hash) unless reset
155
+ @labels = hash if reset
86
156
 
87
157
  # Return self
88
- return self
158
+ self
89
159
  end
90
-
91
- # Convert to integer
160
+
161
+ # Get value
92
162
  def to_i
93
163
  @val
94
164
  end
95
165
 
96
- # Convert to hash
166
+ # Get hash
97
167
  def to_hash
98
168
 
99
- # Raise an error if no labels are set
100
- raise StandardError, "No labels were set!" if @labels.empty?
169
+ # Make sure labels are set
170
+ if @labels.empty?
171
+ raise KellyLSB::BitSwitch::Error,
172
+ "BitSwitch (#{__method__}): No labels were set!"
173
+ end
101
174
 
102
175
  # Prepare new hash
103
176
  serialized = Hash.new
@@ -107,17 +180,20 @@ class BitSwitch
107
180
  serialized[label] = self[bit]
108
181
  end
109
182
 
110
- # Return the serialized BitSwitch
183
+ # Return serialization
111
184
  serialized
112
185
  end
113
186
 
114
- # Method missing for args access
187
+ # Method access
115
188
  def method_missing(method, *args)
189
+
190
+ # Handle setting values
116
191
  if method[-1] == '='
117
192
  method = method[0..-2]
118
193
  return self[method] = args.first
119
194
  end
120
-
195
+
196
+ # Return a value
121
197
  self[method]
122
198
  end
123
199
  end
@@ -132,7 +208,15 @@ end
132
208
  # Convert hash of booleans to Switch
133
209
  class Hash
134
210
  def to_switch(labels = {})
135
- cleaned = self.delete_if{|k,v| ![true, false].include?(v)}
211
+
212
+ # Remove any non boolean values
213
+ cleaned = self.delete_if{|k,v| ![true, false, 1, 0, '1', '0'].include?(v)}
214
+
215
+ # Convert Numerical Booleans
216
+ cleaned.collect!{|k,v|(v.is_a?(String) ? v.to_i : v)}
217
+ cleaned.collect!{|k,v|(v.is_a?(Fixnum) ? !v.zero? : v)}
218
+
219
+ # Return new BitSwitch
136
220
  return BitSwitch.new(0, labels) if cleaned.empty?
137
221
  return BitSwitch.new(cleaned, labels)
138
222
  end
@@ -148,7 +232,7 @@ if defined? ActiveRecord::Base
148
232
  def bitswitch(column, hash = {})
149
233
  columne = column.to_s + '='
150
234
  send(:include, Module.new {
151
- send(:define_method, column.to_sym) do |*args|
235
+ send(:define_method, column) do |*args|
152
236
  val = read_attribute(column)
153
237
 
154
238
  # If nil make 0
@@ -167,19 +251,46 @@ if defined? ActiveRecord::Base
167
251
  return val
168
252
  end
169
253
 
170
- send(:define_method, columne.to_sym) do |input|
254
+ send(:define_method, columne) do |args|
171
255
  val = read_attribute(column)
172
256
 
173
257
  # If nil make 0
174
258
  val = 0 if val.nil?
175
259
 
260
+ # Get the input data
261
+ if args.is_a?(Array)
262
+ input = args[0]
263
+ truncate = args[1]
264
+ else
265
+ input = args
266
+ truncate = false
267
+ end
268
+
176
269
  # Make sure the value is an integer
177
270
  raise KellyLSB::BitSwitch::Error, "Column: #{column} is not an integer!" unless val.is_a?(Fixnum)
178
271
 
179
- # Get the BitSwitch
180
- val = val.to_switch(hash).to_hash.merge(input).to_switch(hash)
272
+ # Make sure the first input is a hash
273
+ raise KellyLSB::BitSwitch::Error, "Input: We are expecting at least one argument that is a Hash" unless input.is_a?(Hash)
274
+
275
+ # Get the BitSwitch as a Hash
276
+ val = val.to_switch(hash).to_hash
277
+
278
+ # If a second argument was passed and was true set all other keys to false
279
+ if truncate == true
181
280
 
182
- # Dont save if it cant save
281
+ # Get list of unset keys
282
+ remove = val.keys.collect(&:to_s) - input.keys.collect(&:to_s)
283
+
284
+ # Set those keys to false
285
+ for key in remove
286
+ input[key] = false
287
+ end
288
+ end
289
+
290
+ # Merge in the changes
291
+ val = val.merge(input).to_switch(hash)
292
+
293
+ # Dont save if this is a new model
183
294
  return false if read_attribute(:id).nil?
184
295
 
185
296
  # Write the updated value
@@ -191,7 +302,7 @@ if defined? ActiveRecord::Base
191
302
  })
192
303
 
193
304
  send(:extend, Module.new {
194
- send(:define_method, column.to_sym) do |*args|
305
+ send(:define_method, column) do |*args|
195
306
  raise KellyLSB::BitSwitch::Error, "Missing arguments!" if args.empty?
196
307
  bits = hash.invert
197
308
 
@@ -231,4 +342,4 @@ if defined? ActiveRecord::Base
231
342
  end
232
343
 
233
344
  ActiveRecord::Base.send(:include, KellyLSB::BitSwitch)
234
- end
345
+ end
@@ -1,3 +1,11 @@
1
- module Bitswitch
2
- VERSION = "1.0.5"
1
+ module KellyLSB
2
+ module BitSwitch
3
+
4
+ # Error class
5
+ class Error < StandardError
6
+ end
7
+
8
+ # Version of the gem
9
+ VERSION = "1.1.0"
10
+ end
3
11
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitswitch
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-09 00:00:00.000000000 Z
12
+ date: 2013-01-29 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Have you ever wanted to store multiple true/false values in your database,
15
15
  but annoyed with how many fields your tables have, then BitSwitcher is good for