ohm-contrib 2.0.0.alpha5 → 2.0.0.rc1
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 +4 -4
- data/.gems +4 -0
- data/.gitignore +29 -0
- data/CHANGELOG.md +45 -0
- data/README.markdown +3 -23
- data/lib/ohm/contrib.rb +8 -8
- data/lib/ohm/datatypes.rb +11 -20
- data/lib/ohm/locking.rb +7 -9
- data/lib/ohm/slug.rb +3 -2
- data/lib/ohm/softdelete.rb +12 -15
- data/lib/ohm/timestamps.rb +1 -1
- data/lib/ohm/versioned.rb +1 -1
- data/makefile +4 -0
- data/ohm-contrib.gemspec +5 -15
- data/test/callbacks.rb +119 -0
- data/test/contrib.rb +13 -0
- data/test/datatypes.rb +151 -0
- data/test/helper.rb +1 -16
- data/test/locking.rb +10 -0
- data/test/scope.rb +10 -12
- data/test/slug.rb +13 -7
- data/test/{soft_delete.rb → softdelete.rb} +15 -20
- data/test/timestamp.rb +19 -10
- data/test/versioned.rb +6 -5
- metadata +34 -13
- data/test/instance_callbacks.rb +0 -43
- data/test/plugin.rb +0 -299
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe7d66dde39d334e746974535e9c58409ea01946
|
4
|
+
data.tar.gz: 6f1bd0fdb34ea731c84c927c0befdea5e93009ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f710be3a098d1a740b4849d1b2377afffd9709114ab624c4c70d5bfb8536b2cfa7a0418239da997c0c74d20aff80a4f86d660138b1f2b943f908760302e229f5
|
7
|
+
data.tar.gz: 774494ccaf92fa8a29256be6f114e3cd683f560eb258fc1e2393e8e1005afac6197adf7d5f2a0e609f4f1f3360b8d5210ba93453341507c28d61408b9a333447
|
data/.gems
ADDED
data/.gitignore
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
## MAC OS
|
2
|
+
.DS_Store
|
3
|
+
|
4
|
+
## TEXTMATE
|
5
|
+
*.tmproj
|
6
|
+
tmtags
|
7
|
+
|
8
|
+
## EMACS
|
9
|
+
*~
|
10
|
+
\#*
|
11
|
+
.\#*
|
12
|
+
|
13
|
+
## VIM
|
14
|
+
*.swp
|
15
|
+
|
16
|
+
## PROJECT::GENERAL
|
17
|
+
coverage
|
18
|
+
rdoc
|
19
|
+
pkg
|
20
|
+
|
21
|
+
## PROJECT::SPECIFIC
|
22
|
+
/.rvmrc
|
23
|
+
/.yardoc
|
24
|
+
/doc
|
25
|
+
/tests
|
26
|
+
|
27
|
+
## rbenv
|
28
|
+
.rbenv-gemsets
|
29
|
+
.rbenv-version
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
* Support for Ohm 1.3.x has been removed. It only supports Ohm 2.x.
|
2
|
+
|
3
|
+
1.2
|
4
|
+
===
|
5
|
+
|
6
|
+
* Support for <= 1.1 versions has been removed.Ohm-contrib v1.2 should be used
|
7
|
+
with Ohm 1.2 and above only, due to the change in the way the `Ohm::Set` and
|
8
|
+
`Ohm::MultiSet` are defined. The way to extend #initialize on both has changed.
|
9
|
+
|
10
|
+
1.1.1
|
11
|
+
=====
|
12
|
+
|
13
|
+
* Add Symbol and Set datatypes.
|
14
|
+
|
15
|
+
Example:
|
16
|
+
|
17
|
+
class Foo < Ohm::Model
|
18
|
+
include Ohm::DataTypes
|
19
|
+
|
20
|
+
attribute :state, Type::Symbol
|
21
|
+
attribute :bar_ids, Type::Set
|
22
|
+
end
|
23
|
+
|
24
|
+
1.0.0
|
25
|
+
=====
|
26
|
+
|
27
|
+
* `Ohm::Typecast` has been removed in favor of `Ohm::DataTypes`.
|
28
|
+
|
29
|
+
* `Ohm::Timestamping` has been renamed to `Ohm::Timestamps`.
|
30
|
+
|
31
|
+
* `Ohm::Timestamps` now store times as a UNIX Timestamp.
|
32
|
+
|
33
|
+
* `All Ohm validation related plugins have been removed.
|
34
|
+
See [scrivener][scrivener] instead.
|
35
|
+
|
36
|
+
* `Ohm::Boundaries` has been removed.
|
37
|
+
|
38
|
+
* `Ohm::Contrib` no longer uses `autoload`. You can either `require 'ohm/contrib'`,
|
39
|
+
which requires everything, or you can `require 'ohm/datatypes'` for example
|
40
|
+
if you want to cherry pick your requires.
|
41
|
+
|
42
|
+
* `Ohm::Callbacks` no longer provides macro style callbacks, i.e.
|
43
|
+
`after :create, :do_something`. Use instance callbacks instead.
|
44
|
+
|
45
|
+
[scrivener]: http://github.com/soveran/scrivener
|
data/README.markdown
CHANGED
@@ -133,7 +133,7 @@ product.meta.kind_of?(Hash)
|
|
133
133
|
product.meta == { resolution: '1280x768', battery: '8 hours' }
|
134
134
|
# => true
|
135
135
|
|
136
|
-
product.
|
136
|
+
product.sizes.kind_of?(Array)
|
137
137
|
# => true
|
138
138
|
|
139
139
|
product.sizes == ['XS S M L XL']
|
@@ -159,7 +159,8 @@ post.to_param == "1-using-ohm-contrib-1.0"
|
|
159
159
|
```
|
160
160
|
|
161
161
|
By default, `Ohm::Slug` tries to load iconv in order to transliterate
|
162
|
-
non-ascii characters.
|
162
|
+
non-ascii characters. For ruby 2 or later, you will need to `gem install iconv`
|
163
|
+
to get transliteration.
|
163
164
|
|
164
165
|
```ruby
|
165
166
|
post = Post.create(:title => "Décor")
|
@@ -193,24 +194,3 @@ rescue Ohm::VersionConflict => ex
|
|
193
194
|
# => true
|
194
195
|
end
|
195
196
|
```
|
196
|
-
|
197
|
-
<a name="upgrade" id="upgrade"></a>
|
198
|
-
|
199
|
-
## Important Upgrade notes from 0.1.x
|
200
|
-
|
201
|
-
The following lists the major changes:
|
202
|
-
|
203
|
-
1. `Ohm::Typecast` has been removed in favor of `Ohm::DataTypes`.
|
204
|
-
2. `Ohm::Timestamping` has been renamed to `Ohm::Timestamps`.
|
205
|
-
3. `Ohm::Timestamps` now store times as a UNIX Timestamp.
|
206
|
-
4. `All Ohm validation related plugins have been removed.
|
207
|
-
See [scrivener][scrivener] instead.
|
208
|
-
5. `Ohm::Boundaries` has been removed.
|
209
|
-
6. Ohm::Contrib no longer uses `autoload`. You can either
|
210
|
-
`require 'ohm/contrib'`, which requires everything, or you
|
211
|
-
can `require ohm/datatypes` for example if you want to cherry
|
212
|
-
pick your requires.
|
213
|
-
7. `Ohm::Callbacks` no longer provides macro style callbacks, i.e.
|
214
|
-
`after :create, :do_something`. Use instance callbacks instead.
|
215
|
-
|
216
|
-
[scrivener]: http://github.com/soveran/scrivener
|
data/lib/ohm/contrib.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
1
|
+
require_relative "callbacks"
|
2
|
+
require_relative "datatypes"
|
3
|
+
require_relative "locking"
|
4
|
+
require_relative "scope"
|
5
|
+
require_relative "slug"
|
6
|
+
require_relative "softdelete"
|
7
|
+
require_relative "timestamps"
|
8
|
+
require_relative "versioned"
|
9
9
|
|
10
10
|
module Ohm
|
11
11
|
module Contrib
|
data/lib/ohm/datatypes.rb
CHANGED
@@ -7,26 +7,17 @@ require "set"
|
|
7
7
|
module Ohm
|
8
8
|
module DataTypes
|
9
9
|
module Type
|
10
|
-
Integer =
|
11
|
-
Decimal =
|
12
|
-
Float =
|
13
|
-
Symbol =
|
14
|
-
Boolean =
|
15
|
-
Time =
|
16
|
-
Date =
|
17
|
-
Timestamp =
|
18
|
-
Hash =
|
19
|
-
Array =
|
20
|
-
Set =
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.bool(val)
|
24
|
-
case val
|
25
|
-
when "false", "0" then false
|
26
|
-
when "true", "1" then true
|
27
|
-
else
|
28
|
-
!! val
|
29
|
-
end
|
10
|
+
Integer = ->(x) { x.to_i }
|
11
|
+
Decimal = ->(x) { BigDecimal(x.to_s) }
|
12
|
+
Float = ->(x) { x.to_f }
|
13
|
+
Symbol = ->(x) { x && x.to_sym }
|
14
|
+
Boolean = ->(x) { !!x }
|
15
|
+
Time = ->(t) { t && (t.kind_of?(::Time) ? t : ::Time.parse(t)) }
|
16
|
+
Date = ->(d) { d && (d.kind_of?(::Date) ? d : ::Date.parse(d)) }
|
17
|
+
Timestamp = ->(t) { t && UnixTime.at(t.to_i) }
|
18
|
+
Hash = ->(h) { h && SerializedHash[h.kind_of?(::Hash) ? h : JSON(h)] }
|
19
|
+
Array = ->(a) { a && SerializedArray.new(a.kind_of?(::Array) ? a : JSON(a)) }
|
20
|
+
Set = ->(s) { s && SerializedSet.new(s.kind_of?(::Set) ? s : JSON(s)) }
|
30
21
|
end
|
31
22
|
|
32
23
|
class UnixTime < Time
|
data/lib/ohm/locking.rb
CHANGED
@@ -8,9 +8,7 @@ module Ohm
|
|
8
8
|
# Lock the object before executing the block, and release it once the block
|
9
9
|
# is done.
|
10
10
|
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
# post = Order.create(:customer => Customer.create)
|
11
|
+
# post = Order.create(customer: Customer.create)
|
14
12
|
# post.mutex(0.01) do
|
15
13
|
# # this block is in a mutex!
|
16
14
|
# end
|
@@ -29,11 +27,11 @@ module Ohm
|
|
29
27
|
#
|
30
28
|
# @see Model#mutex
|
31
29
|
def lock!(wait = 0.1)
|
32
|
-
until key[:_lock]
|
33
|
-
next unless lock = key[:_lock]
|
30
|
+
until redis.call("SETNX", key[:_lock], lock_timeout)
|
31
|
+
next unless lock = redis.call("HGET", key[:_lock])
|
34
32
|
sleep(wait) and next unless lock_expired?(lock)
|
35
33
|
|
36
|
-
break unless lock = key[:_lock]
|
34
|
+
break unless lock = redis.call("GETSET", key[:_lock], lock_timeout)
|
37
35
|
break if lock_expired?(lock)
|
38
36
|
end
|
39
37
|
end
|
@@ -41,15 +39,15 @@ module Ohm
|
|
41
39
|
# Release the lock.
|
42
40
|
# @see Model#mutex
|
43
41
|
def unlock!
|
44
|
-
key[:_lock]
|
42
|
+
redis.call("DEL", key[:_lock])
|
45
43
|
end
|
46
44
|
|
47
45
|
def lock_timeout
|
48
46
|
Time.now.to_f + 1
|
49
47
|
end
|
50
48
|
|
51
|
-
def lock_expired?
|
49
|
+
def lock_expired?(lock)
|
52
50
|
lock.to_f < Time.now.to_f
|
53
51
|
end
|
54
52
|
end
|
55
|
-
end
|
53
|
+
end
|
data/lib/ohm/slug.rb
CHANGED
@@ -11,12 +11,13 @@ module Ohm
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def slug(str = to_s)
|
14
|
-
ret = transcode(str)
|
14
|
+
ret = transcode(str.dup)
|
15
15
|
ret.gsub!("'", "")
|
16
16
|
ret.gsub!(/[^0-9A-Za-z]/u, " ")
|
17
17
|
ret.strip!
|
18
18
|
ret.gsub!(/\s+/, "-")
|
19
|
-
ret.downcase
|
19
|
+
ret.downcase!
|
20
|
+
return ret
|
20
21
|
end
|
21
22
|
module_function :slug
|
22
23
|
|
data/lib/ohm/softdelete.rb
CHANGED
@@ -1,16 +1,14 @@
|
|
1
1
|
module Ohm
|
2
|
-
# Provides support for soft deletion
|
3
|
-
#
|
4
|
-
# @example
|
2
|
+
# Provides support for soft deletion.
|
5
3
|
#
|
6
4
|
# class Post < Ohm::Model
|
7
|
-
#
|
5
|
+
# include Ohm::SoftDelete
|
8
6
|
#
|
9
7
|
# attribute :title
|
10
8
|
# index :title
|
11
9
|
# end
|
12
10
|
#
|
13
|
-
# post = Post.create(:
|
11
|
+
# post = Post.create(title: 'Title')
|
14
12
|
#
|
15
13
|
# post.deleted?
|
16
14
|
# # => false
|
@@ -23,7 +21,7 @@ module Ohm
|
|
23
21
|
# Post.all.empty?
|
24
22
|
# # => true
|
25
23
|
#
|
26
|
-
# Post.find(:
|
24
|
+
# Post.find(title: 'Title').include?(post)
|
27
25
|
# # => true
|
28
26
|
#
|
29
27
|
# Post.exists?(post.id)
|
@@ -33,11 +31,10 @@ module Ohm
|
|
33
31
|
#
|
34
32
|
# post.deleted?
|
35
33
|
# # => true
|
34
|
+
#
|
36
35
|
module SoftDelete
|
37
|
-
DELETED_FLAG = "1"
|
38
|
-
|
39
36
|
def self.included(model)
|
40
|
-
model.attribute :deleted
|
37
|
+
model.attribute :deleted, ->(x) { !!x }
|
41
38
|
|
42
39
|
model.extend ClassMethods
|
43
40
|
end
|
@@ -46,13 +43,13 @@ module Ohm
|
|
46
43
|
redis.queue("MULTI")
|
47
44
|
redis.queue("SREM", model.all.key, id)
|
48
45
|
redis.queue("SADD", model.deleted.key, id)
|
49
|
-
redis.queue("HSET", key, :deleted,
|
46
|
+
redis.queue("HSET", key, :deleted, true)
|
50
47
|
redis.queue("EXEC")
|
51
48
|
redis.commit
|
52
49
|
|
53
|
-
self.deleted =
|
50
|
+
self.deleted = true
|
54
51
|
|
55
|
-
|
52
|
+
self
|
56
53
|
end
|
57
54
|
|
58
55
|
def restore
|
@@ -65,11 +62,11 @@ module Ohm
|
|
65
62
|
|
66
63
|
self.deleted = nil
|
67
64
|
|
68
|
-
|
65
|
+
self
|
69
66
|
end
|
70
67
|
|
71
68
|
def deleted?
|
72
|
-
deleted
|
69
|
+
deleted
|
73
70
|
end
|
74
71
|
|
75
72
|
module ClassMethods
|
@@ -78,7 +75,7 @@ module Ohm
|
|
78
75
|
end
|
79
76
|
|
80
77
|
def exists?(id)
|
81
|
-
super ||
|
78
|
+
super || deleted.exists?(id)
|
82
79
|
end
|
83
80
|
end
|
84
81
|
end
|
data/lib/ohm/timestamps.rb
CHANGED
data/lib/ohm/versioned.rb
CHANGED
data/makefile
ADDED
data/ohm-contrib.gemspec
CHANGED
@@ -1,28 +1,18 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "ohm-contrib"
|
3
|
-
s.version = "2.0.0.
|
3
|
+
s.version = "2.0.0.rc1"
|
4
4
|
s.summary = %{A collection of decoupled drop-in modules for Ohm.}
|
5
5
|
s.description = %{Includes a couple of core functions such as callbacks, timestamping, typecasting and lots of generic validation routines.}
|
6
6
|
s.author = "Cyril David"
|
7
7
|
s.email = "cyx@cyx.is"
|
8
8
|
s.homepage = "http://github.com/cyx/ohm-contrib"
|
9
|
+
s.license = "MIT"
|
9
10
|
|
10
|
-
s.
|
11
|
+
s.files = `git ls-files`.split("\n")
|
11
12
|
|
12
|
-
s.
|
13
|
-
"LICENSE",
|
14
|
-
"README.markdown",
|
15
|
-
"rakefile",
|
16
|
-
"lib/**/*.rb",
|
17
|
-
"*.gemspec",
|
18
|
-
"test/*.*",
|
19
|
-
]
|
20
|
-
|
21
|
-
s.require_paths = ["lib"]
|
22
|
-
s.rubyforge_project = "ohm-contrib"
|
23
|
-
|
24
|
-
s.add_dependency "ohm", "2.0.0.alpha5"
|
13
|
+
s.add_dependency "ohm", "~> 2.0.0.rc1"
|
25
14
|
|
26
15
|
s.add_development_dependency "cutest"
|
16
|
+
s.add_development_dependency "iconv"
|
27
17
|
s.add_development_dependency "override"
|
28
18
|
end
|
data/test/callbacks.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
require_relative "../lib/ohm/callbacks"
|
3
|
+
|
4
|
+
class Post < Ohm::Model
|
5
|
+
include Ohm::Callbacks
|
6
|
+
|
7
|
+
attribute :body
|
8
|
+
|
9
|
+
def did?(action)
|
10
|
+
!!instance_variable_get("@#{ action }")
|
11
|
+
end
|
12
|
+
|
13
|
+
def count(action)
|
14
|
+
instance_variable_get("@#{ action }")
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def before_create() incr(:do_before_create) end
|
20
|
+
def after_create() incr(:do_after_create) end
|
21
|
+
def before_save() incr(:do_before_save) end
|
22
|
+
def after_save() incr(:do_after_save) end
|
23
|
+
def before_update() incr(:do_before_update) end
|
24
|
+
def after_update() incr(:do_after_update) end
|
25
|
+
def before_delete() incr(:do_before_delete) end
|
26
|
+
def after_delete() incr(:do_after_delete) end
|
27
|
+
|
28
|
+
def incr(action)
|
29
|
+
val = instance_variable_get("@#{ action }")
|
30
|
+
val ||= 0
|
31
|
+
val += 1
|
32
|
+
|
33
|
+
instance_variable_set("@#{ action }", val)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
test "create invokes all callbacks (except update)" do
|
38
|
+
post = Post.create(body: "The Body")
|
39
|
+
|
40
|
+
assert post.did?(:do_before_create)
|
41
|
+
assert post.did?(:do_after_create)
|
42
|
+
assert post.did?(:do_before_save)
|
43
|
+
assert post.did?(:do_after_save)
|
44
|
+
assert !post.did?(:do_before_update)
|
45
|
+
assert !post.did?(:do_after_update)
|
46
|
+
end
|
47
|
+
|
48
|
+
test "create only invokes save / create once" do
|
49
|
+
post = Post.create(body: "The Body")
|
50
|
+
|
51
|
+
assert_equal 1, post.count(:do_before_create)
|
52
|
+
assert_equal 1, post.count(:do_after_create)
|
53
|
+
assert_equal 1, post.count(:do_before_save)
|
54
|
+
assert_equal 1, post.count(:do_after_save)
|
55
|
+
end
|
56
|
+
|
57
|
+
test "ensure create / save callbacks are only called once" do
|
58
|
+
post = Post.new(body: "The Body")
|
59
|
+
post.save
|
60
|
+
|
61
|
+
assert_equal 1, post.count(:do_before_create)
|
62
|
+
assert_equal 1, post.count(:do_after_create)
|
63
|
+
assert_equal 1, post.count(:do_before_save)
|
64
|
+
assert_equal 1, post.count(:do_after_save)
|
65
|
+
end
|
66
|
+
|
67
|
+
test "save of existing record executes save and update callbacks" do
|
68
|
+
post = Post.create(body: "The Body")
|
69
|
+
post = Post[post.id]
|
70
|
+
post.save
|
71
|
+
|
72
|
+
assert ! post.did?(:do_before_create)
|
73
|
+
assert ! post.did?(:do_after_create)
|
74
|
+
|
75
|
+
assert post.did?(:do_before_save)
|
76
|
+
assert post.did?(:do_after_save)
|
77
|
+
assert post.did?(:do_before_update)
|
78
|
+
assert post.did?(:do_after_update)
|
79
|
+
|
80
|
+
assert_equal 1, post.count(:do_before_save)
|
81
|
+
assert_equal 1, post.count(:do_after_save)
|
82
|
+
assert_equal 1, post.count(:do_before_update)
|
83
|
+
assert_equal 1, post.count(:do_after_update)
|
84
|
+
end
|
85
|
+
|
86
|
+
test "save of existing record (using #update)" do
|
87
|
+
post = Post.create(body: "The Body")
|
88
|
+
post = Post[post.id]
|
89
|
+
post.update(body: "New Body")
|
90
|
+
|
91
|
+
assert ! post.did?(:do_before_create)
|
92
|
+
assert ! post.did?(:do_after_create)
|
93
|
+
|
94
|
+
assert post.did?(:do_before_save)
|
95
|
+
assert post.did?(:do_after_save)
|
96
|
+
assert post.did?(:do_before_update)
|
97
|
+
assert post.did?(:do_after_update)
|
98
|
+
|
99
|
+
assert_equal 1, post.count(:do_before_save)
|
100
|
+
assert_equal 1, post.count(:do_after_save)
|
101
|
+
assert_equal 1, post.count(:do_before_update)
|
102
|
+
assert_equal 1, post.count(:do_after_update)
|
103
|
+
end
|
104
|
+
|
105
|
+
test "on delete" do
|
106
|
+
post = Post.create(body: "The Body")
|
107
|
+
post = Post[post.id]
|
108
|
+
post.delete
|
109
|
+
|
110
|
+
assert_equal 1, post.count(:do_before_delete)
|
111
|
+
assert_equal 1, post.count(:do_after_delete)
|
112
|
+
|
113
|
+
assert ! post.did?(:do_before_create)
|
114
|
+
assert ! post.did?(:do_after_create)
|
115
|
+
assert ! post.did?(:do_before_save)
|
116
|
+
assert ! post.did?(:do_after_save)
|
117
|
+
assert ! post.did?(:do_before_update)
|
118
|
+
assert ! post.did?(:do_after_update)
|
119
|
+
end
|