dm-types 0.10.2 → 1.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.
- data/.gitignore +36 -0
- data/Gemfile +147 -0
- data/Rakefile +7 -8
- data/VERSION +1 -1
- data/dm-types.gemspec +61 -20
- data/lib/dm-types.rb +24 -19
- data/lib/dm-types/bcrypt_hash.rb +17 -13
- data/lib/dm-types/comma_separated_list.rb +11 -16
- data/lib/dm-types/csv.rb +11 -11
- data/lib/dm-types/enum.rb +33 -50
- data/lib/dm-types/epoch_time.rb +11 -11
- data/lib/dm-types/file_path.rb +13 -10
- data/lib/dm-types/flag.rb +17 -25
- data/lib/dm-types/ip_address.rb +15 -11
- data/lib/dm-types/json.rb +17 -14
- data/lib/dm-types/paranoid/base.rb +38 -0
- data/lib/dm-types/paranoid_boolean.rb +23 -0
- data/lib/dm-types/paranoid_datetime.rb +22 -0
- data/lib/dm-types/regexp.rb +8 -8
- data/lib/dm-types/slug.rb +7 -12
- data/lib/dm-types/uri.rb +21 -9
- data/lib/dm-types/uuid.rb +18 -11
- data/lib/dm-types/yaml.rb +12 -10
- data/spec/fixtures/article.rb +0 -2
- data/spec/fixtures/bookmark.rb +0 -2
- data/spec/fixtures/network_node.rb +0 -2
- data/spec/fixtures/person.rb +0 -2
- data/spec/fixtures/software_package.rb +0 -2
- data/spec/fixtures/ticket.rb +2 -4
- data/spec/fixtures/tshirt.rb +3 -5
- data/spec/integration/bcrypt_hash_spec.rb +33 -31
- data/spec/integration/comma_separated_list_spec.rb +55 -53
- data/spec/integration/enum_spec.rb +55 -53
- data/spec/integration/file_path_spec.rb +105 -103
- data/spec/integration/flag_spec.rb +42 -40
- data/spec/integration/ip_address_spec.rb +91 -89
- data/spec/integration/json_spec.rb +41 -39
- data/spec/integration/slug_spec.rb +36 -34
- data/spec/integration/uri_spec.rb +82 -79
- data/spec/integration/uuid_spec.rb +63 -61
- data/spec/integration/yaml_spec.rb +37 -35
- data/spec/spec_helper.rb +7 -36
- data/spec/unit/bcrypt_hash_spec.rb +18 -10
- data/spec/unit/csv_spec.rb +92 -80
- data/spec/unit/enum_spec.rb +27 -42
- data/spec/unit/epoch_time_spec.rb +18 -7
- data/spec/unit/file_path_spec.rb +15 -10
- data/spec/unit/flag_spec.rb +13 -36
- data/spec/unit/ip_address_spec.rb +13 -10
- data/spec/unit/json_spec.rb +21 -14
- data/spec/unit/paranoid_boolean_spec.rb +138 -0
- data/spec/unit/paranoid_datetime_spec.rb +143 -0
- data/spec/unit/regexp_spec.rb +15 -5
- data/spec/unit/uri_spec.rb +13 -9
- data/spec/unit/yaml_spec.rb +16 -9
- data/tasks/local_gemfile.rake +18 -0
- data/tasks/spec.rake +0 -3
- metadata +122 -52
data/lib/dm-types/csv.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'dm-core'
|
2
|
+
|
1
3
|
if RUBY_VERSION >= '1.9.0'
|
2
4
|
require 'csv'
|
3
5
|
else
|
@@ -6,27 +8,25 @@ else
|
|
6
8
|
end
|
7
9
|
|
8
10
|
module DataMapper
|
9
|
-
|
10
|
-
class Csv <
|
11
|
-
|
12
|
-
|
13
|
-
def self.load(value, property)
|
11
|
+
class Property
|
12
|
+
class Csv < Text
|
13
|
+
def load(value)
|
14
14
|
case value
|
15
|
-
when String then CSV.parse(value)
|
16
|
-
when Array then value
|
15
|
+
when ::String then CSV.parse(value)
|
16
|
+
when ::Array then value
|
17
17
|
else
|
18
18
|
nil
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
22
|
+
def dump(value)
|
23
23
|
case value
|
24
|
-
when Array then CSV.generate { |csv| value.each { |row| csv << row } }
|
25
|
-
when String then value
|
24
|
+
when ::Array then CSV.generate { |csv| value.each { |row| csv << row } }
|
25
|
+
when ::String then value
|
26
26
|
else
|
27
27
|
nil
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end # class Csv
|
31
|
-
end #
|
31
|
+
end # class Property
|
32
32
|
end # module DataMapper
|
data/lib/dm-types/enum.rb
CHANGED
@@ -1,73 +1,56 @@
|
|
1
|
-
|
2
|
-
module Types
|
3
|
-
class Enum < Type
|
4
|
-
primitive Integer
|
1
|
+
require 'dm-core'
|
5
2
|
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
module DataMapper
|
4
|
+
class Property
|
5
|
+
class Enum < Integer
|
6
|
+
accept_options :flags
|
9
7
|
|
10
|
-
|
11
|
-
@flag_map
|
12
|
-
end
|
8
|
+
attr_reader :flag_map
|
13
9
|
|
14
|
-
def
|
15
|
-
|
16
|
-
end
|
10
|
+
def initialize(model, name, options = {}, type = nil)
|
11
|
+
super
|
17
12
|
|
18
|
-
|
19
|
-
enum = Class.new(Enum)
|
20
|
-
enum.flag_map = {}
|
13
|
+
@flag_map = {}
|
21
14
|
|
15
|
+
flags = options.fetch(:flags)
|
22
16
|
flags.each_with_index do |flag, i|
|
23
|
-
|
17
|
+
@flag_map[i + 1] = flag
|
24
18
|
end
|
25
19
|
|
26
|
-
|
20
|
+
if defined?(::DataMapper::Validations)
|
21
|
+
unless model.skip_auto_validation_for?(self)
|
22
|
+
if self.class.ancestors.include?(Property::Enum)
|
23
|
+
allowed = flag_map.values_at(*flag_map.keys.sort)
|
24
|
+
model.validates_within name, model.options_with_message({ :set => allowed }, self, :within)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
27
28
|
end
|
28
29
|
|
29
|
-
def
|
30
|
-
|
30
|
+
def custom?
|
31
|
+
true
|
31
32
|
end
|
32
33
|
|
33
|
-
def
|
34
|
-
|
34
|
+
def load(value)
|
35
|
+
flag_map[value]
|
35
36
|
end
|
36
37
|
|
37
|
-
def
|
38
|
+
def dump(value)
|
38
39
|
case value
|
39
|
-
|
40
|
-
|
40
|
+
when ::Array then value.collect { |v| dump(v) }
|
41
|
+
else flag_map.invert[value]
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
44
|
-
def
|
45
|
+
def typecast_to_primitive(value)
|
45
46
|
# Attempt to typecast using the class of the first item in the map.
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
else value
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.bind(property)
|
56
|
-
if defined?(::DataMapper::Validate)
|
57
|
-
model = property.model
|
58
|
-
|
59
|
-
unless model.skip_auto_validation_for?(property)
|
60
|
-
if property.type.ancestors.include?(Types::Enum)
|
61
|
-
model.class_eval do
|
62
|
-
flag_map = property.type.flag_map
|
63
|
-
allowed = flag_map.values_at(*flag_map.keys.sort)
|
64
|
-
|
65
|
-
validates_within property.name, options_with_message({ :set => allowed }, property, :within)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
47
|
+
case flag_map[1]
|
48
|
+
when ::Symbol then value.to_sym
|
49
|
+
when ::String then value.to_s
|
50
|
+
when ::Fixnum then value.to_i
|
51
|
+
else value
|
69
52
|
end
|
70
53
|
end
|
71
54
|
end # class Enum
|
72
|
-
end #
|
55
|
+
end # class Property
|
73
56
|
end # module DataMapper
|
data/lib/dm-types/epoch_time.rb
CHANGED
@@ -1,22 +1,22 @@
|
|
1
|
-
|
2
|
-
module Types
|
3
|
-
class EpochTime < DataMapper::Type
|
4
|
-
primitive Integer
|
1
|
+
require 'dm-core'
|
5
2
|
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
module DataMapper
|
4
|
+
class Property
|
5
|
+
class EpochTime < Integer
|
6
|
+
def load(value)
|
7
|
+
if value.kind_of?(::Integer)
|
8
|
+
::Time.at(value)
|
9
9
|
else
|
10
10
|
value
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
14
|
+
def dump(value)
|
15
15
|
case value
|
16
|
-
when Integer, Time then value.to_i
|
17
|
-
when DateTime then value.to_time.to_i
|
16
|
+
when ::Integer, ::Time then value.to_i
|
17
|
+
when ::DateTime then value.to_time.to_i
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end # class EpochTime
|
21
|
-
end #
|
21
|
+
end # class Property
|
22
22
|
end # module DataMapper
|
data/lib/dm-types/file_path.rb
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
require 'pathname'
|
2
|
+
require 'dm-core'
|
2
3
|
|
3
4
|
module DataMapper
|
4
|
-
|
5
|
-
class FilePath <
|
6
|
-
|
7
|
-
length 255
|
5
|
+
class Property
|
6
|
+
class FilePath < String
|
7
|
+
length 255
|
8
8
|
|
9
|
-
def
|
9
|
+
def primitive?(value)
|
10
|
+
value.kind_of?(Pathname)
|
11
|
+
end
|
12
|
+
|
13
|
+
def load(value)
|
10
14
|
if value.blank?
|
11
15
|
nil
|
12
16
|
else
|
@@ -14,15 +18,14 @@ module DataMapper
|
|
14
18
|
end
|
15
19
|
end
|
16
20
|
|
17
|
-
def
|
21
|
+
def dump(value)
|
18
22
|
return nil if value.blank?
|
19
23
|
value.to_s
|
20
24
|
end
|
21
25
|
|
22
|
-
def
|
23
|
-
|
24
|
-
value.kind_of?(Pathname) ? value : load(value, property)
|
26
|
+
def typecast_to_primitive(value)
|
27
|
+
load(value)
|
25
28
|
end
|
26
29
|
end # class FilePath
|
27
|
-
end #
|
30
|
+
end # class Property
|
28
31
|
end # module DataMapper
|
data/lib/dm-types/flag.rb
CHANGED
@@ -1,36 +1,28 @@
|
|
1
|
-
|
2
|
-
module Types
|
3
|
-
class Flag < Type
|
4
|
-
primitive Integer
|
1
|
+
require 'dm-core'
|
5
2
|
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
module DataMapper
|
4
|
+
class Property
|
5
|
+
class Flag < Integer
|
6
|
+
accept_options :flags
|
9
7
|
|
10
|
-
|
11
|
-
@flag_map
|
12
|
-
end
|
8
|
+
attr_reader :flag_map
|
13
9
|
|
14
|
-
def
|
15
|
-
|
16
|
-
end
|
10
|
+
def initialize(model, name, options = {}, type = nil)
|
11
|
+
super
|
17
12
|
|
18
|
-
|
19
|
-
type = Class.new(Flag)
|
20
|
-
type.flag_map = {}
|
13
|
+
@flag_map = {}
|
21
14
|
|
15
|
+
flags = options.fetch(:flags)
|
22
16
|
flags.each_with_index do |flag, i|
|
23
|
-
|
17
|
+
flag_map[i] = flag
|
24
18
|
end
|
25
|
-
|
26
|
-
type
|
27
19
|
end
|
28
20
|
|
29
|
-
def
|
30
|
-
|
21
|
+
def custom?
|
22
|
+
true
|
31
23
|
end
|
32
24
|
|
33
|
-
def
|
25
|
+
def load(value)
|
34
26
|
return [] if value.nil? || value <= 0
|
35
27
|
|
36
28
|
begin
|
@@ -46,13 +38,13 @@ module DataMapper
|
|
46
38
|
end
|
47
39
|
end
|
48
40
|
|
49
|
-
def
|
41
|
+
def dump(value)
|
50
42
|
return if value.nil?
|
51
43
|
flags = Array(value).map { |flag| flag.to_sym }.flatten
|
52
44
|
flag_map.invert.values_at(*flags).compact.inject(0) { |sum, i| sum += 1 << i }
|
53
45
|
end
|
54
46
|
|
55
|
-
def
|
47
|
+
def typecast(value)
|
56
48
|
case value
|
57
49
|
when nil then nil
|
58
50
|
when Array then value.map {|v| v.to_sym}
|
@@ -60,5 +52,5 @@ module DataMapper
|
|
60
52
|
end
|
61
53
|
end
|
62
54
|
end # class Flag
|
63
|
-
end #
|
55
|
+
end # class Property
|
64
56
|
end # module DataMapper
|
data/lib/dm-types/ip_address.rb
CHANGED
@@ -1,31 +1,35 @@
|
|
1
1
|
require 'ipaddr'
|
2
|
+
require 'dm-core'
|
2
3
|
|
3
4
|
module DataMapper
|
4
|
-
|
5
|
-
class IPAddress <
|
6
|
-
|
7
|
-
length 16
|
5
|
+
class Property
|
6
|
+
class IPAddress < String
|
7
|
+
length 39
|
8
8
|
|
9
|
-
def
|
9
|
+
def primitive?(value)
|
10
|
+
value.kind_of?(IPAddr)
|
11
|
+
end
|
12
|
+
|
13
|
+
def load(value)
|
10
14
|
if value.nil?
|
11
15
|
nil
|
12
|
-
elsif value.is_a?(String) && !value.empty?
|
16
|
+
elsif value.is_a?(::String) && !value.empty?
|
13
17
|
IPAddr.new(value)
|
14
|
-
elsif value.is_a?(String) && value.empty?
|
18
|
+
elsif value.is_a?(::String) && value.empty?
|
15
19
|
IPAddr.new("0.0.0.0")
|
16
20
|
else
|
17
21
|
raise ArgumentError.new("+value+ must be nil or a String")
|
18
22
|
end
|
19
23
|
end
|
20
24
|
|
21
|
-
def
|
25
|
+
def dump(value)
|
22
26
|
return nil if value.nil?
|
23
27
|
value.to_s
|
24
28
|
end
|
25
29
|
|
26
|
-
def
|
27
|
-
|
30
|
+
def typecast_to_primitive(value)
|
31
|
+
load(value)
|
28
32
|
end
|
29
33
|
end # class IPAddress
|
30
|
-
end # module
|
34
|
+
end # module Property
|
31
35
|
end # module DataMapper
|
data/lib/dm-types/json.rb
CHANGED
@@ -1,36 +1,39 @@
|
|
1
|
+
require 'dm-core'
|
1
2
|
require 'json'
|
2
3
|
|
3
4
|
module DataMapper
|
4
|
-
|
5
|
-
class Json <
|
6
|
-
|
5
|
+
class Property
|
6
|
+
class Json < Text
|
7
|
+
def custom?
|
8
|
+
true
|
9
|
+
end
|
10
|
+
|
11
|
+
def primitive?(value)
|
12
|
+
value.kind_of?(::Array) || value.kind_of?(::Hash)
|
13
|
+
end
|
7
14
|
|
8
|
-
def
|
15
|
+
def load(value)
|
9
16
|
if value.nil?
|
10
17
|
nil
|
11
|
-
elsif value.is_a?(String)
|
18
|
+
elsif value.is_a?(::String)
|
12
19
|
::JSON.load(value)
|
13
20
|
else
|
14
21
|
raise ArgumentError.new("+value+ of a property of JSON type must be nil or a String")
|
15
22
|
end
|
16
23
|
end
|
17
24
|
|
18
|
-
def
|
19
|
-
if value.nil? || value.is_a?(String)
|
25
|
+
def dump(value)
|
26
|
+
if value.nil? || value.is_a?(::String)
|
20
27
|
value
|
21
28
|
else
|
22
29
|
::JSON.dump(value)
|
23
30
|
end
|
24
31
|
end
|
25
32
|
|
26
|
-
def
|
27
|
-
|
28
|
-
value
|
29
|
-
else
|
30
|
-
::JSON.load(value.to_s)
|
31
|
-
end
|
33
|
+
def typecast_to_primitive(value)
|
34
|
+
::JSON.load(value.to_s)
|
32
35
|
end
|
33
36
|
end # class Json
|
34
37
|
JSON = Json
|
35
|
-
end #
|
38
|
+
end # class Property
|
36
39
|
end # module DataMapper
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Types
|
3
|
+
module Paranoid
|
4
|
+
module Base
|
5
|
+
def self.included(model)
|
6
|
+
model.extend ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
def paranoid_destroy
|
10
|
+
model.paranoid_properties.each do |name, block|
|
11
|
+
attribute_set(name, block.call(self))
|
12
|
+
end
|
13
|
+
save_self
|
14
|
+
self.persisted_state = Resource::State::Immutable.new(self)
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
# @api private
|
21
|
+
def _destroy(execute_hooks = true)
|
22
|
+
return false unless saved?
|
23
|
+
if execute_hooks
|
24
|
+
paranoid_destroy
|
25
|
+
else
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end # module Base
|
30
|
+
|
31
|
+
module ClassMethods
|
32
|
+
def with_deleted
|
33
|
+
with_exclusive_scope({}) { block_given? ? yield : all }
|
34
|
+
end
|
35
|
+
end # module ClassMethods
|
36
|
+
end # module Paranoid
|
37
|
+
end # module Types
|
38
|
+
end # module DataMapper
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'dm-types/paranoid/base'
|
2
|
+
|
3
|
+
module DataMapper
|
4
|
+
class Property
|
5
|
+
class ParanoidBoolean < Boolean
|
6
|
+
default false
|
7
|
+
lazy true
|
8
|
+
|
9
|
+
# @api private
|
10
|
+
def bind
|
11
|
+
property_name = name.inspect
|
12
|
+
|
13
|
+
model.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
14
|
+
include Paranoid::Base
|
15
|
+
|
16
|
+
set_paranoid_property(#{property_name}) { true }
|
17
|
+
|
18
|
+
default_scope(#{repository_name.inspect}).update(#{property_name} => false)
|
19
|
+
RUBY
|
20
|
+
end
|
21
|
+
end # class ParanoidBoolean
|
22
|
+
end # module Property
|
23
|
+
end # module DataMapper
|