sunstone 0.1.0 → 1.0.0

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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/lib/active_record/connection_adapters/sunstone/column.rb +19 -0
  3. data/lib/active_record/connection_adapters/sunstone/database_statements.rb +40 -0
  4. data/lib/active_record/connection_adapters/sunstone/schema_statements.rb +95 -0
  5. data/lib/active_record/connection_adapters/sunstone/type/date_time.rb +22 -0
  6. data/lib/active_record/connection_adapters/sunstone_adapter.rb +177 -0
  7. data/lib/arel/collectors/sunstone.rb +75 -0
  8. data/lib/arel/visitors/sunstone.rb +769 -0
  9. data/lib/ext/active_record/associations/builder/has_and_belongs_to_many.rb +48 -0
  10. data/lib/ext/active_record/relation.rb +26 -0
  11. data/lib/ext/active_record/statement_cache.rb +24 -0
  12. data/lib/sunstone.rb +37 -347
  13. data/lib/sunstone/connection.rb +337 -0
  14. data/sunstone.gemspec +3 -2
  15. data/test/sunstone/connection_test.rb +319 -0
  16. data/test/sunstone/parser_test.rb +21 -21
  17. metadata +30 -36
  18. data/lib/sunstone/model.rb +0 -23
  19. data/lib/sunstone/model/attributes.rb +0 -99
  20. data/lib/sunstone/model/persistence.rb +0 -168
  21. data/lib/sunstone/schema.rb +0 -38
  22. data/lib/sunstone/type/boolean.rb +0 -19
  23. data/lib/sunstone/type/date_time.rb +0 -20
  24. data/lib/sunstone/type/decimal.rb +0 -19
  25. data/lib/sunstone/type/integer.rb +0 -17
  26. data/lib/sunstone/type/mutable.rb +0 -16
  27. data/lib/sunstone/type/string.rb +0 -18
  28. data/lib/sunstone/type/value.rb +0 -97
  29. data/test/sunstone/model/associations_test.rb +0 -55
  30. data/test/sunstone/model/attributes_test.rb +0 -60
  31. data/test/sunstone/model/persistence_test.rb +0 -173
  32. data/test/sunstone/model_test.rb +0 -11
  33. data/test/sunstone/schema_test.rb +0 -25
  34. data/test/sunstone/type/boolean_test.rb +0 -24
  35. data/test/sunstone/type/date_time_test.rb +0 -31
  36. data/test/sunstone/type/decimal_test.rb +0 -27
  37. data/test/sunstone/type/integer_test.rb +0 -29
  38. data/test/sunstone/type/string_test.rb +0 -54
  39. data/test/sunstone/type/value_test.rb +0 -27
@@ -1,10 +1,10 @@
1
1
  require 'test_helper'
2
2
 
3
- class TestModel < Sunstone::Model
3
+ class TestParserModel < Sunstone::Model
4
4
 
5
- belongs_to :test_model
5
+ belongs_to :test_parser_model
6
6
 
7
- has_many :test_models
7
+ has_many :test_parser_models
8
8
 
9
9
  define_schema do
10
10
  integer :testid
@@ -19,11 +19,11 @@ end
19
19
  class Sunstone::ParserTest < Minitest::Test
20
20
 
21
21
  test '::parse(klass, string)' do
22
- assert_equal true, Sunstone::Parser.parse(TestModel, '{"red": true}').red
22
+ assert_equal true, Sunstone::Parser.parse(TestParserModel, '{"red": true}').red
23
23
  end
24
24
 
25
25
  test '::parse(model_instance, string)' do
26
- model = TestModel.new
26
+ model = TestParserModel.new
27
27
  Sunstone::Parser.parse(model, '{"red": true}')
28
28
  assert_equal true, model.red
29
29
  end
@@ -33,71 +33,71 @@ class Sunstone::ParserTest < Minitest::Test
33
33
  stub_request(:get, "http://testhost.com/test").to_return(:body => '{"red": true}')
34
34
 
35
35
  model = Sunstone.get('/test') do |response|
36
- Sunstone::Parser.parse(TestModel, response)
36
+ Sunstone::Parser.parse(TestParserModel, response)
37
37
  end
38
38
 
39
39
  assert_equal true, model.red
40
40
  end
41
41
 
42
42
  test "parse boolean attributes" do
