ardm 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.
Files changed (179) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +35 -0
  3. data/Gemfile +13 -0
  4. data/LICENSE +21 -0
  5. data/README.md +70 -0
  6. data/Rakefile +4 -0
  7. data/ardm.gemspec +29 -0
  8. data/db/.gitignore +1 -0
  9. data/lib/ardm/active_record/associations.rb +80 -0
  10. data/lib/ardm/active_record/base.rb +49 -0
  11. data/lib/ardm/active_record/dirty.rb +25 -0
  12. data/lib/ardm/active_record/hooks.rb +31 -0
  13. data/lib/ardm/active_record/inheritance.rb +37 -0
  14. data/lib/ardm/active_record/is/state_machine.rb +21 -0
  15. data/lib/ardm/active_record/is.rb +22 -0
  16. data/lib/ardm/active_record/not_found.rb +7 -0
  17. data/lib/ardm/active_record/predicate_builder/array_handler.rb +31 -0
  18. data/lib/ardm/active_record/predicate_builder/rails3.rb +147 -0
  19. data/lib/ardm/active_record/predicate_builder/rails4.rb +139 -0
  20. data/lib/ardm/active_record/predicate_builder/relation_handler.rb +15 -0
  21. data/lib/ardm/active_record/predicate_builder.rb +19 -0
  22. data/lib/ardm/active_record/property.rb +357 -0
  23. data/lib/ardm/active_record/query.rb +108 -0
  24. data/lib/ardm/active_record/record.rb +70 -0
  25. data/lib/ardm/active_record/relation.rb +83 -0
  26. data/lib/ardm/active_record/repository.rb +38 -0
  27. data/lib/ardm/active_record/serialization.rb +164 -0
  28. data/lib/ardm/active_record/storage_names.rb +28 -0
  29. data/lib/ardm/active_record/validations.rb +111 -0
  30. data/lib/ardm/active_record.rb +43 -0
  31. data/lib/ardm/data_mapper/not_found.rb +5 -0
  32. data/lib/ardm/data_mapper/record.rb +41 -0
  33. data/lib/ardm/data_mapper.rb +5 -0
  34. data/lib/ardm/env.rb +5 -0
  35. data/lib/ardm/property/api_key.rb +30 -0
  36. data/lib/ardm/property/bcrypt_hash.rb +31 -0
  37. data/lib/ardm/property/binary.rb +23 -0
  38. data/lib/ardm/property/boolean.rb +29 -0
  39. data/lib/ardm/property/class.rb +19 -0
  40. data/lib/ardm/property/comma_separated_list.rb +28 -0
  41. data/lib/ardm/property/csv.rb +35 -0
  42. data/lib/ardm/property/date.rb +12 -0
  43. data/lib/ardm/property/datetime.rb +12 -0
  44. data/lib/ardm/property/decimal.rb +38 -0
  45. data/lib/ardm/property/discriminator.rb +65 -0
  46. data/lib/ardm/property/enum.rb +51 -0
  47. data/lib/ardm/property/epoch_time.rb +38 -0
  48. data/lib/ardm/property/file_path.rb +25 -0
  49. data/lib/ardm/property/flag.rb +65 -0
  50. data/lib/ardm/property/float.rb +18 -0
  51. data/lib/ardm/property/integer.rb +24 -0
  52. data/lib/ardm/property/invalid_value_error.rb +22 -0
  53. data/lib/ardm/property/ip_address.rb +35 -0
  54. data/lib/ardm/property/json.rb +49 -0
  55. data/lib/ardm/property/lookup.rb +29 -0
  56. data/lib/ardm/property/numeric.rb +40 -0
  57. data/lib/ardm/property/object.rb +36 -0
  58. data/lib/ardm/property/paranoid_boolean.rb +18 -0
  59. data/lib/ardm/property/paranoid_datetime.rb +17 -0
  60. data/lib/ardm/property/regexp.rb +22 -0
  61. data/lib/ardm/property/serial.rb +16 -0
  62. data/lib/ardm/property/slug.rb +29 -0
  63. data/lib/ardm/property/string.rb +40 -0
  64. data/lib/ardm/property/support/dirty_minder.rb +169 -0
  65. data/lib/ardm/property/support/flags.rb +41 -0
  66. data/lib/ardm/property/support/paranoid_base.rb +78 -0
  67. data/lib/ardm/property/text.rb +11 -0
  68. data/lib/ardm/property/time.rb +12 -0
  69. data/lib/ardm/property/uri.rb +27 -0
  70. data/lib/ardm/property/uuid.rb +65 -0
  71. data/lib/ardm/property/validation.rb +208 -0
  72. data/lib/ardm/property/yaml.rb +38 -0
  73. data/lib/ardm/property.rb +891 -0
  74. data/lib/ardm/property_set.rb +152 -0
  75. data/lib/ardm/query/expression.rb +85 -0
  76. data/lib/ardm/query/ext/symbol.rb +37 -0
  77. data/lib/ardm/query/operator.rb +64 -0
  78. data/lib/ardm/record.rb +1 -0
  79. data/lib/ardm/support/assertions.rb +8 -0
  80. data/lib/ardm/support/deprecate.rb +12 -0
  81. data/lib/ardm/support/descendant_set.rb +89 -0
  82. data/lib/ardm/support/equalizer.rb +48 -0
  83. data/lib/ardm/support/ext/array.rb +22 -0
  84. data/lib/ardm/support/ext/blank.rb +25 -0
  85. data/lib/ardm/support/ext/hash.rb +67 -0
  86. data/lib/ardm/support/ext/module.rb +47 -0
  87. data/lib/ardm/support/ext/object.rb +57 -0
  88. data/lib/ardm/support/ext/string.rb +24 -0
  89. data/lib/ardm/support/ext/try_dup.rb +12 -0
  90. data/lib/ardm/support/hook.rb +405 -0
  91. data/lib/ardm/support/lazy_array.rb +451 -0
  92. data/lib/ardm/support/local_object_space.rb +13 -0
  93. data/lib/ardm/support/logger.rb +201 -0
  94. data/lib/ardm/support/mash.rb +176 -0
  95. data/lib/ardm/support/naming_conventions.rb +90 -0
  96. data/lib/ardm/support/ordered_set.rb +380 -0
  97. data/lib/ardm/support/subject.rb +33 -0
  98. data/lib/ardm/support/subject_set.rb +250 -0
  99. data/lib/ardm/version.rb +3 -0
  100. data/lib/ardm.rb +56 -0
  101. data/spec/fixtures/api_user.rb +11 -0
  102. data/spec/fixtures/article.rb +22 -0
  103. data/spec/fixtures/bookmark.rb +14 -0
  104. data/spec/fixtures/invention.rb +5 -0
  105. data/spec/fixtures/network_node.rb +23 -0
  106. data/spec/fixtures/person.rb +17 -0
  107. data/spec/fixtures/software_package.rb +22 -0
  108. data/spec/fixtures/ticket.rb +12 -0
  109. data/spec/fixtures/tshirt.rb +15 -0
  110. data/spec/integration/api_key_spec.rb +25 -0
  111. data/spec/integration/bcrypt_hash_spec.rb +45 -0
  112. data/spec/integration/comma_separated_list_spec.rb +85 -0
  113. data/spec/integration/dirty_minder_spec.rb +197 -0
  114. data/spec/integration/enum_spec.rb +79 -0
  115. data/spec/integration/epoch_time_spec.rb +59 -0
  116. data/spec/integration/file_path_spec.rb +158 -0
  117. data/spec/integration/flag_spec.rb +72 -0
  118. data/spec/integration/ip_address_spec.rb +151 -0
  119. data/spec/integration/json_spec.rb +70 -0
  120. data/spec/integration/slug_spec.rb +65 -0
  121. data/spec/integration/uri_spec.rb +136 -0
  122. data/spec/integration/uuid_spec.rb +102 -0
  123. data/spec/integration/yaml_spec.rb +85 -0
  124. data/spec/public/property/binary_spec.rb +41 -0
  125. data/spec/public/property/boolean_spec.rb +30 -0
  126. data/spec/public/property/class_spec.rb +28 -0
  127. data/spec/public/property/date_spec.rb +22 -0
  128. data/spec/public/property/date_time_spec.rb +22 -0
  129. data/spec/public/property/decimal_spec.rb +23 -0
  130. data/spec/public/property/discriminator_spec.rb +133 -0
  131. data/spec/public/property/float_spec.rb +22 -0
  132. data/spec/public/property/integer_spec.rb +22 -0
  133. data/spec/public/property/object_spec.rb +103 -0
  134. data/spec/public/property/serial_spec.rb +22 -0
  135. data/spec/public/property/string_spec.rb +22 -0
  136. data/spec/public/property/text_spec.rb +23 -0
  137. data/spec/public/property/time_spec.rb +22 -0
  138. data/spec/public/property_spec.rb +316 -0
  139. data/spec/rcov.opts +6 -0
  140. data/spec/schema.rb +86 -0
  141. data/spec/semipublic/property/binary_spec.rb +14 -0
  142. data/spec/semipublic/property/boolean_spec.rb +48 -0
  143. data/spec/semipublic/property/class_spec.rb +36 -0
  144. data/spec/semipublic/property/date_spec.rb +44 -0
  145. data/spec/semipublic/property/date_time_spec.rb +47 -0
  146. data/spec/semipublic/property/decimal_spec.rb +83 -0
  147. data/spec/semipublic/property/discriminator_spec.rb +22 -0
  148. data/spec/semipublic/property/float_spec.rb +83 -0
  149. data/spec/semipublic/property/integer_spec.rb +83 -0
  150. data/spec/semipublic/property/lookup_spec.rb +27 -0
  151. data/spec/semipublic/property/serial_spec.rb +14 -0
  152. data/spec/semipublic/property/string_spec.rb +14 -0
  153. data/spec/semipublic/property/text_spec.rb +30 -0
  154. data/spec/semipublic/property/time_spec.rb +49 -0
  155. data/spec/semipublic/property_spec.rb +51 -0
  156. data/spec/shared/flags_shared_spec.rb +36 -0
  157. data/spec/shared/identity_function_group.rb +5 -0
  158. data/spec/shared/public_property_spec.rb +229 -0
  159. data/spec/shared/semipublic_property_spec.rb +159 -0
  160. data/spec/spec.opts +4 -0
  161. data/spec/spec_helper.rb +58 -0
  162. data/spec/unit/bcrypt_hash_spec.rb +154 -0
  163. data/spec/unit/csv_spec.rb +139 -0
  164. data/spec/unit/dirty_minder_spec.rb +64 -0
  165. data/spec/unit/enum_spec.rb +125 -0
  166. data/spec/unit/epoch_time_spec.rb +72 -0
  167. data/spec/unit/file_path_spec.rb +75 -0
  168. data/spec/unit/flag_spec.rb +114 -0
  169. data/spec/unit/ip_address_spec.rb +109 -0
  170. data/spec/unit/json_spec.rb +127 -0
  171. data/spec/unit/paranoid_boolean_spec.rb +142 -0
  172. data/spec/unit/paranoid_datetime_spec.rb +149 -0
  173. data/spec/unit/regexp_spec.rb +62 -0
  174. data/spec/unit/uri_spec.rb +64 -0
  175. data/spec/unit/yaml_spec.rb +111 -0
  176. data/tasks/spec.rake +40 -0
  177. data/tasks/yard.rake +9 -0
  178. data/tasks/yardstick.rake +19 -0
  179. metadata +350 -0
