sencha-model 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +6 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +35 -0
- data/LICENSE +20 -0
- data/README.rdoc +113 -0
- data/Rakefile +26 -0
- data/VERSION +1 -0
- data/lib/sencha-model.rb +17 -0
- data/lib/sencha-model/adapters/active_record.rb +88 -0
- data/lib/sencha-model/adapters/data_mapper.rb +66 -0
- data/lib/sencha-model/adapters/mongo_mapper.rb +64 -0
- data/lib/sencha-model/model.rb +373 -0
- data/lib/sencha-model/version.rb +5 -0
- data/rails/init.rb +1 -0
- data/sencha-model.gemspec +99 -0
- data/shoulda_macros/macros.rb +20 -0
- data/test/active_record_test.rb +0 -0
- data/test/app/config/application.rb +70 -0
- data/test/app/config/database.yml +3 -0
- data/test/app/db/schema.rb +75 -0
- data/test/app/models/active_record/address.rb +4 -0
- data/test/app/models/active_record/data_type.rb +3 -0
- data/test/app/models/active_record/group.rb +4 -0
- data/test/app/models/active_record/house.rb +4 -0
- data/test/app/models/active_record/location.rb +5 -0
- data/test/app/models/active_record/person.rb +4 -0
- data/test/app/models/active_record/user.rb +6 -0
- data/test/app/models/active_record/user_group.rb +4 -0
- data/test/data_mapper_test.rb +0 -0
- data/test/model_test.rb +526 -0
- data/test/mongo_mapper_test.rb +0 -0
- data/test/test_helper.rb +32 -0
- metadata +147 -0
@@ -0,0 +1,373 @@
|
|
1
|
+
module Sencha
|
2
|
+
module Model
|
3
|
+
|
4
|
+
def self.included(model)
|
5
|
+
model.send(:extend, ClassMethods)
|
6
|
+
model.send(:include, InstanceMethods)
|
7
|
+
##
|
8
|
+
# @config {String} sencha_parent_trail_template This a template used to render mapped field-names.
|
9
|
+
# Default is Proc.new{ |field_name| "_#{field_name}" }
|
10
|
+
# You could also use the Rails standard
|
11
|
+
# Proc.new{ |field_name| "[#{field_name}]" }
|
12
|
+
#
|
13
|
+
model.cattr_accessor :sencha_parent_trail_template
|
14
|
+
model.sencha_parent_trail_template = Proc.new{ |field_name| "_#{field_name}" } if model.sencha_parent_trail_template.nil?
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# InstanceMethods
|
19
|
+
#
|
20
|
+
module InstanceMethods
|
21
|
+
|
22
|
+
##
|
23
|
+
# Converts a model instance to a record compatible with javascript applications
|
24
|
+
#
|
25
|
+
# The first parameter should be the fieldset for which the record will be returned.
|
26
|
+
# If no parameter is provided, then the default fieldset will be choosen
|
27
|
+
# Alternativly the first parameter can be a Hash with a :fields member to directly specify
|
28
|
+
# the fields to use for the record.
|
29
|
+
#
|
30
|
+
# All these are valid calls:
|
31
|
+
#
|
32
|
+
# user.to_record # returns record for :default fieldset
|
33
|
+
# # (fieldset is autmatically defined, if not set)
|
34
|
+
#
|
35
|
+
# user.to_record :fieldset # returns record for :fieldset fieldset
|
36
|
+
# # (fieldset is autmatically defined, if not set)
|
37
|
+
#
|
38
|
+
# user.to_record :fields => [:id, :password]
|
39
|
+
# # returns record for the fields 'id' and 'password'
|
40
|
+
#
|
41
|
+
# For even more valid options for this method (which all should not be neccessary to use)
|
42
|
+
# have a look at Whorm::Model::Util.extract_fieldset_and_options
|
43
|
+
def to_record(*params)
|
44
|
+
fieldset, options = Util.extract_fieldset_and_options params
|
45
|
+
|
46
|
+
fields = []
|
47
|
+
if options[:fields].empty?
|
48
|
+
fields = self.class.sencha_get_fields_for_fieldset(fieldset)
|
49
|
+
else
|
50
|
+
fields = self.class.process_fields(*options[:fields])
|
51
|
+
end
|
52
|
+
|
53
|
+
assns = self.class.sencha_associations
|
54
|
+
pk = self.class.sencha_primary_key
|
55
|
+
|
56
|
+
# build the initial field data-hash
|
57
|
+
data = {pk => self.send(pk)}
|
58
|
+
|
59
|
+
fields.each do |field|
|
60
|
+
next if data.has_key? field[:name] # already processed (e.g. explicit mentioning of :id)
|
61
|
+
|
62
|
+
value = nil
|
63
|
+
if association_reflection = assns[field[:name]] # if field is an association
|
64
|
+
association = self.send(field[:name])
|
65
|
+
|
66
|
+
# skip this association if we already visited it
|
67
|
+
# otherwise we could end up in a cyclic reference
|
68
|
+
next if options[:visited_classes].include? association.class
|
69
|
+
|
70
|
+
case association_reflection[:type]
|
71
|
+
when :belongs_to, :has_one
|
72
|
+
if association.respond_to? :to_record
|
73
|
+
assn_fields = field[:fields]
|
74
|
+
if assn_fields.nil?
|
75
|
+
assn_fields = association.class.sencha_get_fields_for_fieldset(field.fetch(:fieldset, fieldset))
|
76
|
+
end
|
77
|
+
|
78
|
+
value = association.to_record :fields => assn_fields,
|
79
|
+
:visited_classes => options[:visited_classes] + [self.class]
|
80
|
+
else
|
81
|
+
value = {}
|
82
|
+
(field[:fields]||[]).each do |sub_field|
|
83
|
+
value[sub_field[:name]] = association.send(sub_field[:name]) if association.respond_to? sub_field[:name]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
if association_reflection[:type] == :belongs_to
|
87
|
+
# Append associations foreign_key to data
|
88
|
+
data[association_reflection[:foreign_key]] = self.send(association_reflection[:foreign_key])
|
89
|
+
if association_reflection[:is_polymorphic]
|
90
|
+
foreign_type = self.class.sencha_polymorphic_type(association_reflection[:foreign_key])
|
91
|
+
data[foreign_type] = self.send(foreign_type)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
when :many
|
95
|
+
value = association.collect { |r| r.to_record } # use carefully, can get HUGE
|
96
|
+
end
|
97
|
+
else # not an association -> get the method's value
|
98
|
+
value = self.send(field[:name])
|
99
|
+
value = value.to_record if value.respond_to? :to_record
|
100
|
+
end
|
101
|
+
data[field[:name]] = value
|
102
|
+
end
|
103
|
+
data
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
##
|
108
|
+
# ClassMethods
|
109
|
+
#
|
110
|
+
module ClassMethods
|
111
|
+
##
|
112
|
+
# render AR columns to Ext.data.Record.create format
|
113
|
+
# eg: {name:'foo', type: 'string'}
|
114
|
+
#
|
115
|
+
# The first parameter should be the fieldset for which the record definition will be returned.
|
116
|
+
# If no parameter is provided, then the default fieldset will be choosen
|
117
|
+
# Alternativly the first parameter can be a Hash with a :fields member to directly specify
|
118
|
+
# the fields to use for the record config.
|
119
|
+
#
|
120
|
+
# All these are valid calls:
|
121
|
+
#
|
122
|
+
# User.sencha_schema # returns record config for :default fieldset
|
123
|
+
# # (fieldset is autmatically defined, if not set)
|
124
|
+
#
|
125
|
+
# User.sencha_schema :fieldset # returns record config for :fieldset fieldset
|
126
|
+
# # (fieldset is autmatically defined, if not set)
|
127
|
+
#
|
128
|
+
# User.sencha_schema :fields => [:id, :password]
|
129
|
+
# # returns record config for the fields 'id' and 'password'
|
130
|
+
#
|
131
|
+
# For even more valid options for this method (which all should not be neccessary to use)
|
132
|
+
# have a look at Whorm::Model::Util.extract_fieldset_and_options
|
133
|
+
def sencha_schema(*params)
|
134
|
+
fieldset, options = Util.extract_fieldset_and_options params
|
135
|
+
|
136
|
+
if options[:fields].empty?
|
137
|
+
fields = self.sencha_get_fields_for_fieldset(fieldset)
|
138
|
+
else
|
139
|
+
fields = self.process_fields(*options[:fields])
|
140
|
+
end
|
141
|
+
|
142
|
+
associations = self.sencha_associations
|
143
|
+
columns = self.sencha_columns_hash
|
144
|
+
pk = self.sencha_primary_key
|
145
|
+
rs = []
|
146
|
+
|
147
|
+
fields.each do |field|
|
148
|
+
|
149
|
+
field = Marshal.load(Marshal.dump(field)) # making a deep copy
|
150
|
+
|
151
|
+
if col = columns[field[:name]] # <-- column on this model
|
152
|
+
rs << self.sencha_field(field, col)
|
153
|
+
elsif assn = associations[field[:name]]
|
154
|
+
# skip this association if we already visited it
|
155
|
+
# otherwise we could end up in a cyclic reference
|
156
|
+
next if options[:visited_classes].include? assn[:class]
|
157
|
+
|
158
|
+
assn_fields = field[:fields]
|
159
|
+
if assn[:class].respond_to?(:sencha_schema) # <-- exec sencha_schema on assn Model.
|
160
|
+
if assn_fields.nil?
|
161
|
+
assn_fields = assn[:class].sencha_get_fields_for_fieldset(field.fetch(:fieldset, fieldset))
|
162
|
+
end
|
163
|
+
|
164
|
+
record = assn[:class].sencha_schema(field.fetch(:fieldset, fieldset), { :visited_classes => options[:visited_classes] + [self], :fields => assn_fields})
|
165
|
+
rs.concat(record[:fields].collect { |assn_field|
|
166
|
+
self.sencha_field(assn_field, :parent_trail => field[:name], :mapping => field[:name], :allowBlank => true) # <-- allowBlank on associated data?
|
167
|
+
})
|
168
|
+
elsif assn_fields # <-- :parent => [:id, :name, :sub => [:id, :name]]
|
169
|
+
field_collector = Proc.new do |parent_trail, mapping, assn_field|
|
170
|
+
if assn_field.is_a?(Hash) && assn_field.keys.size == 1 && assn_field.keys[0].is_a?(Symbol) && assn_field.values[0].is_a?(Array)
|
171
|
+
field_collector.call(parent_trail.to_s + self.sencha_parent_trail_template.call(assn_field.keys.first), "#{mapping}.#{assn_field.keys.first}", assn_field.values.first)
|
172
|
+
else
|
173
|
+
self.sencha_field(assn_field, :parent_trail => parent_trail, :mapping => mapping, :allowBlank => true)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
rs.concat(assn_fields.collect { |assn_field| field_collector.call(field[:name], field[:name], assn_field) })
|
177
|
+
else
|
178
|
+
rs << sencha_field(field)
|
179
|
+
end
|
180
|
+
|
181
|
+
# attach association's foreign_key if not already included.
|
182
|
+
if columns.has_key?(assn[:foreign_key]) && !rs.any? { |r| r[:name] == assn[:foreign_key] }
|
183
|
+
rs << sencha_field({:name => assn[:foreign_key]}, columns[assn[:foreign_key]])
|
184
|
+
end
|
185
|
+
# attach association's type if polymorphic association and not alredy included
|
186
|
+
if assn[:is_polymorphic]
|
187
|
+
foreign_type = self.sencha_polymorphic_type(assn[:foreign_key])
|
188
|
+
if columns.has_key?(foreign_type) && !rs.any? { |r| r[:name] == foreign_type }
|
189
|
+
rs << sencha_field({:name => foreign_type}, columns[foreign_type])
|
190
|
+
end
|
191
|
+
end
|
192
|
+
else # property is a method?
|
193
|
+
rs << sencha_field(field)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
return {
|
198
|
+
:fields => rs,
|
199
|
+
:idProperty => pk,
|
200
|
+
:associations => associations.keys.map {|a| { # <-- New, experimental for ExtJS-4.0
|
201
|
+
:type => associations[a][:type],
|
202
|
+
:model => associations[a][:class].to_s,
|
203
|
+
:name => associations[a][:class].to_s.downcase.pluralize
|
204
|
+
}}
|
205
|
+
}
|
206
|
+
end
|
207
|
+
|
208
|
+
##
|
209
|
+
# meant to be used within a Model to define the sencha record fields.
|
210
|
+
# eg:
|
211
|
+
# class User
|
212
|
+
# sencha_fieldset :grid, [:first, :last, :email => {"sortDir" => "ASC"}, :company => [:id, :name]]
|
213
|
+
# end
|
214
|
+
# or
|
215
|
+
# class User
|
216
|
+
# sencha_fieldset :last, :email => {"sortDir" => "ASC"}, :company => [:id, :name] # => implies fieldset name :default
|
217
|
+
# end
|
218
|
+
#
|
219
|
+
def sencha_fieldset(*params)
|
220
|
+
fieldset, options = Util.extract_fieldset_and_options params
|
221
|
+
var_name = :"@sencha_fieldsets__#{fieldset}"
|
222
|
+
self.instance_variable_set( var_name, self.process_fields(*options[:fields]) )
|
223
|
+
end
|
224
|
+
|
225
|
+
def sencha_get_fields_for_fieldset(fieldset)
|
226
|
+
var_name = :"@sencha_fieldsets__#{fieldset}"
|
227
|
+
super_value = nil
|
228
|
+
unless self.instance_variable_get( var_name )
|
229
|
+
if self.superclass.respond_to? :sencha_get_fields_for_fieldset
|
230
|
+
super_value = self.superclass.sencha_get_fields_for_fieldset(fieldset)
|
231
|
+
end
|
232
|
+
self.sencha_fieldset(fieldset, self.sencha_column_names) unless super_value
|
233
|
+
end
|
234
|
+
super_value || self.instance_variable_get( var_name )
|
235
|
+
end
|
236
|
+
|
237
|
+
##
|
238
|
+
# shortcut to define the default fieldset. For backwards-compatibility.
|
239
|
+
#
|
240
|
+
def sencha_fields(*params)
|
241
|
+
self.sencha_fieldset(:default, {
|
242
|
+
:fields => params
|
243
|
+
})
|
244
|
+
end
|
245
|
+
|
246
|
+
##
|
247
|
+
# Prepare a field configuration list into a normalized array of Hashes, {:name => "field_name"}
|
248
|
+
# @param {Mixed} params
|
249
|
+
# @return {Array} of Hashes
|
250
|
+
#
|
251
|
+
def process_fields(*params)
|
252
|
+
fields = []
|
253
|
+
if params.size == 1 && params.last.is_a?(Hash) # peek into argument to see if its an option hash
|
254
|
+
options = params.last
|
255
|
+
if options.has_key?(:additional) && options[:additional].is_a?(Array)
|
256
|
+
return self.process_fields(*(self.sencha_column_names + options[:additional].map(&:to_sym)))
|
257
|
+
elsif options.has_key?(:exclude) && options[:exclude].is_a?(Array)
|
258
|
+
return self.process_fields(*(self.sencha_column_names - options[:exclude].map(&:to_sym)))
|
259
|
+
elsif options.has_key?(:only) && options[:only].is_a?(Array)
|
260
|
+
return self.process_fields(*options[:only])
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
params = self.sencha_column_names if params.empty?
|
265
|
+
|
266
|
+
params.each do |f|
|
267
|
+
if f.kind_of?(Hash)
|
268
|
+
if f.keys.size == 1 && f.keys[0].is_a?(Symbol) && f.values[0].is_a?(Array) # {:association => [:field1, :field2]}
|
269
|
+
fields << {
|
270
|
+
:name => f.keys[0],
|
271
|
+
:fields => process_fields(*f.values[0])
|
272
|
+
}
|
273
|
+
elsif f.keys.size == 1 && f.keys[0].is_a?(Symbol) && f.values[0].is_a?(Hash) # {:field => {:sortDir => 'ASC'}}
|
274
|
+
fields << f.values[0].update(:name => f.keys[0])
|
275
|
+
elsif f.has_key?(:name) # already a valid Hash, just copy it over
|
276
|
+
fields << f
|
277
|
+
else
|
278
|
+
raise ArgumentError, "encountered a Hash that I don't know anything to do with `#{f.inspect}:#{f.class}`"
|
279
|
+
end
|
280
|
+
else # should be a String or Symbol
|
281
|
+
raise ArgumentError, "encountered a fields Array that I don't understand: #{params.inspect} -- `#{f.inspect}:#{f.class}` is not a Symbol or String" unless f.is_a?(Symbol) || f.is_a?(String)
|
282
|
+
fields << {:name => f.to_sym}
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
fields
|
287
|
+
end
|
288
|
+
|
289
|
+
##
|
290
|
+
# Render a column-config object
|
291
|
+
# @param {Hash/Column} field Field-configuration Hash, probably has :name already set and possibly Ext.data.Field options.
|
292
|
+
# @param {ORM Column Object from AR, DM or MM}
|
293
|
+
#
|
294
|
+
def sencha_field(field, config=nil)
|
295
|
+
if config.kind_of? Hash
|
296
|
+
if config.has_key?(:mapping) && config.has_key?(:parent_trail)
|
297
|
+
field.update( # <-- We use a template for rendering mapped field-names.
|
298
|
+
:name => config[:parent_trail].to_s + self.sencha_parent_trail_template.call(field[:name]),
|
299
|
+
:mapping => "#{config[:mapping]}.#{field[:name]}"
|
300
|
+
)
|
301
|
+
end
|
302
|
+
field.update(config.except(:mapping, :parent_trail))
|
303
|
+
elsif !config.nil? # <-- Hopfully an ORM Column object.
|
304
|
+
field.update(
|
305
|
+
:allowBlank => self.sencha_allow_blank(config),
|
306
|
+
:type => self.sencha_type(config),
|
307
|
+
:defaultValue => self.sencha_default(config)
|
308
|
+
)
|
309
|
+
field[:dateFormat] = "c" if field[:type] === "date" && field[:dateFormat].nil? # <-- ugly hack for date
|
310
|
+
end
|
311
|
+
field.update(:type => "auto") if field[:type].nil?
|
312
|
+
# convert Symbol values to String values
|
313
|
+
field.keys.each do |k|
|
314
|
+
raise ArgumentError, "sencha_field expects a Hash as first parameter with all it's keys Symbols. Found key #{k.inspect}:#{k.class.to_s}" unless k.is_a?(Symbol)
|
315
|
+
field[k] = field[k].to_s if field[k].is_a?(Symbol)
|
316
|
+
end
|
317
|
+
field
|
318
|
+
end
|
319
|
+
|
320
|
+
# ##
|
321
|
+
# # Returns an array of symbolized association names that will be referenced by a call to to_record
|
322
|
+
# # i.e. [:parent1, :parent2]
|
323
|
+
# #
|
324
|
+
# def sencha_used_associations
|
325
|
+
# if @sencha_used_associations.nil?
|
326
|
+
# assoc = []
|
327
|
+
# self.sencha_record_fields.each do |f|
|
328
|
+
# #This needs to be the first condition because the others will break if f is an Array
|
329
|
+
# if sencha_associations[f[:name]]
|
330
|
+
# assoc << f[:name]
|
331
|
+
# end
|
332
|
+
# end
|
333
|
+
# @sencha_used_associations = assoc.uniq
|
334
|
+
# end
|
335
|
+
# @sencha_used_associations
|
336
|
+
# end
|
337
|
+
end
|
338
|
+
|
339
|
+
module Util
|
340
|
+
|
341
|
+
##
|
342
|
+
# returns the fieldset from the arguments and normalizes the options.
|
343
|
+
# @return [{Symbol}, {Hash}]
|
344
|
+
def self.extract_fieldset_and_options arguments
|
345
|
+
orig_args = arguments
|
346
|
+
fieldset = :default
|
347
|
+
options = { # default options
|
348
|
+
:visited_classes => [],
|
349
|
+
:fields => []
|
350
|
+
}
|
351
|
+
if arguments.size > 2 || (arguments.size == 2 && !arguments[0].is_a?(Symbol))
|
352
|
+
raise ArgumentError, "Don't know how to handle #{arguments.inspect}"
|
353
|
+
elsif arguments.size == 2 && arguments[0].is_a?(Symbol)
|
354
|
+
fieldset = arguments.shift
|
355
|
+
if arguments[0].is_a?(Array)
|
356
|
+
options.update({
|
357
|
+
:fields => arguments[0]
|
358
|
+
})
|
359
|
+
elsif arguments[0].is_a?(Hash)
|
360
|
+
options.update(arguments[0])
|
361
|
+
end
|
362
|
+
elsif arguments.size == 1 && (arguments[0].is_a?(Symbol) || arguments[0].is_a?(String))
|
363
|
+
fieldset = arguments.shift.to_sym
|
364
|
+
elsif arguments.size == 1 && arguments[0].is_a?(Hash)
|
365
|
+
fieldset = arguments[0].delete(:fieldset) || :default
|
366
|
+
options.update(arguments[0])
|
367
|
+
end
|
368
|
+
[fieldset, options]
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
data/rails/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'sencha-model'
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "sencha-model/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "sencha-model"
|
7
|
+
s.version = Sencha::Model::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Chris Scott"]
|
10
|
+
s.email = ["christocracy@gmail.com"]
|
11
|
+
s.homepage = "http://www.440solutions.com"
|
12
|
+
s.summary = %q{This gem auto-generates ExtJS compatible model specifications from your ORM (eg: ActiveRecord, DataMapper, MongoMapper)}
|
13
|
+
s.description = %q{This gem auto-generates ExtJS compatible model specifications from your ORM (eg: ActiveRecord, DataMapper, MongoMapper)}
|
14
|
+
|
15
|
+
s.add_development_dependency "shoulda"
|
16
|
+
s.add_development_dependency "mocha"
|
17
|
+
s.add_development_dependency "extlib"
|
18
|
+
s.add_development_dependency "activerecord", ">= 3.0.0"
|
19
|
+
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
23
|
+
s.require_paths = ["lib"]
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
# Generated by jeweler
|
29
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
30
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
31
|
+
# -*- encoding: utf-8 -*-
|
32
|
+
|
33
|
+
#Gem::Specification.new do |s|
|
34
|
+
# s.name = %q{whorm}
|
35
|
+
# s.version = "0.4.0"
|
36
|
+
|
37
|
+
# s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
38
|
+
# s.authors = ["Chris Scott"]
|
39
|
+
# s.date = %q{2010-03-09}
|
40
|
+
# s.description = %q{Whorm contains a Model-mixin named Whorm::Model. Once included, your Model now exposes a class-method named #whorm_schema which will return Hash representation of the Model-schema.}
|
41
|
+
# s.email = %q{christocracy@gmail.com}
|
42
|
+
# s.extra_rdoc_files = [
|
43
|
+
## "LICENSE",
|
44
|
+
# "README.rdoc"
|
45
|
+
# ]
|
46
|
+
# s.files = [
|
47
|
+
# "LICENSE",
|
48
|
+
# "README.rdoc",
|
49
|
+
# "Rakefile",
|
50
|
+
# "VERSION",
|
51
|
+
# "lib/test/macros.rb",
|
52
|
+
# "lib/whorm.rb",
|
53
|
+
# "lib/whorm/adapters/active_record.rb",
|
54
|
+
# "lib/whorm/adapters/data_mapper.rb",
|
55
|
+
# "lib/whorm/adapters/mongo_mapper.rb",
|
56
|
+
# "lib/whorm/model.rb",
|
57
|
+
# "test/active_record_test.rb",
|
58
|
+
# "test/app/config/application.rb",
|
59
|
+
# "test/app/config/database.yml",
|
60
|
+
# "test/app/db/schema.rb",
|
61
|
+
# "test/app/models/active_record/address.rb",
|
62
|
+
# "test/app/models/active_record/data_type.rb",
|
63
|
+
# "test/app/models/active_record/group.rb",
|
64
|
+
# "test/app/models/active_record/house.rb",
|
65
|
+
# "test/app/models/active_record/location.rb",
|
66
|
+
# "test/app/models/active_record/person.rb",
|
67
|
+
# "test/app/models/active_record/user.rb",
|
68
|
+
# "test/app/models/active_record/user_group.rb",
|
69
|
+
# "test/data_mapper_test.rb",
|
70
|
+
# "test/model_test.rb",
|
71
|
+
# "test/mongo_mapper_test.rb",
|
72
|
+
# "test/test_helper.rb"
|
73
|
+
# ]
|
74
|
+
# s.homepage = %q{http://github.com/christocracy/whorm}
|
75
|
+
# s.rdoc_options = ["--charset=UTF-8"]
|
76
|
+
# s.require_paths = ["lib"]
|
77
|
+
# s.rubygems_version = %q{1.3.6}
|
78
|
+
# s.summary = %q{Ruby ORM-inspecting tools to assist with generating JSON representations of database schemas and recordsets.}
|
79
|
+
|
80
|
+
# if s.respond_to? :specification_version then
|
81
|
+
# current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
82
|
+
# s.specification_version = 3
|
83
|
+
|
84
|
+
# if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
85
|
+
# s.add_development_dependency(%q<shoulda>, [">= 0"])
|
86
|
+
# s.add_development_dependency(%q<mocha>, [">= 0"])
|
87
|
+
# s.add_development_dependency(%q<extlib>, [">= 0"])
|
88
|
+
# else
|
89
|
+
# s.add_dependency(%q<shoulda>, [">= 0"])
|
90
|
+
## s.add_dependency(%q<mocha>, [">= 0"])
|
91
|
+
# s.add_dependency(%q<extlib>, [">= 0"])
|
92
|
+
# end
|
93
|
+
# else
|
94
|
+
# s.add_dependency(%q<shoulda>, [">= 0"])
|
95
|
+
# s.add_dependency(%q<mocha>, [">= 0"])
|
96
|
+
# s.add_dependency(%q<extlib>, [">= 0"])
|
97
|
+
# end
|
98
|
+
#end
|
99
|
+
|