resource_model 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e75b1686bd2c25fbe1ed8b41081a3653e7d7f4ec
4
+ data.tar.gz: 6e43b8d87d5057e7b5365b35f1c24470ed7517f9
5
+ SHA512:
6
+ metadata.gz: b843e35b9a1430728e86ae09f221450b797b924cf2f9260675404494e1b46ca6e36167210a28a47e5e57109ac3c86c6c57de35b8d67c41ae8eee41b2adcb3598
7
+ data.tar.gz: 1b65fba097a4bf5b3919fed6127b9250b2e1a54b879d9b66734b246998d3ae6657ed6aef9f86a69b7d4454a04e578b54c38cea71d1ab88808f00561c72f1b464
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in resource_model.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 James Coleman
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # ResourceModel
2
+
3
+ This code was extracted from a real-world project. While you may browse and use the code contained here, there isn't currently good documentation, example code, or any tests. All of these should follow at some point.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'resource_model'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install resource_model
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://github.com/[my-github-username]/resource_model/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,7 @@
1
+ require "resource_model/version"
2
+
3
+ module ResourceModel
4
+ # Your code goes here...
5
+ end
6
+
7
+ require "resource_model/base"
@@ -0,0 +1,550 @@
1
+ class ResourceModel::Base
2
+
3
+ extend ActiveModel::Callbacks
4
+ extend ActiveModel::Naming
5
+ include ActiveModel::Validations
6
+ include ActiveModel::Validations::Callbacks
7
+ include ActiveModel::Conversion
8
+
9
+ def self.model_name
10
+ ActiveModel::Name.new(self, nil, self.name)
11
+ end
12
+
13
+ def self.view_template
14
+ raise NotImplementedError
15
+ end
16
+
17
+ def persisted?
18
+ self.respond_to?(:id) && self.id.present?
19
+ end
20
+
21
+ @associated_resource_model_attributes = []
22
+ class << self; attr_reader :associated_resource_model_attributes; end
23
+
24
+ def self.has_associated_resource_model(attribute_name, options={})
25
+ raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol)
26
+ if self.associated_resource_model_attributes.include?(attribute_name)
27
+ raise ArgumentError, "Already contains associated resource model named `#{attribute_name}`"
28
+ else
29
+ @associated_resource_model_attributes << attribute_name
30
+ class_name = options[:class_name] || "::#{attribute_name.to_s.camelcase}"
31
+ self.class_eval <<-eos
32
+ attr_reader :#{attribute_name}
33
+ def #{attribute_name}=(model)
34
+ raise ArgumentError, 'Expected instance of `#{class_name}`' unless model.nil? || model.is_a?(#{class_name})
35
+ @#{attribute_name}_attributes = nil
36
+ @#{attribute_name} = model
37
+ end
38
+
39
+ def #{attribute_name}_attributes=(attributes)
40
+ if attributes
41
+ model = #{class_name}.new(attributes)
42
+ self.#{attribute_name} = model
43
+ else
44
+ self.#{attribute_name} = nil
45
+ end
46
+ @#{attribute_name}_attributes = attributes
47
+ end
48
+
49
+ validate do
50
+ if self.#{attribute_name} && !self.#{attribute_name}.valid?
51
+ self.errors.add(:#{attribute_name}, :invalid)
52
+ end
53
+ end
54
+ eos
55
+ end
56
+ end
57
+
58
+ @associated_resource_model_collection_attributes = []
59
+ class << self; attr_reader :associated_resource_model_collection_attributes; end
60
+
61
+ def self.has_associated_resource_model_collection(attribute_name, options={})
62
+ raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol)
63
+ if self.associated_resource_model_collection_attributes.include?(attribute_name)
64
+ raise ArgumentError, "Already contains associated resource model collection named `#{attribute_name}`"
65
+ else
66
+ @associated_resource_model_collection_attributes << attribute_name
67
+ class_name = options[:class_name] || "::#{attribute_name.to_s.singularize.camelcase}"
68
+ self.class_eval <<-eos
69
+ attr_reader :#{attribute_name}
70
+ def #{attribute_name}=(models)
71
+ case models
72
+ when nil
73
+ @#{attribute_name} = []
74
+ when Array
75
+ models.each do |model|
76
+ unless model.is_a?(#{class_name})
77
+ raise ArgumentError, "Assignment of collection to #{attribute_name} contained invalid type \#{model.class.name}; expected only instances of #{class_name}"
78
+ end
79
+ end
80
+ @#{attribute_name} = models
81
+ else
82
+ if models.respond_to?(:to_a)
83
+ self.#{attribute_name} = models.to_a
84
+ else
85
+ raise ArgumentError, 'Expected instance of array'
86
+ end
87
+ end
88
+ end
89
+
90
+ def #{attribute_name}_attributes=(attributes={})
91
+ if attributes
92
+ self.#{attribute_name} = attributes.collect do |(k, model_attributes)|
93
+ #{class_name}.new(model_attributes)
94
+ end
95
+ else
96
+ self.#{attribute_name} = []
97
+ end
98
+ end
99
+
100
+ validate do
101
+ if !self.#{attribute_name}.inject(true) { |valid, model| model.valid? && valid }
102
+ self.errors.add(:#{attribute_name}, :invalid)
103
+ end
104
+ end
105
+ eos
106
+ end
107
+ end
108
+
109
+ @associated_model_attributes = []
110
+ class << self; attr_reader :associated_model_attributes; end
111
+
112
+ def self.has_associated_model(attribute_name, options={}) # accepts_nested_attributes: nil
113
+ raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol)
114
+ if self.associated_model_attributes.include?(attribute_name)
115
+ raise ArgumentError, "Already contains associated model named `#{attribute_name}`"
116
+ else
117
+ @associated_model_attributes << attribute_name
118
+ class_name = options[:class_name] || "::#{attribute_name.to_s.camelcase}"
119
+ self.class_eval <<-eos
120
+ attr_reader :#{attribute_name}, :#{attribute_name}_id
121
+ def #{attribute_name}=(model)
122
+ raise ArgumentError, 'Expected instance of `#{class_name}`' unless model.nil? || model.is_a?(#{class_name})
123
+ @#{attribute_name}_id = model.present? ? model.id : nil
124
+ @#{attribute_name} = model
125
+ end
126
+
127
+ def #{attribute_name}_id=(id)
128
+ if id.present?
129
+ scope = #{class_name}.where(id: id)
130
+ eager_loads = #{options[:eager_load].inspect}
131
+ if eager_loads
132
+ scope = scope.eager_load(eager_loads)
133
+ end
134
+ self.#{attribute_name} = scope.first!
135
+ else
136
+ self.#{attribute_name} = nil
137
+ end
138
+ end
139
+ eos
140
+ end
141
+ end
142
+
143
+ @associated_model_collection_attributes = []
144
+ class << self; attr_reader :associated_model_collection_attributes; end
145
+
146
+ def self.has_associated_model_collection(attribute_name, class_name: nil, unique: true)
147
+ raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol)
148
+ if self.associated_model_collection_attributes.include?(attribute_name)
149
+ raise ArgumentError, "Already contains associated model collection named `#{attribute_name}`"
150
+ else
151
+ @associated_model_collection_attributes << attribute_name
152
+ class_name ||= "::#{attribute_name.to_s.singularize.camelcase}"
153
+ self.class_eval <<-eos
154
+ attr_reader :#{attribute_name}
155
+ def #{attribute_name}_ids
156
+ self.#{attribute_name}.collect { |model| model.id }
157
+ end
158
+
159
+ def #{attribute_name}=(models)
160
+ case models
161
+ when nil
162
+ @#{attribute_name} = []
163
+ when Array
164
+ models.each do |model|
165
+ unless model.is_a?(#{class_name})
166
+ raise ArgumentError, "Assignment of collection to #{attribute_name} contained invalid type \#{model.class.name}; expected only instances of #{class_name}"
167
+ end
168
+ end
169
+ @#{attribute_name} = models
170
+ else
171
+ if models.respond_to?(:to_a)
172
+ self.#{attribute_name} = models.to_a
173
+ else
174
+ raise ArgumentError, 'Expected instance of array'
175
+ end
176
+ end
177
+ end
178
+
179
+ def #{attribute_name}_ids=(ids)
180
+ if ids.present?
181
+ ids = ids.collect do |i|
182
+ unless i.is_a?(Integer) || (i.is_a?(String) && i =~ /\\A\\s*\\d+\\s*\\Z/)
183
+ raise ArgumentError, "Assignment of collection to #{attribute_name}_ids contained value (\#{i}) not an integer or stringified integer"
184
+ end
185
+ i.to_i
186
+ end#{unique ? '.uniq' : ''}
187
+ self.#{attribute_name} = #{class_name}.where(id: ids).to_a
188
+ else
189
+ self.#{attribute_name} = []
190
+ end
191
+ end
192
+ eos
193
+ end
194
+ end
195
+
196
+ @boolean_attributes = []
197
+ class << self; attr_reader :boolean_attributes; end
198
+
199
+ def self.boolean_accessor(attribute_name)
200
+ raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol)
201
+ if self.boolean_attributes.include?(attribute_name)
202
+ raise ArgumentError, "Already contains a boolean accessor named `#{attribute_name}`"
203
+ else
204
+ @boolean_attributes << attribute_name
205
+ self.class_eval <<-eos
206
+ attr_reader :#{attribute_name}
207
+ def #{attribute_name}=(value)
208
+ case value
209
+ when nil
210
+ @#{attribute_name} = nil
211
+ when TrueClass, FalseClass
212
+ @#{attribute_name} = value
213
+ else
214
+ @#{attribute_name} = value.present? ? ['1', 1, 'true', 't'].include?(value) : nil
215
+ end
216
+ end
217
+ eos
218
+ end
219
+ end
220
+
221
+ @integer_attributes = []
222
+ class << self; attr_reader :integer_attributes; end
223
+
224
+ def self.integer_accessor(attribute_name)
225
+ raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol)
226
+ if self.integer_attributes.include?(attribute_name)
227
+ raise ArgumentError, "Already contains a integer accessor named `#{attribute_name}`"
228
+ else
229
+ @integer_attributes << attribute_name
230
+ self.class_eval <<-eos
231
+ attr_reader :#{attribute_name}
232
+ attr_reader :#{attribute_name}_unconverted_value
233
+ def #{attribute_name}=(value)
234
+ @#{attribute_name}_unconverted_value = value
235
+ @#{attribute_name} = value.present? && value.to_s =~ /\\A\\s*\\-?\\d+\\s*\\Z/ ? value.to_i : nil
236
+ end
237
+ validate do
238
+ if self.#{attribute_name}_unconverted_value.present? != self.#{attribute_name}.present?
239
+ self.errors.add(:#{attribute_name}, :not_an_integer)
240
+ end
241
+ end
242
+ eos
243
+ end
244
+ end
245
+
246
+ @decimal_attributes = []
247
+ class << self; attr_reader :decimal_attributes; end
248
+
249
+ def self.decimal_accessor(attribute_name, options={})
250
+ raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol)
251
+ if self.decimal_attributes.include?(attribute_name)
252
+ raise ArgumentError, "Already contains a decimal accessor named `#{attribute_name}`"
253
+ else
254
+ decimal_regex = /\A\s*[+-]?\s*\d*(\d,\d)*\d*\.?\d*\s*\Z/
255
+ @decimal_attributes << attribute_name
256
+ self.class_eval <<-eos
257
+ attr_reader :#{attribute_name}
258
+ attr_reader :#{attribute_name}_unconverted_value
259
+ def #{attribute_name}=(value)
260
+ @#{attribute_name}_unconverted_value = value
261
+ @#{attribute_name} = value.present? && value.to_s =~ #{decimal_regex.inspect} ? BigDecimal.new(value.to_s.gsub(/\\s|[,]/, '')) : nil
262
+ end
263
+ validate do
264
+ if self.#{attribute_name}_unconverted_value.present? != self.#{attribute_name}.present?
265
+ self.errors.add(:#{attribute_name}, :not_a_number)
266
+ end
267
+ end
268
+ eos
269
+ end
270
+ end
271
+
272
+ @usd_attributes = []
273
+ class << self; attr_reader :usd_attributes; end
274
+
275
+ def self.usd_accessor(attribute_name, options={})
276
+ raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol)
277
+ if self.usd_attributes.include?(attribute_name)
278
+ raise ArgumentError, "Already contains a usd accessor named `#{attribute_name}`"
279
+ else
280
+ usd_regex = /\A\s*[+-]?\s*\$?\s*\d*(\d,\d)*\d*\.?\d*\s*\Z/
281
+ @usd_attributes << attribute_name
282
+ self.class_eval <<-eos
283
+ attr_reader :#{attribute_name}
284
+ attr_reader :#{attribute_name}_unconverted_value
285
+ def #{attribute_name}=(value)
286
+ @#{attribute_name}_unconverted_value = value
287
+ @#{attribute_name} = value.present? && value.to_s =~ #{usd_regex.inspect} ? BigDecimal.new(value.to_s.gsub(/[\$,]|\\s/, '')) : nil
288
+ end
289
+ validate do
290
+ if self.#{attribute_name}_unconverted_value.present? != self.#{attribute_name}.present?
291
+ self.errors.add(:#{attribute_name}, :invalid)
292
+ end
293
+ end
294
+ eos
295
+ end
296
+ end
297
+
298
+ @date_attributes = []
299
+ class << self; attr_reader :date_attributes; end
300
+
301
+ def self.date_accessor(attribute_name, options={})
302
+ raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol)
303
+ raise ArgumentError, "Expected options[:timezone]=`#{options[:timezone]}` to be an instance of Symbol, String, or Nil" unless options[:timezone].nil? || options[:timezone].is_a?(String) || options[:timezone].is_a?(Symbol)
304
+ if self.date_attributes.include?(attribute_name)
305
+ raise ArgumentError, "Already contains a date accessor named `#{attribute_name}`"
306
+ else
307
+ @date_attributes << attribute_name
308
+ self.class_eval <<-eos
309
+ attr_reader :#{attribute_name}
310
+ attr_reader :#{attribute_name}_unconverted_value
311
+ def #{attribute_name}=(value)
312
+ case value
313
+ when nil
314
+ @#{attribute_name}_unconverted_value = nil
315
+ @#{attribute_name} = nil
316
+ when Time, DateTime
317
+ @#{attribute_name}_unconverted_value = value
318
+ timezone = #{case options[:timezone]; when Symbol; "self.send(#{options[:timezone].inspect})"; when String; "ActiveSupport::TimeZone[#{options[:timezone].inspect}]"; else; "ActiveSupport::TimeZone['UTC']"; end}
319
+ @#{attribute_name} = ActiveSupport::TimeWithZone.new(nil, timezone, (value.is_a?(ActiveSupport::TimeWithZone) ? value.time : value))
320
+ when String
321
+ @#{attribute_name}_unconverted_value = value
322
+ parsed_date = DateTime.parse(value) rescue nil
323
+ timezone = #{case options[:timezone]; when Symbol; "self.send(#{options[:timezone].inspect})"; when String; "ActiveSupport::TimeZone[#{options[:timezone].inspect}]"; else; "ActiveSupport::TimeZone['UTC']"; end}
324
+ @#{attribute_name} = parsed_date ? ActiveSupport::TimeWithZone.new(nil, timezone, parsed_date) : nil
325
+ else
326
+ raise ArgumentError, 'Unexpected value passed to date_accessor #{attribute_name}; expected Time, String, or nil.'
327
+ end
328
+ end
329
+ validate do
330
+ if self.#{attribute_name}_unconverted_value.present? != self.#{attribute_name}.present?
331
+ self.errors.add(:#{attribute_name}, :invalid)
332
+ end
333
+ end
334
+ eos
335
+ end
336
+ end
337
+
338
+ @string_attributes = []
339
+ class << self; attr_reader :string_attributes; end
340
+
341
+ def self.string_accessor(attribute_name, options={})
342
+ raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol)
343
+ if self.string_attributes.include?(attribute_name)
344
+ raise ArgumentError, "Already contains a string accessor named `#{attribute_name}`"
345
+ else
346
+ @string_attributes << attribute_name
347
+ self.class_eval <<-eos
348
+ attr_reader :#{attribute_name}
349
+ def #{attribute_name}=(value)
350
+ if #{options[:strip] == true} && value
351
+ value = value.strip
352
+ end
353
+ value = nil unless value.present?
354
+ @#{attribute_name} = value
355
+ end
356
+ eos
357
+ end
358
+ end
359
+
360
+ @enum_attributes = []
361
+ class << self; attr_reader :enum_attributes; end
362
+
363
+ def self.enum_accessor(attribute_name, enums:, raise_error_on_set: false, allow_nil: true)
364
+ raise ArgumentError, "Expected `#{attribute_name}` to be an instance of Symbol" unless attribute_name.is_a?(Symbol)
365
+ raise ArgumentError, "Expected `enums`: `#{enums}` to be an instance of Array containing only instances of String" unless enums.is_a?(Array) && enums.all? { |e| e.is_a?(String) }
366
+ raise ArgumentError, "Expected `raise_error_on_set`: `#{raise_error_on_set}` to be an instance of TrueClass or FalseClass" unless raise_error_on_set.is_a?(TrueClass) || raise_error_on_set.is_a?(FalseClass)
367
+ raise ArgumentError, "Expected `allow_nil`: `#{allow_nil}` to be an instance of TrueClass or FalseClass" unless allow_nil.is_a?(TrueClass) || allow_nil.is_a?(FalseClass)
368
+
369
+ if self.enum_attributes.include?(attribute_name)
370
+ raise ArgumentError, "Already contains a enum accessor named `#{attribute_name}`"
371
+ else
372
+ @enum_attributes << attribute_name
373
+ self.class_eval <<-eos
374
+ attr_reader :#{attribute_name}
375
+ validates :#{attribute_name}, inclusion: {in: #{(enums + (allow_nil ? [nil] : [])).inspect}}
376
+ def #{attribute_name}=(value)
377
+ value = nil unless value.present?
378
+ if #{raise_error_on_set} && !((#{allow_nil} && value.nil?) || #{enums.inspect}.include?(value))
379
+ raise ArgumentError, 'Expected to receive valid enum string or nil.'
380
+ end
381
+ @#{attribute_name} = value
382
+ end
383
+ def #{attribute_name}_enums
384
+ #{enums.inspect}
385
+ end
386
+ eos
387
+ end
388
+ end
389
+
390
+ def self.inherited(klass)
391
+ klass.class_eval <<-eos
392
+ @associated_model_attributes = []
393
+ @associated_model_collection_attributes = []
394
+ @associated_resource_model_attributes = []
395
+ @associated_resource_model_collection_attributes = []
396
+ @boolean_attributes = []
397
+ @integer_attributes = []
398
+ @decimal_attributes = []
399
+ @usd_attributes = []
400
+ @date_attributes = []
401
+ @string_attributes = []
402
+ @enum_attributes = []
403
+ eos
404
+ class << klass
405
+ def associated_model_attributes
406
+ self.superclass.associated_model_attributes + @associated_model_attributes
407
+ end
408
+ def associated_model_collection_attributes
409
+ self.superclass.associated_model_collection_attributes + @associated_model_collection_attributes
410
+ end
411
+ def associated_resource_model_attributes
412
+ self.superclass.associated_resource_model_attributes + @associated_resource_model_attributes
413
+ end
414
+ def associated_resource_model_collection_attributes
415
+ self.superclass.associated_resource_model_collection_attributes + @associated_resource_model_collection_attributes
416
+ end
417
+ def boolean_attributes
418
+ self.superclass.boolean_attributes + @boolean_attributes
419
+ end
420
+ def integer_attributes
421
+ self.superclass.integer_attributes + @integer_attributes
422
+ end
423
+ def decimal_attributes
424
+ self.superclass.decimal_attributes + @decimal_attributes
425
+ end
426
+ def usd_attributes
427
+ self.superclass.usd_attributes + @usd_attributes
428
+ end
429
+ def date_attributes
430
+ self.superclass.date_attributes + @date_attributes
431
+ end
432
+ def string_attributes
433
+ self.superclass.date_attributes + @string_attributes
434
+ end
435
+ def enum_attributes
436
+ self.superclass.date_attributes + @enum_attributes
437
+ end
438
+ end
439
+ end
440
+
441
+ def initialize(attributes={})
442
+ self.attributes = attributes
443
+ end
444
+
445
+ def attributes=(attributes)
446
+ (
447
+ self.class.associated_resource_model_collection_attributes +
448
+ self.class.associated_model_collection_attributes
449
+ ).each do |attribute|
450
+ unless (value = self.send(attribute)).is_a?(Array) && value.present?
451
+ self.send("#{attribute}=", [])
452
+ end
453
+ end
454
+
455
+ if attributes.present?
456
+ attributes = attributes.dup
457
+
458
+ (
459
+ self.class.associated_resource_model_attributes +
460
+ self.class.associated_resource_model_collection_attributes
461
+ ).each do |attribute|
462
+ attribute_attributes_key = "#{attribute}_attributes".to_sym
463
+ if attributes.key?(attribute)
464
+ self.send("#{attribute}=", attributes.delete(attribute))
465
+ end
466
+ if attributes.key?(attribute_attributes_key)
467
+ self.send("#{attribute_attributes_key}=", attributes.delete(attribute_attributes_key))
468
+ end
469
+ end
470
+
471
+ self.class.associated_model_attributes.each do |attribute|
472
+ id_attribute = "#{attribute}_id".to_sym
473
+ if attributes.key?(attribute)
474
+ self.send("#{attribute}=", attributes.delete(attribute))
475
+ attributes.delete(id_attribute)
476
+ elsif attributes.key?(id_attribute)
477
+ self.send("#{id_attribute}=", attributes.delete(id_attribute))
478
+ end
479
+ end
480
+
481
+ self.class.associated_model_collection_attributes.each do |attribute|
482
+ ids_attribute = "#{attribute}_ids"
483
+ if attributes.key?(attribute)
484
+ self.send("#{attribute}=", attributes.delete(attribute))
485
+ attributes.delete(ids_attribute)
486
+ elsif attributes.key?(ids_attribute)
487
+ self.send("#{ids_attribute}=", attributes.delete(ids_attribute))
488
+ end
489
+ end
490
+
491
+ attributes.each do |name, value|
492
+ send("#{name}=", value)
493
+ end
494
+ end
495
+ end
496
+
497
+ def to_json_attributes
498
+ hash = {}
499
+ self.class.boolean_attributes.each do |attribute_name|
500
+ hash[attribute_name] = self.send(attribute_name)
501
+ end
502
+ self.class.integer_attributes.each do |attribute_name|
503
+ hash[attribute_name] = self.send(attribute_name)
504
+ end
505
+ self.class.decimal_attributes.each do |attribute_name|
506
+ hash[attribute_name] = self.send(attribute_name).andand.to_s
507
+ end
508
+ self.class.usd_attributes.each do |attribute_name|
509
+ hash[attribute_name] = self.send(attribute_name).andand.to_s
510
+ end
511
+ self.class.date_attributes.each do |attribute_name|
512
+ hash[attribute_name] = self.send(attribute_name).andand.iso8601
513
+ end
514
+ self.class.string_attributes.each do |attribute_name|
515
+ hash[attribute_name] = self.send(attribute_name)
516
+ end
517
+ self.class.enum_attributes.each do |attribute_name|
518
+ hash[attribute_name] = self.send(attribute_name)
519
+ end
520
+ self.class.associated_model_attributes.each do |attribute_name|
521
+ id_attribute_name = "#{attribute_name}_id"
522
+ value = self.send(id_attribute_name)
523
+ if value
524
+ hash[id_attribute_name.to_sym] = value
525
+ end
526
+ end
527
+ self.class.associated_model_collection_attributes.each do |attribute_name|
528
+ ids_attribute_name = "#{attribute_name}_ids"
529
+ value = self.send(ids_attribute_name)
530
+ if value
531
+ hash[ids_attribute_name] = value
532
+ end
533
+ end
534
+ self.class.associated_resource_model_attributes.each do |attribute_name|
535
+ value = self.send(attribute_name)
536
+ if value
537
+ hash["#{attribute_name}_attributes".to_sym] = value.to_json_attributes
538
+ end
539
+ end
540
+ self.class.associated_resource_model_collection_attributes.each do |attribute_name|
541
+ hash["#{attribute_name}_attributes".to_sym] = self.send(attribute_name).inject({}) do |sub_hash, item|
542
+ sub_hash[sub_hash.size] = item.to_json_attributes
543
+ sub_hash
544
+ end
545
+ end
546
+
547
+ hash
548
+ end
549
+
550
+ end
@@ -0,0 +1,3 @@
1
+ module ResourceModel
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'resource_model/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "resource_model"
8
+ spec.version = ResourceModel::VERSION
9
+ spec.authors = ["James Coleman"]
10
+ spec.email = ["jtc331@gmail.com"]
11
+ spec.summary = %q{Smart models to back your resources actions.}
12
+ spec.description = %q{All of the goodness of ActiveModel (validations, callbacks, etc.) along with declarative typed accessors, JSON serialization, and more.}
13
+ spec.homepage = "https://github.com/jcoleman/resource_model"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+
24
+ spec.add_dependency "activerecord", "~> 4.0"
25
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: resource_model
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - James Coleman
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-12-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activerecord
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '4.0'
55
+ description: All of the goodness of ActiveModel (validations, callbacks, etc.) along
56
+ with declarative typed accessors, JSON serialization, and more.
57
+ email:
58
+ - jtc331@gmail.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".gitignore"
64
+ - Gemfile
65
+ - LICENSE.txt
66
+ - README.md
67
+ - Rakefile
68
+ - lib/resource_model.rb
69
+ - lib/resource_model/base.rb
70
+ - lib/resource_model/version.rb
71
+ - resource_model.gemspec
72
+ homepage: https://github.com/jcoleman/resource_model
73
+ licenses:
74
+ - MIT
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 2.4.5
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: Smart models to back your resources actions.
96
+ test_files: []