@@ -0,0 +1,35 @@
1
+ require 'ardm/property/string'
2
+ require 'ardm/property/support/dirty_minder'
3
+
4
+ if RUBY_VERSION >= '1.9.0'
5
+ require 'csv'
6
+ else
7
+ require 'fastercsv' # must be ~>1.5
8
+ CSV = FasterCSV unless defined?(CSV)
9
+ end
10
+
11
+ module Ardm
12
+ class Property
13
+ class Csv < String
14
+ load_as ::Array
15
+
16
+ def load(value)
17
+ case value
18
+ when ::String then CSV.parse(value)
19
+ when ::Array then value
20
+ end
21
+ end
22
+
23
+ def dump(value)
24
+ case value
25
+ when ::Array
26
+ CSV.generate { |csv| value.each { |row| csv << row } }
27
+ when ::String then value
28
+ end
29
+ end
30
+
31
+ include ::Ardm::Property::DirtyMinder
32
+
33
+ end # class Csv
34
+ end # class Property
35
+ end # module Ardm
@@ -0,0 +1,12 @@
1
+ require 'ardm/property/object'
2
+
3
+ module Ardm
4
+ class Property
5
+ class Date < Object
6
+ load_as ::Date
7
+ dump_as ::Date
8
+ coercion_method :to_date
9
+
10
+ end # class Date
11
+ end # class Property
12
+ end # module Ardm
@@ -0,0 +1,12 @@
1
+ require 'ardm/property/object'
2
+
3
+ module Ardm
4
+ class Property
5
+ class DateTime < Object
6
+ load_as ::DateTime
7
+ dump_as ::DateTime
8
+ coercion_method :to_datetime
9
+
10
+ end # class DateTime
11
+ end # class Property
12
+ end # module Ardm
@@ -0,0 +1,38 @@
1
+ require 'bigdecimal'
2
+
3
+ module Ardm
4
+ class Property
5
+ class Decimal < Numeric
6
+ load_as BigDecimal
7
+ dump_as BigDecimal
8
+ coercion_method :to_decimal
9
+
10
+ DEFAULT_PRECISION = 10
11
+ DEFAULT_SCALE = 0
12
+
13
+ precision(DEFAULT_PRECISION)
14
+ scale(DEFAULT_SCALE)
15
+
16
+ protected
17
+
18
+ def initialize(model, name, options = {})
19
+ super
20
+
21
+ [ :scale, :precision ].each do |key|
22
+ unless @options.key?(key)
23
+ warn "options[#{key.inspect}] should be set for #{self.class}, defaulting to #{send(key).inspect} (#{caller.first})"
24
+ end
25
+ end
26
+
27
+ unless @scale >= 0
28
+ raise ArgumentError, "scale must be equal to or greater than 0, but was #{@scale.inspect}"
29
+ end
30
+
31
+ unless @precision >= @scale
32
+ raise ArgumentError, "precision must be equal to or greater than scale, but was #{@precision.inspect} and scale was #{@scale.inspect}"
33
+ end
34
+ end
35
+
36
+ end # class Decimal
37
+ end # class Property
38
+ end # module Ardm
@@ -0,0 +1,65 @@
1
+ require 'ardm/property/class'
2
+
3
+ module Ardm
4
+ class Property
5
+ class Discriminator < Class
6
+ load_as ::Class
7
+ dump_as ::String
8
+ default lambda { |resource, property| resource.class }
9
+ required true
10
+
11
+ # ActiveRecord just stores the string name of the class.
12
+ # We dump false for a bad value because it results in a
13
+ # class that isn't in the "dump_as".
14
+ #
15
+ # Expects the class name to be a valid class name that is
16
+ # loaded and available.
17
+ def dump(value)
18
+ dumped = typecast(value)
19
+ dumped.name if dumped.is_a?(::Class)
20
+ end
21
+
22
+ def load(value)
23
+ typecast(value)
24
+ end
25
+
26
+ # @api private
27
+ def bind
28
+ model.inheritance_column = field
29
+ model.extend Model unless model < Model
30
+ end
31
+
32
+ module Model
33
+ def inherited(model)
34
+ super # setup self.descendants
35
+ #set_discriminator_scope_for(model)
36
+ end
37
+
38
+ def new(*args, &block)
39
+ if args.size == 1 && args.first.kind_of?(Hash)
40
+ discriminator = properties.discriminator
41
+
42
+ if discriminator_value = args.first[discriminator.name]
43
+ model = discriminator.typecast(discriminator_value)
44
+
45
+ if model.kind_of?(Model) && !model.equal?(self)
46
+ return model.new(*args, &block)
47
+ end
48
+ end
49
+ end
50
+
51
+ super
52
+ end
53
+
54
+ private
55
+
56
+ def set_discriminator_scope_for(model)
57
+ discriminator = self.properties.discriminator
58
+ model.scoped.with_default_scope.update_all(discriminator.field => model.descendants.dup << model)
59
+ rescue ::ActiveRecord::ConnectionNotEstablished => e
60
+ puts "Error was raised but it seems to be an ActiveRecord 3.2 error, fixed in 4:\n#{e}"
61
+ end
62
+ end
63
+ end # class Discriminator
64
+ end # class Property
65
+ end # module Ardm
@@ -0,0 +1,51 @@
1
+ require 'ardm/property/object'
2
+ require 'ardm/property/support/flags'
3
+
4
+ module Ardm
5
+ class Property
6
+ class Enum < Object
7
+ include Flags
8
+
9
+ load_as ::Object
10
+ dump_as ::Integer
11
+
12
+ def initialize(model, name, options = {})
13
+ @flag_map = {}
14
+
15
+ flags = options.fetch(:flags, self.class.flags)
16
+ flags.each_with_index do |flag, i|
17
+ @flag_map[i + 1] = flag
18
+ end
19
+
20
+ if self.class.accepted_options.include?(:set) && !options.include?(:set)
21
+ options[:set] = @flag_map.values_at(*@flag_map.keys.sort)
22
+ end
23
+
24
+ super
25
+ end
26
+
27
+ def load(value)
28
+ flag_map[value.to_i]
29
+ end
30
+
31
+ def dump(value)
32
+ case value
33
+ when ::Array then value.collect { |v| dump(v) }
34
+ else flag_map.invert[typecast(value)]
35
+ end
36
+ end
37
+
38
+ def typecast(value)
39
+ return if value.nil?
40
+ # Attempt to typecast using the class of the first item in the map.
41
+ case flag_map[1]
42
+ when ::Symbol then value.to_sym
43
+ when ::String then value.to_s
44
+ when ::Fixnum then value.to_i
45
+ else value
46
+ end
47
+ end
48
+
49
+ end # class Enum
50
+ end # class Property
51
+ end # module Ardm
@@ -0,0 +1,38 @@
1
+ require 'ardm/property/time'
2
+
3
+ module Ardm
4
+ class Property
5
+ class EpochTime < Time
6
+ dump_as ::Integer
7
+
8
+ def load(value)
9
+ if value.kind_of?(::Numeric)
10
+ ::Time.at(value.to_i)
11
+ else
12
+ value
13
+ end
14
+ end
15
+
16
+ def dump(value)
17
+ value.to_i if value
18
+ end
19
+
20
+ def typecast(value)
21
+ case value
22
+ when ::Time then value
23
+ when ::Numeric, /\A\d+\z/ then ::Time.at(value.to_i)
24
+ when ::DateTime then datetime_to_time(value)
25
+ when ::String then ::Time.parse(value)
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def datetime_to_time(datetime)
32
+ utc = datetime.new_offset(0)
33
+ ::Time.utc(utc.year, utc.month, utc.day, utc.hour, utc.min, utc.sec)
34
+ end
35
+
36
+ end # class EpochTime
37
+ end # class Property
38
+ end # module Ardm
@@ -0,0 +1,25 @@
1
+ require 'pathname'
2
+ require 'ardm/property/string'
3
+
4
+ module Ardm
5
+ class Property
6
+ class FilePath < String
7
+ load_as Pathname
8
+
9
+ length 255
10
+
11
+ def load(value)
12
+ Pathname.new(value) unless Ardm::Ext.blank?(value)
13
+ end
14
+
15
+ def dump(value)
16
+ value.to_s unless Ardm::Ext.blank?(value)
17
+ end
18
+
19
+ def typecast(value)
20
+ load(value)
21
+ end
22
+
23
+ end # class FilePath
24
+ end # class Property
25
+ end # module Ardm
@@ -0,0 +1,65 @@
1
+ require 'ardm/property/object'
2
+ require 'ardm/property/support/flags'
3
+
4
+ module Ardm
5
+ class Property
6
+ class Flag < Object
7
+ include Flags
8
+
9
+ load_as ::Object
10
+ dump_as ::Integer
11
+
12
+ def initialize(model, name, options = {})
13
+ super
14
+
15
+ @flag_map = {}
16
+
17
+ flags = options.fetch(:flags, self.class.flags)
18
+ flags.each_with_index do |flag, i|
19
+ flag_map[i] = flag
20
+ end
21
+ end
22
+
23
+ def load(value)
24
+ return [] if value.nil? || value <= 0
25
+
26
+ begin
27
+ matches = []
28
+
29
+ 0.upto(flag_map.size - 1) do |i|
30
+ matches << flag_map[i] if value[i] == 1
31
+ end
32
+
33
+ matches.compact
34
+ rescue TypeError, Errno::EDOM
35
+ []
36
+ end
37
+ end
38
+
39
+ def dump(value)
40
+ unless value.nil?
41
+ flags = Array(value).map { |flag| flag.to_sym }
42
+ flags.uniq!
43
+
44
+ flag = 0
45
+
46
+ flag_map.invert.values_at(*flags).each do |i|
47
+ next if i.nil?
48
+ flag += (1 << i)
49
+ end
50
+
51
+ flag
52
+ end
53
+ end
54
+
55
+ def typecast(value)
56
+ case value
57
+ when nil then nil
58
+ when ::Array then value.map { |v| v.to_sym }
59
+ else [value.to_sym]
60
+ end
61
+ end
62
+
63
+ end # class Flag
64
+ end # class Property
65
+ end # module Ardm
@@ -0,0 +1,18 @@
1
+ require 'ardm/property/numeric'
2
+
3
+ module Ardm
4
+ class Property
5
+ class Float < Numeric
6
+ load_as ::Float
7
+ dump_as ::Float
8
+ coercion_method :to_float
9
+
10
+ DEFAULT_PRECISION = 10
11
+ DEFAULT_SCALE = nil
12
+
13
+ precision(DEFAULT_PRECISION)
14
+ scale(DEFAULT_SCALE)
15
+
16
+ end # class Float
17
+ end # class Property
18
+ end # module Ardm
@@ -0,0 +1,24 @@
1
+ require 'ardm/property/numeric'
2
+
3
+ module Ardm
4
+ class Property
5
+ class Integer < Numeric
6
+ load_as ::Integer
7
+ dump_as ::Integer
8
+ coercion_method :to_integer
9
+
10
+ accept_options :serial
11
+
12
+ protected
13
+
14
+ # @api semipublic
15
+ def initialize(model, name, options = {})
16
+ if options.key?(:serial) && !kind_of?(Serial)
17
+ raise "Integer #{name} with explicit :serial option is deprecated, use Serial instead (#{caller[2]})"
18
+ end
19
+ super
20
+ end
21
+
22
+ end # class Integer
23
+ end # class Property
24
+ end # module Ardm
@@ -0,0 +1,22 @@
1
+ module Ardm
2
+ class Property
3
+ # Exception raised when Ardm is about to work with
4
+ # invalid property values.
5
+ class InvalidValueError < StandardError
6
+ attr_reader :property, :value
7
+
8
+ def initialize(property, value)
9
+ msg = "Invalid value %s for property %s (%s) on model %s" %
10
+ [ value.inspect,
11
+ property.name.inspect,
12
+ property.class.name,
13
+ property.model.name
14
+ ]
15
+ super(msg)
16
+ @property = property
17
+ @value = value
18
+ end
19
+
20
+ end # class InvalidValueError
21
+ end # class Property
22
+ end # module Ardm
@@ -0,0 +1,35 @@
1
+ require 'ipaddr'
2
+ require 'ardm/property/string'
3
+
4
+ module Ardm
5
+ class Property
6
+ class IPAddress < String
7
+ load_as IPAddr
8
+
9
+ length 39
10
+
11
+ def load(value)
12
+ if value.nil? || value_loaded?(value)
13
+ value
14
+ elsif value.is_a?(::String)
15
+ unless value.empty?
16
+ IPAddr.new(value)
17
+ else
18
+ IPAddr.new("0.0.0.0")
19
+ end
20
+ else
21
+ raise ArgumentError.new("+value+ must be nil or a String")
22
+ end
23
+ end
24
+
25
+ def dump(value)
26
+ value.to_s unless value.nil?
27
+ end
28
+
29
+ def typecast(value)
30
+ load(value) unless value.nil?
31
+ end
32
+
33
+ end # class IPAddress
34
+ end # class Property
35
+ end # module Ardm
@@ -0,0 +1,49 @@
1
+ require 'ardm/property/text'
2
+ require 'ardm/property/support/dirty_minder'
3
+ require 'multi_json'
4
+
5
+ module Ardm
6
+ class Property
7
+ class Json < Text
8
+ load_as ::Object
9
+
10
+ def load(value)
11
+ if value.nil? || value_loaded?(value)
12
+ value
13
+ elsif value.is_a?(::String)
14
+ typecast(value)
15
+ else
16
+ raise ArgumentError.new("+value+ of a property of JSON type must be nil or a String")
17
+ end
18
+ end
19
+
20
+ def dump(value)
21
+ if value.nil? || value.is_a?(::String)
22
+ value
23
+ else
24
+ MultiJson.dump(value)
25
+ end
26
+ end
27
+
28
+ def typecast(value)
29
+ return if value.nil?
30
+
31
+ if value_loaded?(value)
32
+ value
33
+ else
34
+ MultiJson.load(value.to_s)
35
+ end
36
+ end
37
+
38
+ def value_loaded?(value)
39
+ value.kind_of?(::Array) || value.kind_of?(::Hash)
40
+ end
41
+
42
+ include ::Ardm::Property::DirtyMinder
43
+
44
+ end # class Json
45
+
46
+ JSON = Json
47
+
48
+ end # class Property
49
+ end # module Ardm
@@ -0,0 +1,29 @@
1
+ require 'ardm/property'
2
+
3
+ module Ardm
4
+ class Property
5
+ module Lookup
6
+
7
+ # Provides transparent access to the Properties defined in
8
+ # {Property}.
9
+ #
10
+ # @param [Symbol] name
11
+ # The name of the property to lookup.
12
+ #
13
+ # @return [Property]
14
+ # The property with the given name.
15
+ #
16
+ # @raise [NameError]
17
+ # The property could not be found.
18
+ #
19
+ # @api private
20
+ #
21
+ # @since 1.0.1
22
+ #
23
+ def const_missing(name)
24
+ Property.find_class(name.to_s) || super
25
+ end
26
+
27
+ end # module Lookup
28
+ end # class Property
29
+ end # module Ardm
@@ -0,0 +1,40 @@
1
+ require 'ardm/property/object'
2
+
3
+ module Ardm
4
+ class Property
5
+ class Numeric < Object
6
+ accept_options :precision, :scale, :min, :max
7
+
8
+ attr_reader :precision, :scale, :min, :max
9
+
10
+ DEFAULT_NUMERIC_MIN = 0
11
+ DEFAULT_NUMERIC_MAX = 2**31-1
12
+
13
+ protected
14
+
15
+ def initialize(model, name, options = {})
16
+ super
17
+
18
+ if kind_of?(Decimal) || kind_of?(Float)
19
+ @precision = @options.fetch(:precision)
20
+ @scale = @options.fetch(:scale)
21
+
22
+ unless @precision > 0
23
+ raise ArgumentError, "precision must be greater than 0, but was #{@precision.inspect}"
24
+ end
25
+ end
26
+
27
+ if @options.key?(:min) || @options.key?(:max)
28
+ @min = @options.fetch(:min, self.class::DEFAULT_NUMERIC_MIN)
29
+ @max = @options.fetch(:max, self.class::DEFAULT_NUMERIC_MAX)
30
+
31
+ if @max < DEFAULT_NUMERIC_MIN && !@options.key?(:min)
32
+ raise ArgumentError, "min should be specified when the max is less than #{DEFAULT_NUMERIC_MIN}"
33
+ elsif @max < @min
34
+ raise ArgumentError, "max must be less than the min, but was #{@max} while the min was #{@min}"
35
+ end
36
+ end
37
+ end
38
+ end # class Numeric
39
+ end # class Property
40
+ end # module Ardm
@@ -0,0 +1,36 @@
1
+ require 'ardm/property'
2
+
3
+ module Ardm
4
+ class Property
5
+ class Object < Property
6
+ load_as ::Object
7
+ dump_as ::Object
8
+ coercion_method :to_object
9
+
10
+ # @api semipublic
11
+ def dump(value)
12
+ instance_of?(Object) ? marshal(value) : value
13
+ end
14
+
15
+ # @api semipublic
16
+ def load(value)
17
+ typecast(instance_of?(Object) ? unmarshal(value) : value)
18
+ end
19
+
20
+ # @api semipublic
21
+ def marshal(value)
22
+ [ Marshal.dump(value) ].pack('m') unless value.nil?
23
+ end
24
+
25
+ # @api semipublic
26
+ def unmarshal(value)
27
+ Marshal.load(value.unpack('m').first) unless value.nil?
28
+ end
29
+
30
+ # @api private
31
+ def to_child_key
32
+ self.class
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,18 @@
1
+ require 'ardm/property/boolean'
2
+ require 'ardm/property/support/paranoid_base'
3
+
4
+ module Ardm
5
+ class Property
6
+ class ParanoidBoolean < Boolean
7
+ default false
8
+ lazy true
9
+
10
+ # @api private
11
+ def bind
12
+ model.send(:include, Ardm::Property::ParanoidBase)
13
+ model.set_paranoid_property(name) { true }
14
+ model.set_paranoid_scope(model.arel_table[name].eq(false))
15
+ end
16
+ end # class ParanoidBoolean
17
+ end # class Property
18
+ end # module Ardm
@@ -0,0 +1,17 @@
1
+ require 'ardm/property/datetime'
2
+ require 'ardm/property/support/paranoid_base'
3
+
4
+ module Ardm
5
+ class Property
6
+ class ParanoidDateTime < DateTime
7
+ lazy true
8
+
9
+ # @api private
10
+ def bind
11
+ model.send(:include, Ardm::Property::ParanoidBase)
12
+ model.set_paranoid_property(name) { ::DateTime.now }
13
+ model.set_paranoid_scope(model.arel_table[name].eq(nil))
14
+ end
15
+ end # class ParanoidDateTime
16
+ end # class Property
17
+ end # module Ardm
@@ -0,0 +1,22 @@
1
+ require 'ardm/property/string'
2
+
3
+ module Ardm
4
+ class Property
5
+ class Regexp < String
6
+ load_as ::Regexp
7
+
8
+ def load(value)
9
+ ::Regexp.new(value) unless value.nil?
10
+ end
11
+
12
+ def dump(value)
13
+ value.source unless value.nil?
14
+ end
15
+
16
+ def typecast(value)
17
+ load(value)
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ require 'ardm/property/integer'
2
+
3
+ module Ardm
4
+ class Property
5
+ class Serial < Integer
6
+ serial true
7
+ min 1
8
+
9
+ # @api private
10
+ def to_child_key
11
+ Property::Integer
12
+ end
13
+
14
+ end # class Text
15
+ end # class Property
16
+ end # module Ardm