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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- N2VhZTQxOTNiMmU4MzdmNjgyYjIzNzMwNjMzZjY1MjM3ODJiOGJhZQ==
4
+ Njk0YzdlMmY0YzRiMmYxNzdjMmE3OTMyODUwNjIzNjgwZmEzOTZiMg==
5
5
  data.tar.gz: !binary |-
6
- YzRmYWY5M2JmYmNmMGY0ODdiMTIwY2QyZDdkYjhkZDMxODMzYzM3MQ==
6
+ NDNiMmViY2U5NTNmZmY5ZjQ3NzdkMTY5Mjg4YTlmMTJmMTI3NjI3Yw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- Y2NjZTY3YmIyMDBjZjNlMmZiNWU1NjdlZGExMTE0ZGViYTg3NWY4YWY3ZmM3
10
- YzBmZjJlNWI4MWFlYWQ0ZWQ5ZmRmZDgxMmI3NTYzM2VlNGZmNGYyYzEyNmE2
11
- ZjQ0YzAzNzhmMjk5ZTE0OGZkNjM2YzAzM2IwNzI5MTkxMTU1MmU=
9
+ OTlhYzQ1ODkwNjg1ZjNkYjhjZTY3ZTgwZWIyYjgxYTgzNDM1NmJlNmExODEy
10
+ ZTU1MTYxOTllMDAwNmUwOTM0MTVkM2FlODZlN2ZjNzViOTYzNmFmOTk2NTEw
11
+ Y2JlNzEzZGUyN2EyMTk4M2Q2YWZiNTQ2ODI5NjAzYWY1ZWMwNjY=
12
12
  data.tar.gz: !binary |-
13
- MDA2M2M3MjY2NzUyYTVhYjJkMmU4ZDhjYmJjNDcxOGU3NDFlNWE5MmFkMDMy
14
- ODdhZTFkOWJlYWEyOTcxNjM5MTMxOGEzMmFmZDBlMDc3NDllYjMzZjRlZThl
15
- ZTM5ZThmZWM3NzE1NjIyOTY1ZTUyZWY1NTE5MmY5MjY2YmQzZTk=
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)
@@ -1,41 +1,34 @@
1
1
  require 'active_support'
2
- require 'verbs'
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.each { |n| has_event(n) }
7
+ options = names.extract_options!
8
+ names.each { |n| has_event(n, options) }
13
9
  end
14
10
 
15
- def has_event(name)
16
- _module = ActiveRecord::Events
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("#{past_participle}?") do
22
- self[field_name].present?
14
+ define_method("#{naming.predicate}?") do
15
+ self[naming.field].present?
23
16
  end
24
17
 
25
- define_method(name) do
26
- touch(field_name) if self[field_name].blank?
18
+ define_method(naming.action) do
19
+ touch(naming.field) if self[naming.field].blank?
27
20
  end
28
21
 
29
- define_method("#{name}!") do
30
- touch(field_name)
22
+ define_method("#{naming.action}!") do
23
+ touch(naming.field)
31
24
  end
32
25
 
33
- define_singleton_method(past_participle) do
34
- where(arel_table[field_name].not_eq(nil))
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("not_#{past_participle}") do
38
- where(arel_table[field_name].eq(nil))
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
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module Events
3
- VERSION = '1.0.0'
3
+ VERSION = '1.1.0'
4
4
  end
5
5
  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
@@ -0,0 +1,3 @@
1
+ class User < ActiveRecord::Base
2
+ has_event :confirm, subject: :email
3
+ end
@@ -0,0 +1,9 @@
1
+ class CreateUsers < ActiveRecord::Migration
2
+ def change
3
+ create_table :users do |t|
4
+ t.datetime :email_confirmed_at
5
+
6
+ t.timestamps null: false
7
+ end
8
+ end
9
+ end
@@ -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 => 20150813132804) do
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
Binary file
@@ -1,3 +1,4 @@
1
1
  FactoryGirl.define do
2
2
  factory :task
3
+ factory :user
3
4
  end
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.0.0
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: 2016-12-28 00:00:00.000000000 Z
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