43
- parser = Sunstone::Parser.new(TestModel)
43
+ parser = Sunstone::Parser.new(TestParserModel)
44
44
  assert_equal true, parser.parse('{"red": true}').red
45
45
 
46
- parser = Sunstone::Parser.new(TestModel)
46
+ parser = Sunstone::Parser.new(TestParserModel)
47
47
  assert_equal false, parser.parse('{"red": false}').red
48
48
  end
49
49
 
50
50
  test "parse date attributes" do
51
- parser = Sunstone::Parser.new(TestModel)
51
+ parser = Sunstone::Parser.new(TestParserModel)
52
52
  assert_equal DateTime.new(2014, 7, 14, 16, 44, 15, '-7'), parser.parse('{"created_at": "2014-07-14T16:44:15-07:00"}').created_at
53
53
  end
54
54
 
55
55
  test "parse decimal attributes" do
56
- parser = Sunstone::Parser.new(TestModel)
56
+ parser = Sunstone::Parser.new(TestParserModel)
57
57
  assert_equal 10.254, parser.parse('{"rate": 10.254}').rate
58
58
  end
59
59
 
60
60
  test "parse integer attributes" do
61
- parser = Sunstone::Parser.new(TestModel)
61
+ parser = Sunstone::Parser.new(TestParserModel)
62
62
  assert_equal 123654, parser.parse('{"testid": 123654}').testid
63
63
  end
64
64
 
65
65
  test "parse string attributes" do
66
- parser = Sunstone::Parser.new(TestModel)
66
+ parser = Sunstone::Parser.new(TestParserModel)
67
67
  assert_equal "my name", parser.parse('{"name": "my name"}').name
68
68
  end
69
69
 
70
70
  test "parse array attribute" do
71
- parser = Sunstone::Parser.new(TestModel)
71
+ parser = Sunstone::Parser.new(TestParserModel)
72
72
  assert_equal ["name 1", "name 2"], parser.parse('{"nicknames": ["name 1", "name 2"]}').nicknames
73
73
  end
74
74
 
75
75
  test "parse skips over unkown key" do
76
76
  assert_nothing_raised do
77
- Sunstone::Parser.parse(TestModel, '{"other_key": "name 2"}')
78
- Sunstone::Parser.parse(TestModel, '{"other_key": ["name 1", "name 2"]}')
77
+ Sunstone::Parser.parse(TestParserModel, '{"other_key": "name 2"}')
78
+ Sunstone::Parser.parse(TestParserModel, '{"other_key": ["name 1", "name 2"]}')
79
79
  end
80
80
  end
81
81
 
82
82
  test "parse belong_to association" do
83
- parser = Sunstone::Parser.new(TestModel)
83
+ parser = Sunstone::Parser.new(TestParserModel)
84
84
  assert_equal({
85
85
  :rate => BigDecimal.new("10.254"),
86
86
  :created_at => DateTime.new(2014, 7, 14, 16, 44, 15, '-7'),
87
87
  :testid => 123654,
88
88
  :name => "my name",
89
89
  :nicknames => ["name 1", "name 2"]
90
- }, parser.parse('{"test_model": {
90
+ }, parser.parse('{"test_parser_model": {
91
91
  "rate": 10.254,
92
92
  "created_at": "2014-07-14T16:44:15-07:00",
93
93
  "testid": 123654,
94
94
  "name": "my name",
95
95
  "nicknames": ["name 1", "name 2"]
96
- }}').test_model.instance_variable_get(:@attributes))
96
+ }}').test_parser_model.instance_variable_get(:@attributes))
97
97
  end
98
98
 
99
99
  test "parse has_many association" do
100
- parser = Sunstone::Parser.new(TestModel)
100
+ parser = Sunstone::Parser.new(TestParserModel)
101
101
  attrs = {
102
102
  :rate => BigDecimal.new("10.254"),
103
103
  :created_at => DateTime.new(2014, 7, 14, 16, 44, 15, '-7'),
@@ -106,7 +106,7 @@ class Sunstone::ParserTest < Minitest::Test
106
106
  :nicknames => ["name 1", "name 2"]
107
107
  }
108
108
 
