active_record-events 1.0.0 → 1.1.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 +8 -8
- data/README.md +13 -0
- data/lib/active_record/events.rb +15 -22
- data/lib/active_record/events/naming.rb +39 -0
- data/lib/active_record/events/version.rb +1 -1
- data/spec/active_record/events/naming_spec.rb +51 -0
- data/spec/active_record/events_spec.rb +7 -0
- data/spec/dummy/app/models/user.rb +3 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20170103215307_create_users.rb +9 -0
- data/spec/dummy/db/schema.rb +7 -1
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/support/factories.rb +1 -0
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
Njk0YzdlMmY0YzRiMmYxNzdjMmE3OTMyODUwNjIzNjgwZmEzOTZiMg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NDNiMmViY2U5NTNmZmY5ZjQ3NzdkMTY5Mjg4YTlmMTJmMTI3NjI3Yw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
OTlhYzQ1ODkwNjg1ZjNkYjhjZTY3ZTgwZWIyYjgxYTgzNDM1NmJlNmExODEy
|
10
|
+
ZTU1MTYxOTllMDAwNmUwOTM0MTVkM2FlODZlN2ZjNzViOTYzNmFmOTk2NTEw
|
11
|
+
Y2JlNzEzZGUyN2EyMTk4M2Q2YWZiNTQ2ODI5NjAzYWY1ZWMwNjY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YWZmMzdhYjNmODJlMmY5ZDExOGE1ODBjNmQ3NTc4YTJmOWZlMjIwODU0ZTMz
|
14
|
+
MmJiZjU1ZTJlYjQyOWI4NDA3N2U2NzZjYWFkNDAxNTIyYTE0MDEyMWExOWQz
|
15
|
+
YTA0MmE4MGQzNzNjMWQwNjQzZGQzMzJmZTE3YzBmNDBjMzdlMDg=
|
data/README.md
CHANGED
@@ -69,6 +69,19 @@ scope :not_completed, -> { where(completed_at: nil) }
|
|
69
69
|
scope :completed, -> { where.not(completed_at: nil) }
|
70
70
|
```
|
71
71
|
|
72
|
+
### Subject
|
73
|
+
|
74
|
+
There are events which do not relate to a model itself but to one of its attributes – take the `User` model with the `email_confirmed_at` field as an example.
|
75
|
+
In order to keep method names grammatically correct, you can specify a subject using the `subject` option.
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
class User < ActiveRecord::Base
|
79
|
+
has_event :confirm, subject: :email
|
80
|
+
end
|
81
|
+
```
|
82
|
+
|
83
|
+
This will generate `email_confirmed?`, `confirm_email` and `confirm_email!` methods.
|
84
|
+
|
72
85
|
## See also
|
73
86
|
|
74
87
|
- [ActiveRecord::Enum](http://api.rubyonrails.org/classes/ActiveRecord/Enum.html)
|
data/lib/active_record/events.rb
CHANGED
@@ -1,41 +1,34 @@
|
|
1
1
|
require 'active_support'
|
2
|
-
require '
|
2
|
+
require 'active_record/events/naming'
|
3
3
|
|
4
4
|
module ActiveRecord
|
5
5
|
module Events
|
6
|
-
def self.past_participle(infinitive)
|
7
|
-
options = { tense: :past, aspect: :perfective }
|
8
|
-
infinitive.verb.conjugate(options)
|
9
|
-
end
|
10
|
-
|
11
6
|
def has_events(*names)
|
12
|
-
names.
|
7
|
+
options = names.extract_options!
|
8
|
+
names.each { |n| has_event(n, options) }
|
13
9
|
end
|
14
10
|
|
15
|
-
def has_event(name)
|
16
|
-
|
17
|
-
|
18
|
-
past_participle = _module.past_participle(name)
|
19
|
-
field_name = "#{past_participle}_at"
|
11
|
+
def has_event(name, options = {})
|
12
|
+
naming = Naming.new(name, options)
|
20
13
|
|
21
|
-
define_method("#{
|
22
|
-
self[
|
14
|
+
define_method("#{naming.predicate}?") do
|
15
|
+
self[naming.field].present?
|
23
16
|
end
|
24
17
|
|
25
|
-
define_method(
|
26
|
-
touch(
|
18
|
+
define_method(naming.action) do
|
19
|
+
touch(naming.field) if self[naming.field].blank?
|
27
20
|
end
|
28
21
|
|
29
|
-
define_method("#{
|
30
|
-
touch(
|
22
|
+
define_method("#{naming.action}!") do
|
23
|
+
touch(naming.field)
|
31
24
|
end
|
32
25
|
|
33
|
-
define_singleton_method(
|
34
|
-
where(arel_table[
|
26
|
+
define_singleton_method(naming.scope) do
|
27
|
+
where(arel_table[naming.field].not_eq(nil))
|
35
28
|
end
|
36
29
|
|
37
|
-
define_singleton_method(
|
38
|
-
where(arel_table[
|
30
|
+
define_singleton_method(naming.inverse_scope) do
|
31
|
+
where(arel_table[naming.field].eq(nil))
|
39
32
|
end
|
40
33
|
end
|
41
34
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'verbs'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Events
|
5
|
+
class Naming
|
6
|
+
def initialize(infinitive, options = {})
|
7
|
+
@infinitive = infinitive
|
8
|
+
@subject = options[:subject].presence
|
9
|
+
end
|
10
|
+
|
11
|
+
def field
|
12
|
+
[@subject, past_participle, 'at'].compact.join('_')
|
13
|
+
end
|
14
|
+
|
15
|
+
def predicate
|
16
|
+
[@subject, past_participle].compact.join('_')
|
17
|
+
end
|
18
|
+
|
19
|
+
def action
|
20
|
+
[@infinitive, @subject].compact.join('_')
|
21
|
+
end
|
22
|
+
|
23
|
+
def scope
|
24
|
+
[@subject, past_participle].compact.join('_')
|
25
|
+
end
|
26
|
+
|
27
|
+
def inverse_scope
|
28
|
+
[@subject, 'not', past_participle].compact.join('_')
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def past_participle
|
34
|
+
options = { tense: :past, aspect: :perfective }
|
35
|
+
@infinitive.verb.conjugate(options)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe ActiveRecord::Events::Naming do
|
4
|
+
context 'without a subject' do
|
5
|
+
subject { described_class.new(:complete) }
|
6
|
+
|
7
|
+
it 'generates a field name' do
|
8
|
+
expect(subject.field).to eq('completed_at')
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'generates a predicate name' do
|
12
|
+
expect(subject.predicate).to eq('completed')
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'generates an action name' do
|
16
|
+
expect(subject.action).to eq('complete')
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'generates a scope name' do
|
20
|
+
expect(subject.scope).to eq('completed')
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'generates an inverse scope name' do
|
24
|
+
expect(subject.inverse_scope).to eq('not_completed')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'with a subject' do
|
29
|
+
subject { described_class.new(:confirm, subject: :email) }
|
30
|
+
|
31
|
+
it 'generates a field name' do
|
32
|
+
expect(subject.field).to eq('email_confirmed_at')
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'generates a predicate name' do
|
36
|
+
expect(subject.predicate).to eq('email_confirmed')
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'generates an action name' do
|
40
|
+
expect(subject.action).to eq('confirm_email')
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'generates a scope name' do
|
44
|
+
expect(subject.scope).to eq('email_confirmed')
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'generates an inverse scope name' do
|
48
|
+
expect(subject.inverse_scope).to eq('email_not_confirmed')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -28,4 +28,11 @@ RSpec.describe ActiveRecord::Events do
|
|
28
28
|
expect(Task.not_completed).to include(task)
|
29
29
|
expect(Task.completed).not_to include(task)
|
30
30
|
end
|
31
|
+
|
32
|
+
let(:user) { create(:user) }
|
33
|
+
|
34
|
+
it 'handles a subject' do
|
35
|
+
user.confirm_email
|
36
|
+
expect(user.email_confirmed?).to be(true)
|
37
|
+
end
|
31
38
|
end
|
Binary file
|
data/spec/dummy/db/schema.rb
CHANGED
@@ -11,7 +11,7 @@
|
|
11
11
|
#
|
12
12
|
# It's strongly recommended to check this file into your version control system.
|
13
13
|
|
14
|
-
ActiveRecord::Schema.define(:version =>
|
14
|
+
ActiveRecord::Schema.define(:version => 20170103215307) do
|
15
15
|
|
16
16
|
create_table "tasks", :force => true do |t|
|
17
17
|
t.datetime "completed_at"
|
@@ -19,4 +19,10 @@ ActiveRecord::Schema.define(:version => 20150813132804) do
|
|
19
19
|
t.datetime "updated_at", :null => false
|
20
20
|
end
|
21
21
|
|
22
|
+
create_table "users", :force => true do |t|
|
23
|
+
t.datetime "email_confirmed_at"
|
24
|
+
t.datetime "created_at", :null => false
|
25
|
+
t.datetime "updated_at", :null => false
|
26
|
+
end
|
27
|
+
|
22
28
|
end
|
data/spec/dummy/db/test.sqlite3
CHANGED
Binary file
|
data/spec/support/factories.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_record-events
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bartosz Pieńkowski
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-01-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -133,14 +133,18 @@ files:
|
|
133
133
|
- README.md
|
134
134
|
- Rakefile
|
135
135
|
- lib/active_record/events.rb
|
136
|
+
- lib/active_record/events/naming.rb
|
136
137
|
- lib/active_record/events/version.rb
|
138
|
+
- spec/active_record/events/naming_spec.rb
|
137
139
|
- spec/active_record/events_spec.rb
|
138
140
|
- spec/dummy/app/models/task.rb
|
141
|
+
- spec/dummy/app/models/user.rb
|
139
142
|
- spec/dummy/config/boot.rb
|
140
143
|
- spec/dummy/config/database.yml
|
141
144
|
- spec/dummy/config/environment.rb
|
142
145
|
- spec/dummy/db/development.sqlite3
|
143
146
|
- spec/dummy/db/migrate/20150813132804_create_tasks.rb
|
147
|
+
- spec/dummy/db/migrate/20170103215307_create_users.rb
|
144
148
|
- spec/dummy/db/schema.rb
|
145
149
|
- spec/dummy/db/test.sqlite3
|
146
150
|
- spec/spec_helper.rb
|
@@ -170,13 +174,16 @@ signing_key:
|
|
170
174
|
specification_version: 4
|
171
175
|
summary: Manage timestamps in ActiveRecord models
|
172
176
|
test_files:
|
177
|
+
- spec/active_record/events/naming_spec.rb
|
173
178
|
- spec/active_record/events_spec.rb
|
174
179
|
- spec/dummy/app/models/task.rb
|
180
|
+
- spec/dummy/app/models/user.rb
|
175
181
|
- spec/dummy/config/boot.rb
|
176
182
|
- spec/dummy/config/database.yml
|
177
183
|
- spec/dummy/config/environment.rb
|
178
184
|
- spec/dummy/db/development.sqlite3
|
179
185
|
- spec/dummy/db/migrate/20150813132804_create_tasks.rb
|
186
|
+
- spec/dummy/db/migrate/20170103215307_create_users.rb
|
180
187
|
- spec/dummy/db/schema.rb
|
181
188
|
- spec/dummy/db/test.sqlite3
|
182
189
|
- spec/spec_helper.rb
|