public
Rubygem
Description: DataMapper - Core
Homepage: http://datamapper.org
Clone URL: git://github.com/sam/dm-core.git
somebee (author)
Wed May 07 13:54:30 -0700 2008
commit  ce8ccc44ddf810de2f037e2122ece5646200aea2
tree    2a4927e06a863d2ef720d0c0be549e4373a44145
parent  6cc58071331ded6b6f5d8a1cc5a04e4e653f683d parent  8b86e2e9ed0e44af3f4ccf43b1f194f45000af22
dm-core / lib / data_mapper / type.rb
100644 166 lines (146 sloc) 4.337 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
module DataMapper
 
  # = Types
  # Provides means of writing custom types for properties. Each type is based
  # on a ruby primitive and handles its own serialization and materialization,
  # and therefore is responsible for providing those methods.
  #
  # To see complete list of supported types, see documentation for
  # DataMapper::Property::TYPES
  #
  # == Defining new Types
  # To define a new type, subclass DataMapper::Type, pick ruby primitive, and
  # set the options for this type.
  #
  # class MyType < DataMapper::Type
  # primitive String
  # size 10
  # end
  #
  # Following this, you will be able to use MyType as a type for any given
  # property. If special materialization and serialization is required,
  # override the class methods
  #
  # class MyType < DataMapper::Type
  # primitive String
  # size 10
  #
  # def self.dump(value, property)
  # <work some magic>
  # end
  #
  # def self.load(value)
  # <work some magic>
  # end
  # end
  class Type
    PROPERTY_OPTIONS = [
      :public, :protected, :private, :accessor, :reader, :writer,
      :lazy, :default, :nullable, :key, :serial, :field, :size, :length,
      :format, :index, :check, :ordinal, :auto_validation, :validates, :unique,
      :lock, :track, :scale, :precision
    ]
 
    PROPERTY_OPTION_ALIASES = {
      :size => [ :length ]
    }
 
    class << self
 
      def configure(primitive_type, options)
        @_primitive_type = primitive_type
        @_options = options
 
        def self.inherited(base)
          base.primitive @_primitive_type
 
          @_options.each do |k, v|
            base.send(k, v)
          end
        end
 
        self
      end
 
      # The Ruby primitive type to use as basis for this type. See
      # DataMapper::Property::TYPES for list of types.
      #
      # ==== Parameters
      # primitive<Class, nil>::
      # The class for the primitive. If nil is passed in, it returns the
      # current primitive
      #
      # ==== Returns
      # Class:: if the <primitive> param is nil, return the current primitive.
      #
      # @public
      def primitive(primitive = nil)
        return @primitive if primitive.nil?
 
        @primitive = primitive
      end
 
      #load DataMapper::Property options
      PROPERTY_OPTIONS.each do |property_option|
        self.class_eval <<-EOS, __FILE__, __LINE__
def #{property_option}(arg = nil)
return @#{property_option} if arg.nil?
 
@#{property_option} = arg
end
EOS
      end
 
      #create property aliases
      PROPERTY_OPTION_ALIASES.each do |property_option, aliases|
        aliases.each do |ali|
          self.class_eval <<-EOS, __FILE__, __LINE__
alias #{ali} #{property_option}
EOS
        end
      end
 
      # Gives all the options set on this type
      #
      # ==== Returns
      # Hash:: with all options and their values set on this type
      #
      # @public
      def options
        options = {}
        PROPERTY_OPTIONS.each do |method|
          next if (value = send(method)).nil?
          options[method] = value
        end
        options
      end
    end
 
    # Stub instance method for dumping
    #
    # ==== Parameters
    # value<Object, nil>::
    # The value to dump
    # property<Property, nil>::
    # The property the type is being used by
    #
    # ==== Returns
    # Object:: Dumped object
    #
    #
    # @public
    def self.dump(value, property)
        value
    end
 
    # Stub instance method for loading
    #
    # ==== Parameters
    # value<Object, nil>::
    # The value to serialize
    # property<Property, nil>::
    # The property the type is being used by
    #
    # ==== Returns
    # Object:: Serialized object. Must be the same type as the ruby primitive
    #
    #
    # @public
    def self.load(value, property)
      value
    end
    
    def self.bind(property)
      # This method should not modify the state of this type class, and
      # should produce no side-effects on the type class. It's just a
      # hook to allow your custom-type to modify the property it's bound to.
    end
 
  end # class Type
 
  def self.Type(primitive_type, options = {})
    Class.new(Type).configure(primitive_type, options)
  end
 
end # module DataMapper