bitfields 0.11.0 → 0.12.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dc824cf59452e64b1e34422e7416920dd725ea7d
4
- data.tar.gz: 78a184dd4eda1d311ef1246f089babc00711a22b
3
+ metadata.gz: cf9f6971a5470e30369fcfa61814a7533ac62b89
4
+ data.tar.gz: 559897cbd82a915ae89b0a462da4e40d8f8d9a3a
5
5
  SHA512:
6
- metadata.gz: 1e3d053623af2a5c60eb9d1818849d72b9e1d66801d2c9bb07fa12a63462770614f3a87e7b802470ca5cfd7609a0aab167d5fa2b3032c2477bdc7c48c86653ae
7
- data.tar.gz: c45ced97d18462bf25ddfa2b4221b26e69ea1b75f293c6b200c457a415697c144f14d0c00e72dd781a24214f5e3b7e16236397103a8329a482a6a75eb4219726
6
+ metadata.gz: dd96cded51293734f1dc013966f26a42d90710efb082f628076728e96425a31011c6cfd8a964d9cb0aa7bdc7f63d2669e6655eb96a37423fddf978aaa35027fc
7
+ data.tar.gz: b68f9ec05b94f11ead65c5690a19f72199dc50b0d3434e82d3a202c9c22a9a5f7793a195310c28123b334f87c4fc6213643ac1fb196dd188e61d114ee03d695d
data/Readme.md CHANGED
@@ -17,7 +17,7 @@ user.my_bits # => 3
17
17
  - Individual added methods (i.e, `seller_was`, `seller_changed?`, etc..) can be deactivated with `bitfield ..., added_instance_methods: false`
18
18
  - **Note**: ActiveRecord 5.2 changes the behavior of `_was` and `_changed?` methods when used in the context of an `after_save` callback.
19
19
  - ActiveRecord 5.1 will use the use the values that were _just_ changed.
20
- - ActiveRecord 5.2, however, will return `nil` for `_was` and `false` for `_changed?` since the previous changes have been persisted.
20
+ - ActiveRecord 5.2, however, will return the current value for `_was` and `false` for `_changed?` since the previous changes have been persisted.
21
21
  - adds scopes `User.seller.sensible.first` (deactivate with `bitfield ..., scopes: false`)
22
22
  - builds sql `User.bitfield_sql(insane: true, sensible: false) # => '(users.my_bits & 6) = 1'`
23
23
  - builds sql with OR condition `User.bitfield_sql({ insane: true, sensible: true }, query_mode: :bit_operator_or) # => '(users.my_bits & 2) = 2 OR (users.bits & 4) = 4'`
@@ -25,18 +25,6 @@ user.my_bits # => 3
25
25
  - builds update sql `User.set_bitfield_sql(insane: true, sensible: false) == 'my_bits = (my_bits | 6) - 4'`
26
26
  - **faster sql than any other bitfield lib** through combination of multiple bits into a single sql statement
27
27
  - gives access to bits `User.bitfields[:my_bits][:sensible] # => 4`
