action_callback 0.2.1 → 0.3.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: 5a4abe852096e06e5583e4cfcca4d52602849ffe
4
- data.tar.gz: 1e60d8d0f4af193dbddab6afcd3de35cacb52873
3
+ metadata.gz: e2308622a7b13b58904071fd5c6190d5b3433988
4
+ data.tar.gz: c65e93d23b37e7690a18c621f835fad5785434c5
5
5
  SHA512:
6
- metadata.gz: b7c228312cf98559c0820a580a7e21e9f2156083e659a36835621aeed54cc023b3692338695c0a93e43d093e645c4adee90b8806c83fcd44b4636daeeb714b48
7
- data.tar.gz: 97c9fc56abc6318928644dffd38e305e110830b55726161af12e0a755b382effc8572dfb04b43c33ee142c74afe9ebfa5fd0b9763a61890dfa79909c72bb4a7f
6
+ metadata.gz: 555276c5220445cf130f7998f79e1684c9ee945ac4042149874b5bb68e118ed3407e4cc16d598fa14fdc270d55c27f225a58e3ed6dad722cc71c9c8232c32065
7
+ data.tar.gz: ccb8a7d7f36eae991d0458bbb77c94af7e45758aa52746586cab0be8cbe6bbf9988f57c3b696ceebfaa313cdb25d1b9d30cec9fb45635bc8cfa8f746314a3d53
data/.gitignore CHANGED
@@ -8,4 +8,6 @@
8
8
  /spec/reports/
9
9
  /tmp/
10
10
  *.gem
11
- *.log
11
+ *.log
12
+ .ruby-version
13
+ .DS_Store
data/Gemfile CHANGED
@@ -5,6 +5,5 @@ gemspec
5
5
  group :test do
6
6
  gem "sqlite3"
7
7
  gem 'minitest-reporters'
8
- gem 'minitest-debugger'
9
8
  gem 'rails', '4.0.0'
10
9
  end