109
- assert_equal([attrs, attrs], parser.parse('{"test_models": [{
109
+ assert_equal([attrs, attrs], parser.parse('{"test_parser_models": [{
110
110
  "rate": 10.254,
111
111
  "created_at": "2014-07-14T16:44:15-07:00",
112
112
  "testid": 123654,
@@ -118,7 +118,7 @@ class Sunstone::ParserTest < Minitest::Test
118
118
  "testid": 123654,
119
119
  "name": "my name",
120
120
  "nicknames": ["name 1", "name 2"]
121
- }]}').test_models.map{|m| m.instance_variable_get(:@attributes)})
121
+ }]}').test_parser_models.map{|m| m.instance_variable_get(:@attributes)})
122
122
  end
123
123
 
124
124
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sunstone
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Bracy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-19 00:00:00.000000000 Z
11
+ date: 2014-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -192,6 +192,20 @@ dependencies:
192
192
  - - ">="
193
193
  - !ruby/object:Gem::Version
194
194
  version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: arel
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :runtime
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
195
209
  - !ruby/object:Gem::Dependency
196
210
  name: activesupport
197
211
  requirement: !ruby/object:Gem::Requirement
@@ -221,7 +235,7 @@ dependencies:
221
235
  - !ruby/object:Gem::Version
222
236
  version: '0'
223
237
  - !ruby/object:Gem::Dependency
224
- name: connection_pool
238
+ name: activerecord
225
239
  requirement: !ruby/object:Gem::Requirement
226
240
  requirements:
227
241
  - - ">="
@@ -247,34 +261,24 @@ files:
247
261
  - README.md
248
262
  - Rakefile.rb
249
263
  - TODO.md
264
+ - lib/active_record/connection_adapters/sunstone/column.rb
265
+ - lib/active_record/connection_adapters/sunstone/database_statements.rb
266
+ - lib/active_record/connection_adapters/sunstone/schema_statements.rb
267
+ - lib/active_record/connection_adapters/sunstone/type/date_time.rb
268
+ - lib/active_record/connection_adapters/sunstone_adapter.rb
269
+ - lib/arel/collectors/sunstone.rb
270
+ - lib/arel/visitors/sunstone.rb
271
+ - lib/ext/active_record/associations/builder/has_and_belongs_to_many.rb
272
+ - lib/ext/active_record/relation.rb
273
+ - lib/ext/active_record/statement_cache.rb
250
274
  - lib/sunstone.rb
275
+ - lib/sunstone/connection.rb
251
276
  - lib/sunstone/exception.rb
252
- - lib/sunstone/model.rb
253
277
  - lib/sunstone/model/associations.rb
254
- - lib/sunstone/model/attributes.rb
255
- - lib/sunstone/model/persistence.rb
256
278
  - lib/sunstone/parser.rb
257
- - lib/sunstone/schema.rb
258
- - lib/sunstone/type/boolean.rb
259
- - lib/sunstone/type/date_time.rb
260
- - lib/sunstone/type/decimal.rb
261
- - lib/sunstone/type/integer.rb
262
- - lib/sunstone/type/mutable.rb
263
- - lib/sunstone/type/string.rb
264
- - lib/sunstone/type/value.rb
265
279
  - sunstone.gemspec
266
- - test/sunstone/model/associations_test.rb
267
- - test/sunstone/model/attributes_test.rb
268
- - test/sunstone/model/persistence_test.rb
269
- - test/sunstone/model_test.rb
280
+ - test/sunstone/connection_test.rb
270
281
  - test/sunstone/parser_test.rb
271
- - test/sunstone/schema_test.rb
272
- - test/sunstone/type/boolean_test.rb
273
- - test/sunstone/type/date_time_test.rb
274
- - test/sunstone/type/decimal_test.rb
275
- - test/sunstone/type/integer_test.rb
276
- - test/sunstone/type/string_test.rb
277
- - test/sunstone/type/value_test.rb
278
282
  - test/sunstone_test.rb
279
283
  - test/test_helper.rb
280
284
  homepage: http://sunstonerb.com
@@ -301,18 +305,8 @@ signing_key:
301
305
  specification_version: 4
302
306
  summary: A library for interacting with REST APIs
303
307
  test_files:
304
- - test/sunstone/model/associations_test.rb
305
- - test/sunstone/model/attributes_test.rb
306
- - test/sunstone/model/persistence_test.rb
307
- - test/sunstone/model_test.rb
308
+ - test/sunstone/connection_test.rb
308
309
  - test/sunstone/parser_test.rb
