sequel-attribute_callbacks 0.0.1
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.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +74 -0
- data/Rakefile +5 -0
- data/lib/sequel-attribute_callbacks.rb +2 -0
- data/lib/sequel-attribute_callbacks/version.rb +5 -0
- data/lib/sequel/plugins/attribute_callbacks.rb +93 -0
- data/lib/sequel/plugins/attribute_callbacks/pg_array_fixes.rb +38 -0
- data/sequel-attribute_callbacks.gemspec +25 -0
- data/spec/callbacks_spec.rb +183 -0
- data/spec/spec_helper.rb +15 -0
- metadata +125 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Rafał Rzepecki
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Sequel::AttributeCallbacks
|
2
|
+
|
3
|
+
This plugin for Sequel::Record allows to easily hook in callbacks watching
|
4
|
+
specific model attribute changes. The hooks are defined with conventionally
|
5
|
+
named instance methods for maximum DRYness.
|
6
|
+
|
7
|
+
There's special support for callbacks involving array fields (as in Postgres
|
8
|
+
array types with :pg_array extension), so that they can be used similarly to
|
9
|
+
associations, with add and remove callbacks.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
gem 'sequel-attribute_callbacks'
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install sequel-attribute_callbacks
|
24
|
+
|
25
|
+
## Synopsis
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
# people table has (name text) column
|
29
|
+
class Person < Sequel::Model
|
30
|
+
plugin :attribute_callbacks
|
31
|
+
|
32
|
+
def before_name_change old, new_name
|
33
|
+
return true unless Dictionary.is_offensive? new_name
|
34
|
+
end
|
35
|
+
|
36
|
+
def after_name_change old, new
|
37
|
+
NameChangeRecord.create self.id, old, new
|
38
|
+
end
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
Special support for arrays (with pg_array plugin):
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
# widgets table has (colors text[]) column
|
46
|
+
class Widget < Sequel::Model
|
47
|
+
plugin :attribute_callbacks
|
48
|
+
|
49
|
+
def before_colors_add color
|
50
|
+
return false unless Paint.color_vailable? color
|
51
|
+
end
|
52
|
+
|
53
|
+
def after_colors_add color
|
54
|
+
Paint.order color
|
55
|
+
end
|
56
|
+
|
57
|
+
def before_colors_remove color
|
58
|
+
# this is our company color, we need it!
|
59
|
+
return true unless color == 'fuchsia'
|
60
|
+
end
|
61
|
+
|
62
|
+
def after_colors_remove color
|
63
|
+
Paint.reduce_consumption color
|
64
|
+
end
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
## Contributing
|
69
|
+
|
70
|
+
1. Fork it
|
71
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
72
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
73
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
74
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
|
3
|
+
module Sequel::Plugins
|
4
|
+
module AttributeCallbacks
|
5
|
+
def self.apply model
|
6
|
+
model.plugin :dirty
|
7
|
+
|
8
|
+
if defined? ::Sequel::Postgres::PGArray
|
9
|
+
require 'sequel/plugins/attribute_callbacks/pg_array_fixes'
|
10
|
+
model.include PgArrayFixes::AttributeCallbacks
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module InstanceMethods
|
15
|
+
def before_update
|
16
|
+
(column_changes || []).each do |column, change|
|
17
|
+
return false unless call_before_attribute_hook column, change
|
18
|
+
end
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def after_update
|
23
|
+
super
|
24
|
+
(previous_changes || []).each do |column, change|
|
25
|
+
call_after_attribute_hook column, change
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def before_create
|
30
|
+
columns.each do |column|
|
31
|
+
value = send column
|
32
|
+
return false unless call_before_attribute_hook column, [nil, value] if value
|
33
|
+
end
|
34
|
+
super
|
35
|
+
end
|
36
|
+
|
37
|
+
def after_create
|
38
|
+
super
|
39
|
+
columns.each do |column|
|
40
|
+
value = send column
|
41
|
+
call_after_attribute_hook column, [nil, value] if value
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def call_after_attribute_hook column, change
|
48
|
+
method = "after_#{column}_change".to_sym
|
49
|
+
send method, *change if respond_to? method
|
50
|
+
call_after_array_hooks column, *change if change.all?{|x| x.respond_to? :to_a}
|
51
|
+
end
|
52
|
+
|
53
|
+
def call_before_attribute_hook column, change
|
54
|
+
method = "before_#{column}_change".to_sym
|
55
|
+
|
56
|
+
scalar = if respond_to? method
|
57
|
+
send method, *change
|
58
|
+
else
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
return false unless scalar
|
63
|
+
|
64
|
+
if change.all?{|x| x.respond_to? :to_a}
|
65
|
+
call_before_array_hooks column, *change
|
66
|
+
else
|
67
|
+
true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def call_before_array_hooks column, before, after
|
72
|
+
add_hook = "before_#{column}_add".to_sym
|
73
|
+
rm_hook = "before_#{column}_remove".to_sym
|
74
|
+
before = before.to_a
|
75
|
+
after = after.to_a
|
76
|
+
|
77
|
+
return false unless (after - before).all? {|x| send add_hook, x} if respond_to? add_hook
|
78
|
+
return false unless (before - after).all? {|x| send rm_hook, x} if respond_to? rm_hook
|
79
|
+
return true
|
80
|
+
end
|
81
|
+
|
82
|
+
def call_after_array_hooks column, before, after
|
83
|
+
add_hook = "after_#{column}_add".to_sym
|
84
|
+
rm_hook = "after_#{column}_remove".to_sym
|
85
|
+
before = before.to_a
|
86
|
+
after = after.to_a
|
87
|
+
|
88
|
+
(after - before).each {|x| send add_hook, x} if respond_to? add_hook
|
89
|
+
(before - after).each {|x| send rm_hook, x} if respond_to? rm_hook
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Sequel::Plugins::AttributeCallbacks
|
2
|
+
module PgArrayFixes
|
3
|
+
module PgArray
|
4
|
+
# Delegator clone method doesn't clone the delegated to object
|
5
|
+
# which makes it impossible for the Dirty plugin track changes
|
6
|
+
def clone
|
7
|
+
c = super
|
8
|
+
c.__setobj__ __getobj__.clone
|
9
|
+
c
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module AttributeCallbacks
|
14
|
+
def after_initialize
|
15
|
+
super
|
16
|
+
clone_array_attributes
|
17
|
+
end
|
18
|
+
|
19
|
+
def after_save
|
20
|
+
super
|
21
|
+
clone_array_attributes
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# arrays are probably going to be often modified in place
|
27
|
+
def clone_array_attributes
|
28
|
+
values.each do |name, value|
|
29
|
+
if value.kind_of? Sequel::Postgres::PGArray
|
30
|
+
initial_values[name] = value.clone
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
Sequel::Postgres::PGArray.send :include, Sequel::Plugins::AttributeCallbacks::PgArrayFixes::PgArray if defined? Sequel::Postgres::PGArray
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sequel-attribute_callbacks/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "sequel-attribute_callbacks"
|
8
|
+
gem.version = Sequel::AttributeCallbacks::VERSION
|
9
|
+
gem.authors = ["Rafał Rzepecki"]
|
10
|
+
gem.email = ["divided.mind@gmail.com"]
|
11
|
+
gem.description = %q{Model plugin making it easy to define callbacks on modification of specific attributes in the database}
|
12
|
+
gem.summary = %q{Attribute modification callbacks}
|
13
|
+
gem.homepage = "https://github.com/dividedmind/sequel-attribute_callbacks"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_runtime_dependency 'sequel', '~>3.44'
|
21
|
+
|
22
|
+
gem.add_development_dependency 'rake', '~>10.0'
|
23
|
+
gem.add_development_dependency 'rspec', '~>2.12'
|
24
|
+
gem.add_development_dependency 'pg'
|
25
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'attribute_callbacks plugin' do
|
4
|
+
include_context 'database'
|
5
|
+
|
6
|
+
before :all do
|
7
|
+
db.create_table :widgets do
|
8
|
+
primary_key :id
|
9
|
+
String :name
|
10
|
+
column :colors, 'text[]'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
before do
|
15
|
+
db.execute "TRUNCATE TABLE widgets"
|
16
|
+
db.extension:pg_array
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:model) { Sequel::Model(:widgets) }
|
20
|
+
subject { model }
|
21
|
+
|
22
|
+
before {
|
23
|
+
model.instance_eval {
|
24
|
+
plugin :attribute_callbacks
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
it "doesn't interfere with record creation" do
|
29
|
+
model.create
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'after_<attribute>_change callbacks' do
|
33
|
+
it "are called when an instance is being modified" do
|
34
|
+
i = model.create
|
35
|
+
i.should_receive(:after_name_change).with(nil, 'foo')
|
36
|
+
i.name = 'foo'
|
37
|
+
i.save
|
38
|
+
end
|
39
|
+
|
40
|
+
it "are called when an instance is being created" do
|
41
|
+
model.any_instance.should_receive(:after_name_change).with(nil, 'foo')
|
42
|
+
i = model.create name: "foo"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "roll back the change if an exception is thrown" do
|
46
|
+
i = model.create name: "foo"
|
47
|
+
i.should_receive(:after_name_change).with("foo", "bar").and_raise Exception
|
48
|
+
i.name = 'bar'
|
49
|
+
expect { i.save }.to raise_error
|
50
|
+
|
51
|
+
model.first.name.should == "foo"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'before_<attribute>_change callbacks' do
|
56
|
+
it "are called when an instance is being modified" do
|
57
|
+
i = model.create
|
58
|
+
i.should_receive(:before_name_change).with(nil, 'foo').and_return true
|
59
|
+
i.name = 'foo'
|
60
|
+
i.save.should be
|
61
|
+
model.first.name.should == "foo"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "are called when an instance is being created" do
|
65
|
+
model.any_instance.should_receive(:before_name_change).with(nil, 'foo').and_return true
|
66
|
+
i = model.create name: "foo"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "cancel the change if false is returned" do
|
70
|
+
i = model.create name: "foo"
|
71
|
+
i.should_receive(:before_name_change).with("foo", "bar").and_return false
|
72
|
+
i.name = 'bar'
|
73
|
+
expect { i.save }.to raise_error(Sequel::HookFailed)
|
74
|
+
|
75
|
+
model.first.name.should == "foo"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe 'before_<attribute>_add callbacks' do
|
80
|
+
it "are called when an instance is being modified" do
|
81
|
+
i = model.create colors: ['red']
|
82
|
+
i.should_receive(:before_colors_add).with('blue').and_return true
|
83
|
+
i.colors += ['blue']
|
84
|
+
i.save.should be
|
85
|
+
model.first.colors.should == ['red', 'blue']
|
86
|
+
end
|
87
|
+
|
88
|
+
it "work with in place modification" do
|
89
|
+
i = model.create colors: ['red']
|
90
|
+
i.should_receive(:before_colors_add).with('blue').and_return true
|
91
|
+
i.will_change_column :colors
|
92
|
+
i.colors << 'blue'
|
93
|
+
i.save.should be
|
94
|
+
model.first.colors.should == ['red', 'blue']
|
95
|
+
end
|
96
|
+
|
97
|
+
it "work with in place modification without will_change_column" do
|
98
|
+
i = model.create colors: ['red']
|
99
|
+
i.should_receive(:before_colors_add).with('blue').and_return true
|
100
|
+
i.colors << 'blue'
|
101
|
+
i.save.should be
|
102
|
+
model.first.colors.should == ['red', 'blue']
|
103
|
+
end
|
104
|
+
|
105
|
+
it "are called when an instance is being created" do
|
106
|
+
model.any_instance.should_receive(:before_colors_add).with('red').and_return true
|
107
|
+
model.any_instance.should_receive(:before_colors_add).with('blue').and_return true
|
108
|
+
i = model.create colors: ['red', 'blue']
|
109
|
+
end
|
110
|
+
|
111
|
+
it "cancel the change if false is returned" do
|
112
|
+
i = model.create colors: ['red']
|
113
|
+
i.should_receive(:before_colors_add).with('blue').and_return false
|
114
|
+
i.colors += ['blue']
|
115
|
+
expect { i.save }.to raise_error(Sequel::HookFailed)
|
116
|
+
|
117
|
+
model.first.colors.should == ['red']
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe 'before_<attribute>_remove callbacks' do
|
122
|
+
it "are called when an instance is being modified" do
|
123
|
+
i = model.create colors: ['red']
|
124
|
+
i.should_receive(:before_colors_remove).with('red').and_return true
|
125
|
+
i.colors -= ['red']
|
126
|
+
i.save.should be
|
127
|
+
model.first.colors.should == []
|
128
|
+
end
|
129
|
+
|
130
|
+
it "cancel the change if false is returned" do
|
131
|
+
i = model.create colors: ['red']
|
132
|
+
i.should_receive(:before_colors_remove).with('red').and_return false
|
133
|
+
i.colors -= ['red']
|
134
|
+
expect { i.save }.to raise_error(Sequel::HookFailed)
|
135
|
+
|
136
|
+
model.first.colors.should == ['red']
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe 'after_<attribute>_add callbacks' do
|
141
|
+
it "are called when an instance is being modified" do
|
142
|
+
i = model.create colors: ['red']
|
143
|
+
i.should_receive(:after_colors_add).with('blue')
|
144
|
+
i.colors << 'blue'
|
145
|
+
i.save.should be
|
146
|
+
model.first.colors.should == ['red', 'blue']
|
147
|
+
end
|
148
|
+
|
149
|
+
it "are called when an instance is being created" do
|
150
|
+
model.any_instance.should_receive(:after_colors_add).with('red')
|
151
|
+
model.any_instance.should_receive(:after_colors_add).with('blue')
|
152
|
+
i = model.create colors: ['red', 'blue']
|
153
|
+
end
|
154
|
+
|
155
|
+
it "cancel the change if an exception is thrown" do
|
156
|
+
i = model.create colors: ['red']
|
157
|
+
i.should_receive(:after_colors_add).with('blue').and_raise Exception
|
158
|
+
i.colors << 'blue'
|
159
|
+
expect { i.save }.to raise_error
|
160
|
+
|
161
|
+
model.first.colors.should == ['red']
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe 'after_<attribute>_remove callbacks' do
|
166
|
+
it "are called when an instance is being modified" do
|
167
|
+
i = model.create colors: ['red']
|
168
|
+
i.should_receive(:after_colors_remove).with('red')
|
169
|
+
i.colors -= ['red']
|
170
|
+
i.save.should be
|
171
|
+
model.first.colors.should == []
|
172
|
+
end
|
173
|
+
|
174
|
+
it "cancel the change if an exception is thrown" do
|
175
|
+
i = model.create colors: ['red']
|
176
|
+
i.should_receive(:after_colors_remove).with('red').and_raise Exception
|
177
|
+
i.colors -= ['red']
|
178
|
+
expect { i.save }.to raise_error
|
179
|
+
|
180
|
+
model.first.colors.should == ['red']
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'sequel-attribute_callbacks'
|
2
|
+
|
3
|
+
shared_context 'database' do
|
4
|
+
let(:dburl) { ENV['TEST_DATABASE_URL'] || 'postgres:///sequel-attribute_callbacks_test' }
|
5
|
+
let(:db) { Sequel::connect dburl }
|
6
|
+
|
7
|
+
let(:clean_database) {
|
8
|
+
db.execute """
|
9
|
+
DROP SCHEMA public CASCADE;
|
10
|
+
CREATE SCHEMA public;
|
11
|
+
"""
|
12
|
+
}
|
13
|
+
|
14
|
+
before(:all) { clean_database }
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sequel-attribute_callbacks
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Rafał Rzepecki
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-12 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: sequel
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.44'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.44'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '10.0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '10.0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '2.12'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.12'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: pg
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
description: Model plugin making it easy to define callbacks on modification of specific
|
79
|
+
attributes in the database
|
80
|
+
email:
|
81
|
+
- divided.mind@gmail.com
|
82
|
+
executables: []
|
83
|
+
extensions: []
|
84
|
+
extra_rdoc_files: []
|
85
|
+
files:
|
86
|
+
- .gitignore
|
87
|
+
- Gemfile
|
88
|
+
- LICENSE.txt
|
89
|
+
- README.md
|
90
|
+
- Rakefile
|
91
|
+
- lib/sequel-attribute_callbacks.rb
|
92
|
+
- lib/sequel-attribute_callbacks/version.rb
|
93
|
+
- lib/sequel/plugins/attribute_callbacks.rb
|
94
|
+
- lib/sequel/plugins/attribute_callbacks/pg_array_fixes.rb
|
95
|
+
- sequel-attribute_callbacks.gemspec
|
96
|
+
- spec/callbacks_spec.rb
|
97
|
+
- spec/spec_helper.rb
|
98
|
+
homepage: https://github.com/dividedmind/sequel-attribute_callbacks
|
99
|
+
licenses: []
|
100
|
+
post_install_message:
|
101
|
+
rdoc_options: []
|
102
|
+
require_paths:
|
103
|
+
- lib
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
none: false
|
112
|
+
requirements:
|
113
|
+
- - ! '>='
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
requirements: []
|
117
|
+
rubyforge_project:
|
118
|
+
rubygems_version: 1.8.24
|
119
|
+
signing_key:
|
120
|
+
specification_version: 3
|
121
|
+
summary: Attribute modification callbacks
|
122
|
+
test_files:
|
123
|
+
- spec/callbacks_spec.rb
|
124
|
+
- spec/spec_helper.rb
|
125
|
+
has_rdoc:
|