data/README.md CHANGED
@@ -1,3 +1,6 @@
1
+ [![Gem Version](https://badge.fury.io/rb/action_callback.svg)](https://badge.fury.io/rb/action_callback)
2
+ [![security](https://hakiri.io/github/EdmundLeex/action_callback/master.svg)](https://hakiri.io/github/EdmundLeex/action_callback/master)
3
+ [![Code Climate](https://codeclimate.com/github/EdmundLeex/action_callback/badges/gpa.svg)](https://codeclimate.com/github/EdmundLeex/action_callback)
1
4
  [![Build Status](https://travis-ci.org/EdmundLeex/action_callback.svg?branch=master)](https://travis-ci.org/EdmundLeex/action_callback)
2
5
 
3
6
  # CallbackAction
@@ -20,8 +23,87 @@ Or install it yourself as:
20
23
 
21
24
  $ gem install callback_action
22
25
 
26
+ ## Preliminary
27
+
28
+ - Ruby >= 2.1.0
29
+ - Rails >= 4.2.6
30
+
23
31
  ## Usage
24
32
 
33
+ ### 1. `validate`
34
+
35
+ #### In Rails
36
+
37
+ This gem adds a `before` option to the `validate` method.
38
+ Use it on any of your model's method. Simply add custom validation method just
39
+ like you usually do.
40
+
41
+ - It runs the method if validation is good
42
+ - Otherwise, it returns false (if there is any error)
43
+
44
+ ```ruby
45
+ class Car < ActiveRecord::Base
46
+ validate :key_present, before: [:unlock_door]
47
+
48
+ def unlock_door
49
+ # unlock the door
50
+ end
51
+
52
+ private
53
+
54
+ def key_present
55
+ unless has_key? && valid_key?
56
+ errors.add(:base, 'need the right key')
57
+ end
58
+ end
59
+ end
60
+
61
+ car = Car.new
62
+ car.unlock_door
63
+ # If has_key?
64
+ # - do whatever the method does
65
+ # - return whatever it returns
66
+ # If !has_key?
67
+ # - returns false
68
+ # - car.errors.full_messages => ['need the right key']
69
+ ```
70
+
71
+ At the same time, it preserves the default `validate` logic if `before` option is
72
+ not used.
73
+
74
+ ```ruby
75
+ class Car < ActiveRecord::Base
76
+ validate :valid_vin_number
77
+ end
78
+ ```
79
+
80
+ #### In Plain Ruby
81
+
82
+ This gem adds a `validate` method to classes that extend this module. You should
83
+ raise error in the validator method
84
+
85
+ - It execute the method if validation passes.
86
+ - It raises the error you specify in the validator method, and stop there.
87
+
88
+ ```ruby
89
+ class Car
90
+ extend ActionCallback
91
+ validate :key_present, before: [:unlock_door]
92
+
93
+ def unlock_door
94
+ # unlock the door
95
+ end
96
+
97
+ private
98
+
99
+ def key_present
100
+ fail 'key invalid' unless valid_key?
101
+ end
102
+ end
103
+ ```
104
+
105
+ ### 2. `before_action` / `after_action`
106
+
25
107
  If you are using Rails, in your Active Record models:
26
108
 
27
109
  ```ruby
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.summary = 'Add callbacks to your ActiveRecord models or plain Ruby classes'
10
10
  spec.description = "Here you can add callbacks to your models using `before_action`, `after_action`"
11
11
 
12
- spec.required_ruby_version = ">= 2.0.0"
12
+ spec.required_ruby_version = ">= 2.1.0"
13
13
 
14
14
  spec.license = "MIT"
15
15
 
@@ -1,9 +1,12 @@
1
- require "action_callback/version"
2
- require "action_callback/define_callback"
3
- require "action_callback/callback"
1
+ require_relative "./action_callback/version"
2
+ require_relative "./action_callback/define_callback"
3
+ require_relative "./action_callback/callback"
4
+ require_relative "./action_callback/define_validation"
5
+ require_relative "./action_callback/validation"
4
6
 
5
7
  module ActionCallback
6
8
  include Callback
9
+ include Validation
7
10
  extend self
8
11
 
9
12
  def ActionCallback.extended(mod)
@@ -13,6 +16,9 @@ module ActionCallback
13
16
  define_callback(callback)
14
17
  alias_method :"#{callback}_filter", :"#{callback}_action"
15
18
  end
19
+
20
+ initialize_validation_chain(mod)
21
+ define_validation
16
22
  end
17
23
  end
18
24
 
@@ -1,54 +1,39 @@
1
1
  require 'set'
2
2
 
3
3
  module Callback
4
- # The chain should have each method that has callback as key
5
- # and each callback points to a hash with :before, :after as key
6
- # each of those keys points to an array of callbacks
7
- # {
8
- # method: {
9
- # before: [...],
10
- # after: [...]
11
- # }
12
- # }
4
+ HOOKS = [:before, :after].freeze
5
+
13
6
  class Chain
14
- CALLBACK_HOOK = [:before, :after].freeze
7
+ HOOKS.each do |cb_hook|
8
+ define_method("#{cb_hook}_chain_of") do |mth_name|
9
+ get_hook(cb_hook, mth_name)
10
+ end
11
+ end
15
12
 
16
13
  def initialize
17
- CALLBACK_HOOK.each do |cb_hook|
14
+ HOOKS.each do |cb_hook|
18
15
  instance_variable_set("@_#{cb_hook}_chain", new_chain)
19
16
  end
20
17
  end
21
18
 
22
- def append_callback(callback_hook, mth, callback)
23
- chain = get_chain(callback_hook)
24
- chain[mth] << callback
25
- end
26
-
27
- CALLBACK_HOOK.each do |cb_hook|
28
- define_method("#{cb_hook}_chain_of") do |mth_name|
29
- get_callbacks(cb_hook, mth_name)
30
- end
19
+ def append(hook_name, mth, hook_mth)
20
+ chain = get_chain(hook_name)
21
+ chain[mth] << hook_mth
31
22
  end
32
23
 
33
24
  private
34
25
 
35
- def get_callbacks(callback_hook, mth)
36
- chain = get_chain(callback_hook)
26
+ def get_hook(hook_name, mth)
27
+ chain = get_chain(hook_name)
37
28
  chain[mth].dup
38
29
  end
39
30
 
40
- def get_chain(callback_hook)
41
- instance_variable_get("@_#{callback_hook}_chain")
31
+ def get_chain(hook_name)
32
+ instance_variable_get("@_#{hook_name}_chain")
42
33
  end
43
34
 
44
35
  def new_chain
45
- Hash.new { |h, k| h[k] = [] }
46
- end
47
- end
48
-
49
- class << self
50
- def get_callbacks(mth)
51
- @_callback_chain.get_callbacks[mth]
36
+ Hash.new { |h, k| h[k] = Set.new }
52
37
  end
53
38
  end
54
39
  end
@@ -2,19 +2,19 @@ module ActionCallback
2
2
  private
3
3
 
4
4
  def initialize_callback_chain(mod)
5
- mod.instance_variable_set('@_callback_chain', Callback::Chain.new)
6
-
7
5
  mod.define_singleton_method(:_callback_chain) do
8
- instance_variable_get('@_callback_chain')
6
+ @_callback_chain
9
7
  end
10
8
  end
11
9
 
12
10
  def define_callback(callback_hook)
13
11
  define_method("#{callback_hook}_action") do |callback, method_scope|
12
+ @_callback_chain ||= Callback::Chain.new
13
+
14
14
  method_scope[:on].each do |mth_name|
15
- @_callback_chain.append_callback(callback_hook, mth_name, callback)
15
+ _callback_chain.append(callback_hook, mth_name, callback)
16
16
 
17
- undef_method(mth_name) if method_defined?(mth_name)
17
+ undef_method(mth_name) if included_modules.map(&:to_s).include?('ActionWithCallbacks')
18
18
 
19
19
  class_eval <<-RUBY
20
20
  module ActionWithCallbacks
@@ -0,0 +1,41 @@
1
+ module ActionCallback
2
+ private
3
+
4
+ def initialize_validation_chain(mod)
5
+ mod.define_singleton_method(:_validation_chain) do
6
+ @_validation_chain
7
+ end
8
+ end
9
+
10
+ def define_validation
11
+ define_method(:validate) do |*args, &block|
12
+ @_validation_chain ||= Validation::Chain.new
13
+
14
+ options = args.last
15
+ if options.key?(:before)
16
+ validator_mth_name = args.first
17
+ options[:before].each do |mth_name|
18
+ _validation_chain.append(:before, mth_name, validator_mth_name)
19
+ undef_method(mth_name) if included_modules.map(&:to_s).include?('ActionWithValidations')
20
+
21
+ class_eval <<-RUBY
22
+ module ActionWithValidations
23
+ define_method(:#{mth_name}) do |*args, &block|
24
+ self.class._validation_chain.before_chain_of(:#{mth_name}).each { |v| send(v) }
25
+
26
+ should_run = true
27
+ should_run = !errors.present? if self.class.ancestors.include?(ActiveRecord::Base)
28
+
29
+ super(*args, &block) if should_run
30
+ end
31
+ end
32
+ RUBY
33
+
34
+ prepend self::ActionWithValidations
35
+ end
36
+ else
37
+ super(*args, &block)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,39 @@
1
+ require 'set'
2
+
3
+ module Validation
4
+ HOOKS = [:before].freeze
5
+
6
+ class Chain
7
+ HOOKS.each do |cb_hook|
8
+ define_method("#{cb_hook}_chain_of") do |mth_name|
9
+ get_hook(cb_hook, mth_name)
10
+ end
11
+ end
12
+
13
+ def initialize
14
+ HOOKS.each do |cb_hook|
15
+ instance_variable_set("@_#{cb_hook}_chain", new_chain)
16
+ end
17
+ end
18
+
19
+ def append(hook_name, mth, hook_mth)
20
+ chain = get_chain(hook_name)
21
+ chain[mth] << hook_mth
22
+ end
23
+
24
+ private
25
+
26
+ def get_hook(hook_name, mth)
27
+ chain = get_chain(hook_name)
28
+ chain[mth].dup
29
+ end
30
+
31
+ def get_chain(hook_name)
32
+ instance_variable_get("@_#{hook_name}_chain")
33
+ end
34
+
35
+ def new_chain
36
+ Hash.new { |h, k| h[k] = Set.new }
37
+ end
38
+ end
39
+ end
@@ -1,5 +1,5 @@
1
1
  module ActionCallback
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
 
4
4
  def self.version
5
5
  VERSION
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: action_callback
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Edmund Li
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-01-08 00:00:00.000000000 Z
11
+ date: 2017-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -72,6 +72,8 @@ files:
72
72
  - lib/action_callback.rb
73
73
  - lib/action_callback/callback.rb
74
74
  - lib/action_callback/define_callback.rb
75
+ - lib/action_callback/define_validation.rb
76
+ - lib/action_callback/validation.rb
75
77
  - lib/action_callback/version.rb
76
78
  homepage: https://github.com/EdmundLeex/action_callback
77
79
  licenses:
@@ -85,7 +87,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
85
87
  requirements:
86
88
  - - ">="
87
89
  - !ruby/object:Gem::Version
88
- version: 2.0.0
90
+ version: 2.1.0
89
91
  required_rubygems_version: !ruby/object:Gem::Requirement
90
92
  requirements:
91
93
  - - ">="
@@ -93,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
95
  version: '0'
94
96
  requirements: []
95
97
  rubyforge_project:
96
- rubygems_version: 2.6.8
98
+ rubygems_version: 2.5.2
97
99
  signing_key:
98
100
  specification_version: 4
99
101
  summary: Add callbacks to your ActiveRecord models or plain Ruby classes