og 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/CHANGELOG +27 -0
  2. data/INSTALL +56 -0
  3. data/{README.og → README} +3 -3
  4. data/Rakefile +7 -73
  5. data/benchmark/bench.rb +75 -0
  6. data/benchmark/sqlite-no-prepare.1.txt +13 -0
  7. data/benchmark/sqlite-no-prepare.2.txt +13 -0
  8. data/benchmark/sqlite-prepare.1.txt +13 -0
  9. data/benchmark/sqlite-prepare.2.txt +13 -0
  10. data/doc/AUTHORS +0 -9
  11. data/{RELEASES.og → doc/RELEASES} +15 -0
  12. data/doc/config.txt +35 -0
  13. data/doc/tutorial.txt +595 -0
  14. data/examples/{og/README → README} +1 -1
  15. data/examples/{og/mock_example.rb → mock_example.rb} +1 -1
  16. data/examples/{og/mysql_to_psql.rb → mysql_to_psql.rb} +1 -1
  17. data/examples/{og/run.rb → run.rb} +1 -1
  18. data/install.rb +8 -5
  19. data/lib/og.rb +13 -8
  20. data/lib/og/adapter.rb +1 -1
  21. data/lib/og/adapters/filesys.rb +1 -1
  22. data/lib/og/adapters/mysql.rb +4 -3
  23. data/lib/og/adapters/oracle.rb +1 -1
  24. data/lib/og/adapters/psql.rb +4 -3
  25. data/lib/og/adapters/sqlite.rb +1 -1
  26. data/lib/og/backend.rb +1 -1
  27. data/lib/og/connection.rb +1 -1
  28. data/lib/og/database.rb +1 -1
  29. data/lib/og/meta.rb +13 -2
  30. data/lib/og/observer.rb +1 -1
  31. data/lib/og/typemacros.rb +1 -1
  32. data/lib/og/validation.rb +81 -0
  33. data/test/og/tc_validation.rb +89 -0
  34. metadata +33 -65
  35. data/ChangeLog +0 -1549
  36. data/lib/glue.rb +0 -55
  37. data/lib/glue/array.rb +0 -61
  38. data/lib/glue/attribute.rb +0 -83
  39. data/lib/glue/cache.rb +0 -138
  40. data/lib/glue/flexob.rb +0 -12
  41. data/lib/glue/hash.rb +0 -122
  42. data/lib/glue/inflector.rb +0 -91
  43. data/lib/glue/logger.rb +0 -147
  44. data/lib/glue/misc.rb +0 -14
  45. data/lib/glue/mixins.rb +0 -36
  46. data/lib/glue/number.rb +0 -24
  47. data/lib/glue/object.rb +0 -32
  48. data/lib/glue/pool.rb +0 -60
  49. data/lib/glue/property.rb +0 -408
  50. data/lib/glue/string.rb +0 -162
  51. data/lib/glue/time.rb +0 -85
  52. data/lib/glue/validation.rb +0 -394
  53. data/vendor/extensions/_base.rb +0 -153
  54. data/vendor/extensions/_template.rb +0 -36
  55. data/vendor/extensions/all.rb +0 -21
  56. data/vendor/extensions/array.rb +0 -68
  57. data/vendor/extensions/binding.rb +0 -224
  58. data/vendor/extensions/class.rb +0 -50
  59. data/vendor/extensions/continuation.rb +0 -71
  60. data/vendor/extensions/enumerable.rb +0 -250
  61. data/vendor/extensions/hash.rb +0 -23
  62. data/vendor/extensions/io.rb +0 -58
  63. data/vendor/extensions/kernel.rb +0 -42
  64. data/vendor/extensions/module.rb +0 -114
  65. data/vendor/extensions/numeric.rb +0 -230
  66. data/vendor/extensions/object.rb +0 -164
  67. data/vendor/extensions/ostruct.rb +0 -41
  68. data/vendor/extensions/string.rb +0 -316
  69. data/vendor/extensions/symbol.rb +0 -28