309
- - test/sunstone/schema_test.rb
310
- - test/sunstone/type/boolean_test.rb
311
- - test/sunstone/type/date_time_test.rb
312
- - test/sunstone/type/decimal_test.rb
313
- - test/sunstone/type/integer_test.rb
314
- - test/sunstone/type/string_test.rb
315
- - test/sunstone/type/value_test.rb
316
310
  - test/sunstone_test.rb
317
311
  - test/test_helper.rb
318
312
  has_rdoc:
@@ -1,23 +0,0 @@
1
- require 'sunstone/model/attributes'
2
- require 'sunstone/model/associations'
3
- require 'sunstone/model/persistence'
4
-
5
- module Sunstone
6
- class Model
7
-
8
- extend ActiveModel::Naming
9
- include ActiveModel::Conversion
10
-
11
- include Sunstone::Model::Attributes
12
- include Sunstone::Model::Associations
13
- include Sunstone::Model::Persistence
14
-
15
- def initialize(attrs={})
16
- super
17
- attrs.each do |k, v|
18
- self.send(:"#{k}=", v)
19
- end
20
- end
21
-
22
- end
23
- end
@@ -1,99 +0,0 @@
1
- module Sunstone
2
- class Model
3
-
4
- class SchemaDefiner
5
-
6
- attr_reader :defined_attributes
7
-
8
- def initialize(schema)
9
- @schema = schema
10
- @defined_attributes = []
11
- end
12
-
13
- def attribute(name, type, options = {})
14
- @schema.attribute(name, type, options)
15
- @defined_attributes << name
16
- end
17
-
18
- Sunstone::Type::Value.subclasses.each do |type|
19
- class_eval <<-EOV, __FILE__, __LINE__ + 1
20
- def #{type.name.demodulize.downcase}(name, options = {})
21
- attribute(name, "#{type.name.demodulize.downcase}", options)
22
- end
23
- EOV
24
- end
25
-
26
- end
27
-
28
- module Attributes
29
-
30
- extend ActiveSupport::Concern
31
-
32
- attr_accessor :attributes
33
-
34
- def initialize(*)
35
- @attributes = {}
36
- end
37
-
38
- def schema
39
- self.class.schema
40
- end
41
-
42
- def has?(attribute)
43
- !!@attributes[attribute]
44
- end
45
-
46
- module ClassMethods
47
-
48
- def inherited(subclass)
49
- super
50
- subclass.initialize_schema
51
- end
52
-
53
- def initialize_schema
54
- @schema = Sunstone::Schema.new
55
- attribute(:id, :integer)
56
- end
57
-
58
- def schema
59
- @schema
60
- end
61
-
62
- def define_schema(&block)
63
- definer = SchemaDefiner.new(@schema)
64
- definer.instance_eval(&block)
65
-
66
- definer.defined_attributes.each do |name|
67
- define_attribute_reader(name, @schema[name])
68
- define_attribute_writer(name, @schema[name])
69
- end
70
- end
71
-
72
- def attribute(name, type, options = {})
73
- attribute = @schema.attribute(name, type, options)
74
-
75
- define_attribute_reader(name, attribute)
76
- define_attribute_writer(name, attribute)
77
- end
78
-
79
- def define_attribute_reader(name, type)
80
- class_eval <<-EOV, __FILE__, __LINE__ + 1
81
- def #{name}
82
- @attributes[:#{name}]
83
- end
84
- EOV
85
- end
86
-
87
- def define_attribute_writer(name, type)
88
- class_eval <<-EOV, __FILE__, __LINE__ + 1
89
- def #{name}=(value)
90
- @attributes[:#{name}] = schema[:#{name}].type_cast_from_user(value)
91
- end
92
- EOV
93
- end
94
-
95
- end
96
-
97
- end
98
- end
99
- end
@@ -1,168 +0,0 @@
1
- class Wankel::SaxEncoder
2
-
3
- def value(val)
4
- if val.is_a?(Numeric)
5
- number(val)
6
- elsif val.is_a?(String)
7
- string(val)
8
- elsif val.nil?
9
- null
10
- elsif val == true || val == false
11
- boolean(val)
12
- elsif val.is_a?(Array)
13
- array_open
14
- val.each {|v| value(v) }
15
- array_close
16
- else
17
- puts 'fail'
18
- end
19
- end
20
-
21
- end
22
-
23
- module Sunstone
24
- class Model
25
-
26
- module Persistence
27
-
28
- extend ActiveSupport::Concern
29
-
30
- def initialize(*)
31
- super
32
- @new_record = true
33
- end
34
-
35
- # Returns true if this object hasn't been saved yet -- that is, a record
36
- # for the object doesn't exist in the database yet; otherwise, returns false.
37
- def new_record?
38
- @new_record
39
- end
40
-
41
- # Returns true if this object has been destroyed, otherwise returns false.
42
- def destroyed?
43
- @destroyed
44
- end
45
-
46
- # Returns true if the record is persisted, i.e. it's not a new record and
47
- # it was not destroyed, otherwise returns false.
48
- def persisted?
49
- !(new_record? || destroyed?)
50
- end
51
-
52
- def serialize(options={})
53
- attrs = options[:only] || schema.attributes.keys
54
-
55
- output = StringIO.new
56
- encoder = Wankel::SaxEncoder.new(output)
57
-
58
- encoder.map_open
59
-
60
- attrs.each do |name|
61
- encoder.string name
62
- encoder.value schema[name].type_cast_for_json(self.send(name))
63
- end
64
-
65
- encoder.map_close
66
- encoder.complete
67
- output.string
68
- end
69
-
70
- def serialize_for_create_and_update
71
- attrs = []
72
- schema.attributes.each do |name, type|
73
- attrs << name if name != "id" && !type.readonly?
74
- end
75
-
76
- serialize(:only => attrs)
77
- end
78
-
79
- # Saves the model.
80
- #
81
- # If the model is new a record gets created, otherwise the existing record
82
- # gets updated.
83
- #
84
- # TODO:
85
- # By default, save always run validations. If any of them fail the action
86
- # is cancelled and +save+ returns +false+. However, if you supply
87
- # validate: false, validations are bypassed altogether. See
88
- # ActiveRecord::Validations for more information.
89
- #
90
- # TODO:
91
- # There's a series of callbacks associated with +save+. If any of the
92
- # <tt>before_*</tt> callbacks return +false+ the action is cancelled and
93
- # +save+ returns +false+. See ActiveRecord::Callbacks for further
94
- # details.
95
- #
96
- # Attributes marked as readonly are silently ignored if the record is
97
- # being updated.
98
- def save(*)
99
- create_or_update
100
- rescue Sunstone::RecordInvalid
101
- false
102
- end
103
-
104
- # Saves the model.
105
- #
106
- # If the model is new a record gets created, otherwise the existing record
107
- # gets updated.
108
- #
109
- # TODO:
110
- # With <tt>save!</tt> validations always run. If any of them fail
111
- # ActiveRecord::RecordInvalid gets raised. See ActiveRecord::Validations
112
- # for more information.
113
- #
114
- # TODO:
115
- # There's a series of callbacks associated with <tt>save!</tt>. If any of
116
- # the <tt>before_*</tt> callbacks return +false+ the action is cancelled
117
- # and <tt>save!</tt> raises ActiveRecord::RecordNotSaved. See
118
- # ActiveRecord::Callbacks for further details.
119
- #
120
- # Attributes marked as readonly are silently ignored if the record is
121
- # being updated.
122
- def save!(*)
123
- create_or_update || raise(RecordNotSaved)
124
- end
125
-
126
- private
127
-
128
- def create_or_update
129
- result = new_record? ? _create_record : _update_record
130
- result != false
131
- end
132
-
133
- def _create_record
134
- begin
135
- Sunstone.post("/#{self.class.model_name.route_key}", serialize_for_create_and_update) do |response|
136
- Sunstone::Parser.parse(self, response)
137
- end
138
- @new_record = false
139
- true
140
- rescue Sunstone::Exception::BadRequest => e
141
- Sunstone::Parser.parse(self, e.response)
142
- raise Sunstone::RecordInvalid
143
- end
144
- end
145
-
146
- def _update_record
147
- Sunstone.put("/#{self.class.model_name.route_key}/#{self.to_param}", serialize_for_create_and_update) do |response|
148
- Sunstone::Parser.parse(self, response)
149
- end
150
- end
151
-
152
- module ClassMethods
153
-
154
- def find(id)
155
- Sunstone.get("/#{self.model_name.route_key}/#{id}") do |response|
156
- model = Sunstone::Parser.parse(self, response)
157
- model.instance_variable_set(:@new_record, false)
158
- model
159
- end
160
- end
161
-
162
- end
163
-
164
-
165
- end
166
-
167
- end
168
- end