arrest 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/lib/arrest.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "arrest/version"
2
2
 
3
+ require "arrest/attributes/belongs_to"
3
4
  require "arrest/attributes/has_attributes"
4
5
  require "arrest/attributes/converter"
5
6
  require "arrest/source"
@@ -64,7 +64,7 @@ module Arrest
64
64
  @child_collections = {}
65
65
  end
66
66
  if @child_collections[method_name] == nil
67
- @child_collections[method_name] = ChildCollection.new(self, (StringUtils.classify clazz_name))
67
+ @child_collections[method_name] = ChildCollection.new(self, (StringUtils.classify (StringUtils.singular clazz_name)))
68
68
  end
69
69
 
70
70
  @child_collections[method_name]
@@ -92,18 +92,10 @@ module Arrest
92
92
  end
93
93
  end
94
94
 
95
- def belongs_to(*args)
96
- arg = args[0]
97
- name = arg.to_s.downcase
98
- attributes({"#{name}_id".to_sym => String})
99
- send :define_method, name do
100
- val = self.instance_variable_get("@#{name}_id")
101
- Arrest::Source.mod.const_get(StringUtils.classify name).find(val)
102
- end
103
- end
104
-
105
95
  end
106
96
 
97
+ include BelongsTo
98
+
107
99
  attr_accessor :id
108
100
  attr_reader :stub
109
101
 
@@ -132,6 +124,8 @@ module Arrest
132
124
  val = self.instance_variable_get("@#{field.name.to_s}")
133
125
  if val != nil && val.is_a?(NestedResource)
134
126
  val = val.to_hash
127
+ elsif val != nil && field.is_a?(NestedCollection)
128
+ val = val.map {|v| v.to_hash}
135
129
  end
136
130
  result[json_name] = val
137
131
  end
@@ -0,0 +1,32 @@
1
+ module Arrest
2
+ # Manages an id field of an external resource referenced by this resource.
3
+ # Provides accessor to load exteral resource.
4
+ module BelongsTo
5
+ def self.included(base) # :nodoc:
6
+ base.extend BelongsToMethods
7
+ end
8
+
9
+ module BelongsToMethods
10
+ def belongs_to(*args)
11
+ arg = args[0]
12
+ name = arg.to_s.downcase
13
+ class_name = StringUtils.classify name
14
+ params = args[1] unless args.length < 2
15
+ field_name = "#{name}_id"
16
+ if params
17
+ field_name = params[:field_name] unless params[:field_name] == nil
18
+ class_name = params[:class_name].to_s unless params[:class_name] == nil
19
+ end
20
+ attributes({field_name.to_sym => String})
21
+ send :define_method, name do
22
+ val = self.send(field_name)
23
+ begin
24
+ Arrest::Source.mod.const_get(class_name).find(val)
25
+ rescue Errors::DocumentNotFoundError => e
26
+ raise Errors::DocumentNotFoundError, "Couldnt find a #{class_name} with id #{val}"
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -30,15 +30,23 @@ module Arrest
30
30
 
31
31
  def convert value
32
32
  return unless value
33
- resolved_class.new value
33
+ @clazz.new value
34
+ end
35
+ end
36
+
37
+ class NestedCollection < Attribute
38
+ def initialize name, read_only, clazz
39
+ super name, read_only, clazz
34
40
  end
35
41
 
36
- def resolved_class
37
- if @clazz == nil
38
- @clazz = Source.mod.const_get(@clazz_name)
42
+ def convert value
43
+ return unless value
44
+ raise "Expected an array but got #{value.class.name}" unless value.is_a?(Array)
45
+ value.map do |v|
46
+ @clazz.new v
39
47
  end
40
- @clazz
41
48
  end
49
+
42
50
  end
43
51
 
44
52
  CONVERTER = {}
@@ -92,6 +92,22 @@ module Arrest
92
92
 
93
93
  end
94
94
 
95
+ def nested_array name, clazz
96
+ add_attribute NestedCollection.new(name, false, clazz)
97
+
98
+ send :define_method, "#{name}=" do |v|
99
+ self.unstub
100
+ self.instance_variable_set("@#{name}", v)
101
+ end
102
+ send :define_method, "#{name}" do
103
+ self.unstub
104
+ self.instance_variable_get("@#{name}")
105
+ end
106
+
107
+ end
108
+
95
109
  end
110
+
111
+
96
112
  end
97
113
  end
@@ -4,6 +4,7 @@ module Arrest
4
4
  # an other NestedResource
5
5
  class NestedResource
6
6
  include HasAttributes
7
+ include BelongsTo
7
8
 
8
9
  def initialize h
9
10
  init_from_hash h
@@ -28,6 +28,10 @@ module Arrest
28
28
  end
29
29
  end
30
30
 
31
+ def find id
32
+ raise "find cannot be executed for child resources - use find_for with a parent"
33
+ end
34
+
31
35
  def find_for parent,id
32
36
  r = source().get_one "#{self.resource_path_for(parent)}/#{id}"
33
37
  body = body_root(r)
@@ -45,7 +45,8 @@ class StringUtils
45
45
  def classify(str, upper_first = true)
46
46
  result = ""
47
47
  upperNext = false
48
- (singular str) .each_char do |c|
48
+ #(singular str) .each_char do |c|
49
+ (str) .each_char do |c|
49
50
  if c == "_"
50
51
  upperNext = true
51
52
  else
@@ -1,3 +1,3 @@
1
1
  module Arrest
2
- VERSION = "0.0.6"
2
+ VERSION = "0.0.7"
3
3
  end
data/test/models.rb CHANGED
@@ -41,3 +41,28 @@ class WithNested < Arrest::RootResource
41
41
  nested :nested_object, ANestedClass
42
42
  end
43
43
 
44
+ class WithManyNested < Arrest::RootResource
45
+ attribute :parent_name, String
46
+ attribute :bool, Boolean
47
+ nested_array :nested_objects, ANestedClass
48
+ end
49
+
50
+
51
+ class ANestedClassBelonging < Arrest::NestedResource
52
+ attribute :name, String
53
+ attribute :bool, Boolean
54
+
55
+ belongs_to :zoo
56
+ end
57
+
58
+ class WithNestedBelongingTo < Arrest::RootResource
59
+ attribute :parent_name, String
60
+ attribute :bool, Boolean
61
+ nested :nested_object, ANestedClassBelonging
62
+ end
63
+
64
+ class CustomNamedBelongsTo < Arrest::RootResource
65
+ attribute :name, String
66
+ belongs_to :zoo_thing, { :field_name => :schinken, :class_name => :Zoo}
67
+ belongs_to :zoo, { :field_name => :batzen}
68
+ end
@@ -26,7 +26,6 @@ class NestedResourcesTest < Test::Unit::TestCase
26
26
  actual = WithNested.new(input)
27
27
  assert_equal 'parent', actual.parent_name
28
28
  assert_equal false, actual.bool
29
- puts actual.inspect
30
29
  assert actual.respond_to? :nested_object, "The parent object should have an accessor for the nested object"
31
30
  assert_equal 'iamnested', actual.nested_object.name
32
31
  assert_equal true, actual.nested_object.bool
@@ -58,6 +57,97 @@ class NestedResourcesTest < Test::Unit::TestCase
58
57
 
59
58
  end
60
59
 
60
+ def test_many_to_hash
61
+ input = {
62
+ :parent_name => 'parent',
63
+ :bool => false,
64
+ :nested_objects => [
65
+ {
66
+ :name => 'iamnested_one',
67
+ :bool => true
68
+ },{
69
+ :name => 'iamnested_two',
70
+ :bool => false
71
+ }
72
+ ]
73
+ }
74
+
75
+ actual = WithManyNested.new(input)
76
+
77
+ # we expect camel cased keys
78
+ expected = {
79
+ 'parentName' => 'parent',
80
+ 'bool' => false,
81
+ 'nestedObjects' => [
82
+ {
83
+ 'name' => 'iamnested_one',
84
+ 'bool' => true
85
+ },{
86
+ 'name' => 'iamnested_two',
87
+ 'bool' => false
88
+ }
89
+ ]
90
+ }
91
+
92
+ assert_equal_hashes expected, actual.to_hash
93
+
94
+ end
95
+
96
+ def test_belongd_to_to_hash
97
+ new_zoo = Zoo.new({:name => "Foo"})
98
+ new_zoo.save
99
+
100
+ input = {
101
+ :parent_name => 'parent',
102
+ :bool => false,
103
+ :nested_object => {
104
+ :name => 'iamnested',
105
+ :bool => true,
106
+ :zoo_id => new_zoo.id
107
+ }
108
+ }
109
+
110
+ actual = WithNestedBelongingTo.new(input)
111
+
112
+ # we expect camel cased keys
113
+ expected = {
114
+ 'parentName' => 'parent',
115
+ 'bool' => false,
116
+ 'nestedObject' => {
117
+ 'name' => 'iamnested',
118
+ 'bool' => true,
119
+ 'zooId' => new_zoo.id
120
+
121
+ }
122
+ }
123
+
124
+ assert_equal_hashes expected, actual.to_hash
125
+
126
+ zoo = actual.nested_object.zoo
127
+ assert_equal "Foo", zoo.name
128
+
129
+ end
130
+
131
+ def test_custom_belongs_to
132
+
133
+ new_zoo = Zoo.new({:name => "Foo"})
134
+ new_zoo.save
135
+
136
+ c = CustomNamedBelongsTo.new({:name => 'Bar', :schinken => new_zoo.id, :batzen => new_zoo.id})
137
+
138
+ c.save
139
+ assert_not_nil c.id, "Persisted object should have id"
140
+ assert_equal "Foo", c.zoo_thing.name
141
+ assert_equal "Foo", c.zoo.name
142
+
143
+
144
+ assert_not_nil c.id, "Persisted zoo should have id"
145
+ c_reloaded = CustomNamedBelongsTo.all.first
146
+ assert_equal "Foo", c_reloaded.zoo_thing.name
147
+ assert_equal "Foo", c_reloaded.zoo.name
148
+
149
+ end
150
+
61
151
  def assert_equal_hashes expected, actual
62
152
  assert_equal_hashes_ expected, actual, ''
63
153
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arrest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-02 00:00:00.000000000Z
12
+ date: 2011-12-05 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
16
- requirement: &2162431160 !ruby/object:Gem::Requirement
16
+ requirement: &2154189380 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2162431160
24
+ version_requirements: *2154189380
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: faraday
27
- requirement: &2162430460 !ruby/object:Gem::Requirement
27
+ requirement: &2154188840 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - =
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 0.7.5
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2162430460
35
+ version_requirements: *2154188840
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: bundler
38
- requirement: &2162429700 !ruby/object:Gem::Requirement
38
+ requirement: &2154188080 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.0.0
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2162429700
46
+ version_requirements: *2154188080
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rake
49
- requirement: &2162428760 !ruby/object:Gem::Requirement
49
+ requirement: &2154187220 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *2162428760
57
+ version_requirements: *2154187220
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rdoc
60
- requirement: &2162427040 !ruby/object:Gem::Requirement
60
+ requirement: &2154186100 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *2162427040
68
+ version_requirements: *2154186100
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
- requirement: &2162426160 !ruby/object:Gem::Requirement
71
+ requirement: &2154185300 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '2'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *2162426160
79
+ version_requirements: *2154185300
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rr
82
- requirement: &2162425700 !ruby/object:Gem::Requirement
82
+ requirement: &2154184880 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *2162425700
90
+ version_requirements: *2154184880
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: simplecov
93
- requirement: &2162425100 !ruby/object:Gem::Requirement
93
+ requirement: &2154184380 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *2162425100
101
+ version_requirements: *2154184380
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: rack
104
- requirement: &2162424460 !ruby/object:Gem::Requirement
104
+ requirement: &2154183740 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,7 +109,7 @@ dependencies:
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *2162424460
112
+ version_requirements: *2154183740
113
113
  description: Consume a rest API in a AR like fashion
114
114
  email:
115
115
  - axel.tetzlaff@fortytools.com
@@ -125,6 +125,7 @@ files:
125
125
  - arrest.gemspec
126
126
  - lib/arrest.rb
127
127
  - lib/arrest/abstract_resource.rb
128
+ - lib/arrest/attributes/belongs_to.rb
128
129
  - lib/arrest/attributes/converter.rb
129
130
  - lib/arrest/attributes/has_attributes.rb
130
131
  - lib/arrest/exceptions.rb