@@ -1,91 +0,0 @@
1
- # Code from RubyOnRails (http://www.rubyonrails.com)
2
- # Copyright (c) 2004 David Heinemeier Hansson.
3
-
4
- module N
5
-
6
- # The Inflector transforms words from singular to plural,
7
- # class names to table names, modulized class names to ones without,
8
- # and class names to foreign keys.
9
-
10
- module Inflector
11
- extend self
12
-
13
- def pluralize(word)
14
- result = word.dup
15
- plural_rules.each do |(rule, replacement)|
16
- break if result.gsub!(rule, replacement)
17
- end
18
- return result
19
- end
20
-
21
- def singularize(word)
22
- result = word.dup
23
- singular_rules.each do |(rule, replacement)|
24
- break if result.gsub!(rule, replacement)
25
- end
26
- return result
27
- end
28
-
29
- def camelize(lower_case_and_underscored_word)
30
- lower_case_and_underscored_word.gsub(/(^|_)(.)/){$2.upcase}
31
- end
32
-
33
- def underscore(camel_cased_word)
34
- camel_cased_word.gsub(/([A-Z]+)([A-Z])/,'\1_\2').gsub(/([a-z])([A-Z])/,'\1_\2').downcase
35
- end
36
-
37
- def demodulize(class_name_in_module)
38
- class_name_in_module.gsub(/^.*::/, '')
39
- end
40
-
41
- def foreign_key(class_name, separate_class_name_and_id_with_underscore = true)
42
- Inflector.underscore(Inflector.demodulize(class_name)) +
43
- (separate_class_name_and_id_with_underscore ? "_id" : "id")
44
- end
45
-
46
- # Convert a class to a name.
47
-
48
- def name(klass)
49
- Inflector.underscore(Inflector.demodulize(klass.to_s))
50
- end
51
-
52
- # Convert a class to a name in plural
53
-
54
- def plural_name(klass)
55
- Inflector.pluralize(Inflector.underscore(Inflector.demodulize(klass.to_s)))
56
- end
57
-
58
- private
59
- def plural_rules #:doc:
60
- [
61
- [/(x|ch|ss)$/, '\1es'], # search, switch, fix, box, process, address
62
- [/([^aeiouy]|qu)y$/, '\1ies'], # query, ability, agency
63
- [/(?:([^f])fe|([lr])f)$/, '\1\2ves'], # half, safe, wife
64
- [/sis$/, 'ses'], # basis, diagnosis
65
- [/([ti])um$/, '\1a'], # datum, medium
66
- [/person$/, 'people'], # person, salesperson
67
- [/man$/, 'men'], # man, woman, spokesman
68
- [/child$/, 'children'], # child
69
- [/s$/, 's'], # no change (compatibility)
70
- [/$/, 's']
71
- ]
72
- end
73
-
74
- def singular_rules #:doc:
75
- [
76
- [/(x|ch|ss)es$/, '\1'],
77
- [/([^aeiouy]|qu)ies$/, '\1y'],
78
- [/([lr])ves$/, '\1f'],
79
- [/([^f])ves$/, '\1fe'],
80
- [/(analy|ba|diagno|parenthe|progno|synop|the)ses$/, '\1sis'],
81
- [/([ti])a$/, '\1um'],
82
- [/people$/, 'person'],
83
- [/men$/, 'man'],
84
- [/status$/, 'status'],
85
- [/children$/, 'child'],
86
- [/s$/, '']
87
- ]
88
- end
89
- end
90
-
91
- end
@@ -1,147 +0,0 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: logger.rb 248 2005-01-31 13:38:34Z gmosx $
4
-
5
- require 'logger'
6
-
7
- # A simple wrapper arround the Ruby logger. Mainly for
8
- # compatibility purposes.
9
-
10
- class Logger
11
- alias_method :devel, :debug
12
- alias_method :fine, :debug
13
-
14
- # Prints a trace message to DEBUGLOG (at debug level).
15
- # Useful for emitting the value of variables, etc. Use
16
- # like this:
17
- #
18
- # x = y = 5
19
- # trace 'x' # -> 'x = 5'
20
- # trace 'x ** y' # -> 'x ** y = 3125'
21
- #
22
- # If you have a more complicated value, like an array of
23
- # hashes, then you'll probably want to use an alternative
24
- # output format. For instance:
25
- #
26
- # trace 'value', :yaml
27
- #
28
- # Valid output format values (the _style_ parameter) are:
29
- #
30
- # :p :inspect
31
- # :pp (pretty-print, using 'pp' library)
32
- # :s :to_s
33
- # :y :yaml :to_yaml (using the 'yaml' library')
34
- #
35
- # The default is <tt>:p</tt>.
36
- #
37
- # CREDITS:
38
- #
39
- # This code comes straight from the dev-utils Gem.
40
- # Author: Gavin Sinclair <gsinclair@soyabean.com.au>
41
-
42
- def trace(expr, style=:p)
43
- unless expr.respond_to? :to_str
44
- warn "trace: Can't evaluate the given value: #{caller.first}"
45
- else
46
- require 'extensions/binding'
47
-
48
- Binding.of_caller do |b|
49
- value = b.eval(expr.to_str)
50
- formatter = TRACE_STYLES[style] || :inspect
51
- case formatter
52
- when :pp then require 'pp'
53
- when :y, :yaml, :to_yaml then require 'yaml'
54
- end
55
- value_s = value.send(formatter)
56
- message = "#{expr} = #{value_s}"
57
- lines = message.split(/\n/)
58
- indent = " "
59
- debug(lines.shift)
60
- lines.each do |line|
61
- debug(indent + line)
62
- end
63
- end
64
- end
65
- end
66
- TRACE_STYLES = {} # :nodoc:
67
- TRACE_STYLES.update( :pp => :pp_s, :s => :to_s, :p => :inspect, :y => :to_yaml,
68
- :yaml => :to_yaml, :inspect => :inspect, :to_yaml => :to_yaml )
69
-
70
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
71
- # Global logger interface.
72
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
73
-
74
- # Override the logger with your custom version.
75
- #
76
- @@global_logger = Logger.new(STDERR)
77
-
78
- def self.set(logger)
79
- @@global_logger = logger
80
- end
81
-
82
- def self.get
83
- @@global_logger
84
- end
85
-
86
- def self.warn(str)
87
- @@global_logger.warn(str)
88
- end
89
-
90
- def self.info(str)
91
- @@global_logger.info(str)
92
- end
93
-
94
- def self.debug(str)
95
- @@global_logger.debug(str)
96
- end
97
-
98
- def self.error(str)
99
- @@global_logger.error(str)
100
- end
101
-
102
- #--
103
- # Saddly have to duplicate the code to make
104
- # Binding.of_caller work.
105
- #++
106
- def self.trace(expr, style=:p)
107
- unless expr.respond_to? :to_str
108
- warn "trace: Can't evaluate the given value: #{caller.first}"
109
- else
110
- require 'extensions/binding'
111
-
112
- Binding.of_caller do |b|
113
- value = b.eval(expr.to_str)
114
- formatter = TRACE_STYLES[style] || :inspect
115
- case formatter
116
- when :pp then require 'pp'
117
- when :y, :yaml, :to_yaml then require 'yaml'
118
- end
119
- value_s = value.send(formatter)
120
- message = "#{expr} = #{value_s}"
121
- lines = message.split(/\n/)
122
- indent = " "
123
- debug(lines.shift)
124
- lines.each do |line|
125
- debug(indent + line)
126
- end
127
- end
128
- end
129
- end
130
-
131
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
132
-
133
- private
134
-
135
- # the default Ruby logger has a hardwired silly format.
136
- # we use some Ruby magic to fix it!
137
-
138
- remove_const "Format"
139
-
140
- Format = "%5s: %s\n"
141
-
142
- def format_message(severity, timestamp, msg, progname)
143
- Format % [severity, msg]
144
- end
145
-
146
- end
147
-
@@ -1,14 +0,0 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id$
4
-
5
- # Executes a Ruby block without warnings.
6
-
7
- def silence_warnings
8
- old_verbose, $VERBOSE = $VERBOSE, nil
9
- begin
10
- yield
11
- ensure
12
- $VERBOSE = old_verbose
13
- end
14
- end
@@ -1,36 +0,0 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id$
4
-
5
- module N
6
-
7
- # Generic expiring functionality mixin.
8
-
9
- module Expirable
10
- attr_accessor :expires
11
-
12
- # Set the expires timeout for this entry.
13
-
14
- def expires_after(timeout = (60*60*24))
15
- @expires = Time.now + timeout
16
- end
17
-
18
- # Set the expire timeout for this entry. The timeout happens
19
- # after (base + rand(spread)) seconds.
20
-
21
- def expires_spread(base, spread)
22
- @expires = Time.now + base + rand(spread)
23
- end
24
-
25
- # Is this entry expired?
26
-
27
- def expired?
28
- if @expires.nil? or (Time.now > @expires)
29
- return true
30
- else
31
- return false
32
- end
33
- end
34
- end
35
-
36
- end
@@ -1,24 +0,0 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: number.rb 249 2005-02-04 14:03:00Z gmosx $
4
-
5
- module N;
6
-
7
- # Implement as a module to avoid class polution. You can
8
- # still use Ruby's advanced features to include the module in your
9
- # class. Passing the object to act upon allows to check for nil,
10
- # which isn't possible if you use self.
11
-
12
- module NumberUtils
13
-
14
- # Returns the multiple ceil of a number
15
- #
16
- def self.ceil_multiple(num, multiple)
17
- # gmosx: to_f is needed!s
18
- # gmosx: IS THERE a more optimized way to do this?
19
- return ((num.to_f/multiple).ceil*multiple)
20
- end
21
-
22
- end
23
-
24
- end
@@ -1,32 +0,0 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: object.rb 259 2005-02-15 08:54:54Z gmosx $
4
-
5
- # Code from RubyOnRails (http://www.rubyonrails.com)
6
-
7
- class Object #:nodoc:
8
- def remove_subclasses_of(superclass)
9
- subclasses_of(superclass).each { |subclass| Object.send(:remove_const, subclass) rescue nil }
10
- end
11
-
12
- def subclasses_of(superclass)
13
- subclasses = []
14
- ObjectSpace.each_object(Class) do |k|
15
- next if !k.ancestors.include?(superclass) || superclass == k || k.to_s.include?("::") || subclasses.include?(k.to_s)
16
- subclasses << k.to_s
17
- end
18
- subclasses
19
- end
20
- end
21
-
22
- # Code from RubyOnRails (http://www.rubyonrails.com)
23
-
24
- class Class #:nodoc:
25
- def remove_subclasses
26
- Object.remove_subclasses_of(self)
27
- end
28
-
29
- def subclasses
30
- Object.subclasses_of(self)
31
- end
32
- end
@@ -1,60 +0,0 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: pool.rb 266 2005-02-28 14:50:48Z gmosx $
4
-
5
- require 'thread'
6
- require 'monitor'
7
-
8
- module N
9
-
10
- # Generalized object pool implementation. Implemented as a thread
11
- # safe stack. Exclusive locking is needed both for push and pop.
12
- #
13
- # INVESTIGATE: Could use the SizedQueue/Queue.
14
-
15
- class Pool < Array
16
- include MonitorMixin
17
-
18
- def initialize
19
- super
20
- @cv = new_cond()
21
- end
22
-
23
- # Add, restore an object to the pool.
24
-
25
- def push(obj)
26
- synchronize do
27
- super
28
- @cv.signal()
29
- end
30
- end
31
-
32
- # Obtain an object from the pool.
33
-
34
- def pop
35
- synchronize do
36
- @cv.wait_while { empty? }
37
- super
38
- end
39
- end
40
-
41
- # Obtains an object, passes it to a block for processing
42
- # and restores it to the pool.
43
-
44
- def obtain
45
- result = nil
46
-
47
- begin
48
- obj = pop()
49
-
50
- result = yield(obj)
51
- ensure
52
- push(obj)
53
- end
54
-
55
- return result
56
- end
57
-
58
- end
59
-
60
- end
@@ -1,408 +0,0 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # * Michael Neumann <mneumann@ntecs.de>
3
- # (c) 2004-2005 Navel, all rights reserved.
4
- # $Id: property.rb 266 2005-02-28 14:50:48Z gmosx $
5
-
6
- require 'glue/attribute'
7
- require 'glue/array'
8
- require 'glue/hash'
9
-
10
- module N
11
-
12
- # Ruby attributes are typeless and generally this is good.
13
- # Some times we need extra metadata though, for example in
14
- # relational mapping, or web form population.
15
- #
16
- # Only Fixnums, Strings, Floats, Times, Booleans are
17
- # converted.
18
- #
19
- # The default = methods do not force the types. A special
20
- # __force_set method should be used instead.
21
- #--
22
- # TODO:
23
- # Perhaps a sync is needed in evals (!!!!)
24
- #++
25
-
26
- class Property
27
-
28
- # If set to true, perform type checking on property set.
29
- # Useful when debugging.
30
-
31
- cattr_accessor :type_checking, false
32
-
33
- # The symbol of the property.
34
-
35
- attr_accessor :symbol
36
-
37
- # The string representation of the symbol.
38
-
39
- attr_accessor :name
40
-
41
- # The class of the property.
42
-
43
- attr_accessor :klass
44
-
45
- # Additional metadata (like sql declaration, sql index, etc)
46
- # Here is a list of predefined metadata:
47
- #
48
- # [+:reader+]
49
- # create reader?
50
- #
51
- # [+:writer+]
52
- # create writer?
53
- #
54
- # [+:sql_index+]
55
- # create an sql index for the column this poperty maps to?
56
- #
57
- # You can use this mechanism to add your own, custom,
58
- # metadata.
59
-
60
- attr_accessor :meta
61
-
62
- def initialize(symbol, klass, meta = {})
63
- @symbol, @klass = symbol, klass
64
- @meta = meta
65
- @name = @symbol.to_s()
66
- end
67
-
68
- def ==(other)
69
- return @symbol == other.symbol
70
- end
71
-
72
- def to_s
73
- return name
74
- end
75
-
76
- end
77
-
78
- # A collection of Property related utility methods.
79
-
80
- module PropertyUtils
81
-
82
- # Add accessors to the properties to the given target
83
- # (Module or Class). For simplicity also create the
84
- # meta accessors.
85
- #
86
- # [+target+]
87
- # The target class or module
88
- #--
89
- # gmosx: Perhaps we 'll optimize this in the future.
90
- #++
91
-
92
- def self.enchant(target, force = false)
93
- unless target.singleton_methods.include?('__props')
94
- target.module_eval %{
95
- @@__meta = N::SafeHash.new
96
- @@__props = N::SafeArray.new
97
-
98
- def self.__props
99
- @@__props
100
- end
101
-
102
- def self.__props=(props)
103
- @@__props = props
104
- end
105
-
106
- def self.__meta
107
- @@__meta
108
- end
109
-
110
- def self.__meta=(meta)
111
- @@__meta = meta
112
- end
113
- }
114
- end
115
- end
116
-
117
- # Copy properties from src (Module or Class) to dest.
118
-
119
- def self.copy_props(src, dest)
120
- src.__props.each do |p|
121
- add_prop(dest, p)
122
- end
123
-
124
- # copy the metadata.
125
- src.__meta.each do |k, val|
126
- dest.__meta[k] = val.dup
127
- # val.each { |v| dest.meta(k, v) } if val
128
- end
129
- end
130
-
131
- # Add the property to the target (Class or Module)
132
-
133
- def self.add_prop(target, prop)
134
- if idx = target.__props.index(prop)
135
- # override in case of duplicates. Keep the order of the props.
136
- target.__props[idx] = prop
137
- else
138
- target.__props << prop
139
- end
140
-
141
- # Store the property in the :props_and_relations
142
- # metadata array.
143
-
144
- target.meta :props_and_relations, prop
145
-
146
- # Precompile the property read/write methods
147
-
148
- s, klass = prop.symbol, prop.klass
149
-
150
- if prop.meta[:reader]
151
- target.module_eval %{
152
- def #{s}
153
- return @#{s}
154
- end
155
- }
156
- end
157
-
158
- # gmosx: __force_xxx reuses xxx= to allow for easier
159
- # overrides.
160
-
161
- if prop.meta[:writer]
162
- target.module_eval %{
163
- #{prop_setter(prop)}
164
-
165
- def __force_#{s}(val)
166
- self.#{s}=(} + case klass.name
167
- when Fixnum.name
168
- "val.to_i()"
169
- when String.name
170
- "val.to_s()"
171
- when Float.name
172
- "val.to_f()"
173
- when Time.name
174
- "Time.parse(val.to_s())"
175
- when TrueClass.name, FalseClass.name
176
- "val.to_i() > 0"
177
- else
178
- "val"
179
- end + %{)
180
- end
181
- }
182
- end
183
- end
184
-
185
- # Generates the property setter code. Can be overriden
186
- # to support extra functionality (example: markup)
187
-
188
- def self.prop_setter(prop)
189
- s = prop.symbol
190
-
191
- code = %{
192
- def #{s}=(val)
193
- }
194
-
195
- if N::Property.type_checking
196
- code << %{
197
- unless #{prop.klass} == val.class
198
- raise "Invalid type, expected '#{prop.klass}', is '\#\{val.class\}'."
199
- end
200
- }
201
- end
202
-
203
- code << %{
204
- @#{s} = val
205
- end
206
- }
207
-
208
- return code
209
- end
210
-
211
- # Get the property metadata for the given symbol.
212
-
213
- def self.get_prop(klass, sym)
214
- return klass.__props.find { |p| p.symbol == sym }
215
- end
216
-
217
- # Include meta-language mixins
218
-
219
- def self.include_meta_mixins(target)
220
- target.module_eval %{ include N::Validation } if defined?(N::Validation)
221
- # gmosx: TODO, make Og::MetaLanguage equivalent to Validation.
222
- target.module_eval %{ extend Og::MetaLanguage } if defined?(Og::MetaLanguage)
223
- end
224
-
225
- # Resolves the parameters passed to the propxxx macros
226
- # to generate the meta, klass and symbols variables. This
227
- # way the common functionality is factored out.
228
- #
229
- # [+params+]
230
- # The params to resolve.
231
- # [+one_symbol+]
232
- # If true, only resolves one symbol (used in prop).
233
-
234
- def self.resolve_prop_params(*params)
235
- meta = {}
236
- klass = Object
237
- symbols = []
238
-
239
- for param in params.flatten
240
- if param.is_a?(Class)
241
- klass = param
242
- elsif param.is_a?(Symbol)
243
- symbols << param
244
- elsif param.is_a?(TrueClass) or param.is_a?(TrueClass)
245
- writer = param
246
- elsif param.is_a?(Hash)
247
- # the meta hash.
248
- meta.update(param) { |k, a, b| [a,b].join(' ') }
249
- else
250
- raise 'Error when defining property!'
251
- end
252
- end
253
-
254
- raise 'No symbols provided!' if symbols.empty?
255
-
256
- return meta, klass, symbols
257
- end
258
-
259
- end
260
-
261
- end # module
262
-
263
- class Module
264
-
265
- # Define a property (== typed attribute)
266
- # This works like Ruby's standard attr method, ie creates
267
- # only one property.
268
- #
269
- # Use the prop_reader, prop_writer, prop_accessor methods
270
- # for multiple properties.
271
- #
272
- # Examples:
273
- # prop String, :name, :sql => "char(32), :sql_index => "name(32)"
274
- # --> creates only writer.
275
- # prop Fixnum, :oid, writer = true, :sql => "integer PRIMARY KEY"
276
- # --> creates reader and writer.
277
-
278
- def prop(*params)
279
- meta, klass, symbols = N::PropertyUtils.resolve_prop_params(params)
280
- symbol = symbols.first
281
-
282
- N::PropertyUtils.enchant(self)
283
-
284
- if self.is_a?(Class)
285
-
286
- # Add some extra code to append features to
287
- # subclasses.
288
-
289
- self.module_eval %{
290
- def self.inherited(sub)
291
- N::PropertyUtils.enchant(sub)
292
- N::PropertyUtils.copy_props(self, sub)
293
- # gmosx: We have to define @@__props first to avoid reusing
294
- # the hash from the module. super must stay at the end.
295
- super
296
- end
297
- }
298
- else
299
-
300
- # Add some extra code for modules to append
301
- # their features to classes that include it.
302
-
303
- self.module_eval %{
304
- def self.append_features(base)
305
- N::PropertyUtils.enchant(base)
306
- N::PropertyUtils.copy_props(self, base)
307
-
308
- # gmosx: We have to define @@__props first to avoid reusing
309
- # the hash from the module. super must stay at the end.
310
-
311
- N::PropertyUtils.include_meta_mixins(base)
312
-
313
- super
314
- end
315
- }
316
- end
317
-
318
- property = N::Property.new(symbol, klass, meta)
319
-
320
- reader = meta[:reader] || true
321
- writer = writer || meta[:writer] || false
322
-
323
- meta[:reader] = true if meta[:reader].nil?
324
- if defined?(writer)
325
- meta[:writer] = writer
326
- else
327
- meta[:writer] = true if meta[:writer].nil?
328
- end
329
-
330
- N::PropertyUtils.add_prop(self, property)
331
-
332
- # gmosx: should be placed AFTER enchant!
333
-
334
- N::PropertyUtils.include_meta_mixins(self)
335
- end
336
-
337
- # Helper method. Accepts a collection of symbols and generates
338
- # properties. Only generates reader.
339
- #
340
- # Example:
341
- # prop_reader String, :name, :title, :body, :sql => "char(32)"
342
-
343
- def prop_reader(*params)
344
- meta, klass, symbols = N::PropertyUtils.resolve_prop_params(params)
345
-
346
- meta[:reader] = true
347
- meta[:writer] = false
348
-
349
- for symbol in symbols
350
- prop(klass, symbol, meta)
351
- end
352
- end
353
-
354
- # Helper method. Accepts a collection of symbols and generates
355
- # properties. Only generates writer.
356
- #
357
- # Example:
358
- # prop_writer String, :name, :title, :body, :sql => "char(32)"
359
-
360
- def prop_writer(*params)
361
- meta, klass, symbols = N::PropertyUtils.resolve_prop_params(params)
362
-
363
- meta[:reader] = false
364
- meta[:writer] = true
365
-
366
- for symbol in symbols
367
- prop(klass, symbol, meta)
368
- end
369
- end
370
-
371
- # Helper method. Accepts a collection of symbols and generates
372
- # properties. Generates reader and writer.
373
- #
374
- # Example:
375
- # prop_accessor String, :name, :title, :body, :sql => "char(32)"
376
-
377
- def prop_accessor(*params)
378
- meta, klass, symbols = N::PropertyUtils.resolve_prop_params(params)
379
-
380
- meta[:reader] = true
381
- meta[:writer] = true
382
-
383
- for symbol in symbols
384
- prop(klass, symbol, meta)
385
- end
386
- end
387
- alias_method :property, :prop_accessor
388
-
389
- # Attach metadata.
390
- # Guard against duplicates, no need to keep order.
391
- # This method uses closures :)
392
- #--
393
- # gmosx: crappy implementation, recode.
394
- #++
395
-
396
- def meta(key, *val)
397
- val = val.first if val.size == 1
398
-
399
- N::PropertyUtils.enchant(self)
400
-
401
- self.module_eval %{
402
- @@__meta[key] ||= []
403
- @@__meta[key].delete_if { |v| val == v }
404
- @@__meta[key] << val
405
- }
406
- end
407
-
408
- end