28
- - [`ActiveRecord::AttributeMethods::Dirty`](https://api.rubyonrails.org/v5.1.7/classes/ActiveRecord/AttributeMethods/Dirty.html) and [`ActiveModel::Dirty`](https://api.rubyonrails.org/v5.1.7/classes/ActiveModel/Dirty.html) methods can be used on each bitfield:
29
- ```ruby
30
- user = User.new(seller: false)
31
- user.seller = true
32
- user.will_save_change_to_seller? # => true
33
- user.seller_change_to_be_saved # => [false, true]
34
-
35
- user.save
36
-
37
- user.seller_before_last_save # => false
38
- user.saved_change_to_seller # => [false, true]
39
- ```
40
28
 
41
29
  Install
42
30
  =======
@@ -54,6 +42,49 @@ t.integer :my_bits, default: 0, null: false
54
42
  add_column :users, :my_bits, :integer, default: 0, null: false
55
43
  ```
56
44
 
45
+ Instance Methods
46
+ ================
47
+
48
+ ### Global Bitfield Methods
49
+ | Method Name | Example (`user = User.new(seller: true, insane: true`) | Result |
50
+ |--------------------|---------------------------------------------------------|-------------------------------------------------------------|
51
+ | `bitfield_values` | `user.bitfield_values` | `{"seller" => true, "insane" => true, "sensible" => false}` |
52
+ | `bitfield_changes` | `user.bitfield_changes` | `{"seller" => [false, true], "insane" => [false, true]}` |
53
+
54
+ ### Individual Bit Methods
55
+ #### Model Getters / Setters
56
+ | Method Name | Example (`user = User.new`) | Result |
57
+ |----------------|-----------------------------|---------|
58
+ | `#{bit_name}` | `user.seller` | `false` |
59
+ | `#{bit_name}=` | `user.seller = true` | `true` |
60
+ | `#{bit_name}?` | `user.seller?` | `true` |
61
+
62
+ #### Dirty Methods:
63
+
64
+ Some, not all, [`ActiveRecord::AttributeMethods::Dirty`](https://api.rubyonrails.org/v5.1.7/classes/ActiveRecord/AttributeMethods/Dirty.html) and [`ActiveModel::Dirty`](https://api.rubyonrails.org/v5.1.7/classes/ActiveModel/Dirty.html) methods can be used on each bitfield:
65
+
66
+ ##### Before Model Persistence
67
+ | Method Name | Example (`user = User.new`) | Result |
68
+ |------------------------------------|------------------------------------|-----------------|
69
+ | `#{bit_name}_was` | `user.seller_was` | `false` |
70
+ | `#{bit_name}_in_database` | `user.seller_in_database` | `false` |
71
+ | `#{bit_name}_change` | `user.seller_change` | `[false, true]` |
72
+ | `#{bit_name}_change_to_be_saved` | `user.seller_change_to_be_saved` | `[false, true]` |
73
+ | `#{bit_name}_changed?` | `user.seller_changed?` | `true` |
74
+ | `will_save_change_to_#{bit_name}?` | `user.will_save_change_to_seller?` | `true` |
75
+ | `#{bit_name}_became_true?` | `user.seller_became_true?` | `true` |
76
+ | `#{bit_name}_became_false?` | `user.seller_became_false?` | `false` |
77
+
78
+
79
+ ##### After Model Persistence
80
+ | Method Name | Example (`user = User.create(seller: true)`) | Result |
81
+ |--------------------------------|---------------------------------------------------|-----------------|
82
+ | `#{bit_name}_before_last_save` | `user.seller_before_last_save` | `false` |
83
+ | `saved_change_to_#{bit_name}` | `user.saved_change_to_seller` | `[false, true]` |
84
+ | `saved_change_to_#{bit_name}?` | `user.saved_change_to_seller?` | `true` |
85
+
86
+ - **Note**: These methods are dynamically defined for each bitfield, and function separately from the real `ActiveRecord::AttributeMethods::Dirty`/`ActiveModel::Dirty` methods. As such, generic methods (e.g. `attribute_before_last_save(:attribute)`) will not work.
87
+
57
88
  Examples
58
89
  ========
59
90
  Update all users
@@ -120,6 +151,9 @@ Authors
120
151
  - [szTheory](https://github.com/szTheory)
121
152
  - [Reed G. Law](https://github.com/reedlaw)
122
153
  - [Rael Gugelmin Cunha](https://github.com/reedlaw)
154
+ - [Alan Wong](https://github.com/naganowl)
155
+ - [Andrew Bates](https://github.com/a-bates)
156
+ - [Shirish Pampoorickal](https://github.com/shirish-pampoorickal)
123
157
 
124
158
  [Michael Grosser](http://grosser.it)<br/>
125
159
  michael@grosser.it<br/>
@@ -82,11 +82,19 @@ module Bitfields
82
82
  def add_bitfield_methods(column, options)
83
83
  bitfields[column].keys.each do |bit_name|
84
84
  if options[:added_instance_methods] != false
85
- attribute bit_name, :boolean, default: false
86
-
87
85
  define_method(bit_name) { bitfield_value(bit_name) }
88
86
  define_method("#{bit_name}?") { bitfield_value(bit_name) }
89
- define_method("#{bit_name}=") { |value| super(value); set_bitfield_value(bit_name, value) }
87
+ define_method("#{bit_name}=") { |value| set_bitfield_value(bit_name, value) }
88
+
89
+ # Dirty methods usable in before_save contexts
90
+ define_method("#{bit_name}_was") { bitfield_value_was(bit_name) }
91
+ alias_method "#{bit_name}_in_database", "#{bit_name}_was"
92
+
93
+ define_method("#{bit_name}_change") { bitfield_value_change(bit_name) }
94
+ alias_method "#{bit_name}_change_to_be_saved", "#{bit_name}_change"
95
+
96
+ define_method("#{bit_name}_changed?") { bitfield_value_change(bit_name).present? }
97
+ alias_method "will_save_change_to_#{bit_name}?", "#{bit_name}_changed?"
90
98
 
91
99
  define_method("#{bit_name}_became_true?") do
92
100
  value = bitfield_value(bit_name)
@@ -96,6 +104,11 @@ module Bitfields
96
104
  value = bitfield_value(bit_name)
97
105
  !value && send("#{bit_name}_was") != value
98
106
  end
107
+
108
+ # Dirty methods usable in after_save contexts
109
+ define_method("#{bit_name}_before_last_save") { bitfield_value_before_last_save(bit_name) }
110
+ define_method("saved_change_to_#{bit_name}") { saved_change_to_bitfield_value(bit_name) }
111
+ define_method("saved_change_to_#{bit_name}?") { saved_change_to_bitfield_value(bit_name).present? }
99
112
  end
100
113
 
101
114
  if options[:scopes] != false
@@ -186,6 +199,25 @@ module Bitfields
186
199
  send("#{column}_was") & bit != 0
187
200
  end
188
201
 
202
+ def bitfield_value_before_last_save(bit_name)
203
+ column, bit, _ = bitfield_info(bit_name)
204
+ column_before_last_save = send("#{column}_before_last_save")
205
+ column_before_last_save.nil? ? nil : column_before_last_save & bit != 0
206
+ end
207
+
208
+ def bitfield_value_change(bit_name)
209
+ values = [bitfield_value_was(bit_name), bitfield_value(bit_name)]
210
+ values unless values[0] == values[1]
211
+ end
212
+
213
+ def saved_change_to_bitfield_value(bit_name)
214
+ value_before_last_save = bitfield_value_before_last_save(bit_name)
215
+ current_value = bitfield_value(bit_name)
216
+ unless value_before_last_save.nil? || (value_before_last_save == current_value)
217
+ [value_before_last_save, current_value]
218
+ end
219
+ end
220
+
189
221
  def set_bitfield_value(bit_name, value)
190
222
  column, bit, current_value = bitfield_info(bit_name)
191
223
  new_value = TRUE_VALUES.include?(value)
@@ -1,3 +1,3 @@
1
1
  module Bitfields
2
- Version = VERSION = "0.11.0"
2
+ Version = VERSION = "0.12.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitfields
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Grosser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-04 00:00:00.000000000 Z
11
+ date: 2019-10-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord