restpack-resource 0.0.8 → 0.0.9

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.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- restpack-resource (0.0.8)
4
+ restpack-resource (0.0.9)
5
5
  activesupport (~> 3.2.11)
6
6
  dm-pager (~> 1.1.0)
7
7
 
@@ -13,6 +13,7 @@ module RestPack
13
13
  self.resource_filterable_by += columns
14
14
  end
15
15
  def resource_validate_filters!(filters)
16
+ return unless filters
16
17
  filters.keys.each do |filter|
17
18
  raise InvalidFilter.new unless self.resource_filterable_by.include?(filter)
18
19
  end
@@ -14,7 +14,7 @@ module RestPack
14
14
  end
15
15
  def resource_validate_includes!(includes)
16
16
  includes.each do |include|
17
- unless self.resource_includable_associations.include?(include)
17
+ unless self.resource_includable_associations.include?(include.to_sym)
18
18
  raise InvalidInclude, "#{self.name}.#{include} is not an includable relation"
19
19
  end
20
20
  end
@@ -119,7 +119,7 @@ module RestPack
119
119
  def resource_validate_options!(options)
120
120
  self.resource_validate_includes! options[:includes]
121
121
  self.resource_validate_filters! options[:filters]
122
- self.resource_validate_sort_by! options[:sort_by]
122
+ self.resource_validate_sort_by! options[:sort_by]
123
123
  end
124
124
  end
125
125
  end
@@ -1,5 +1,6 @@
1
1
  module RestPack
2
2
  module Resource
3
+ #NOTE: GJ: this need a great big refactor
3
4
  module Single
4
5
  def single_resource(params = {}, overrides = {})
5
6
  options = build_single_options(params, overrides)
@@ -11,7 +12,49 @@ module RestPack
11
12
  def get_single_resource(options)
12
13
  model = self.get(options[:id])
13
14
 
14
- model_as_resource(model)
15
+ raise "404" unless model #TODO: GJ: decide on error handling / status
16
+ resource = model_as_resource(model)
17
+
18
+ options[:includes].each do |association|
19
+ add_single_side_loads(resource, model, association)
20
+ end
21
+
22
+ resource
23
+ end
24
+
25
+ def add_single_side_loads(resource, model, association)
26
+ target_model_name = association.to_s.singularize.capitalize
27
+
28
+ relationships = self.relationships.select {|r| r.target_model.to_s == target_model_name }
29
+ raise InvalidInclude if relationships.empty?
30
+
31
+ side_loaded_entities = []
32
+
33
+ relationships.each do |relationship|
34
+ if relationship.is_a? DataMapper::Associations::ManyToOne::Relationship
35
+ relation = model.send(relationship.name.to_sym)
36
+
37
+ side_loaded_entities << (relation ? model_as_resource(relation) : nil)
38
+ elsif relationship.is_a? DataMapper::Associations::OneToMany::Relationship
39
+ parent_key_name = relationship.parent_key.first.name
40
+ child_key_name = relationship.child_key.first.name
41
+ foreign_key = model.send(parent_key_name)
42
+
43
+ #TODO: GJ: configurable side-load page size
44
+ children = relationship.child_model.all(child_key_name.to_sym => foreign_key).page({ per_page: 100 })
45
+ side_loaded_entities += children.map { |c| model_as_resource(c) }
46
+
47
+ count_key = "#{relationship.child_model_name.downcase}_count".to_sym
48
+ resource[count_key] = children.pager.total
49
+ else
50
+ raise InvalidInclude, "#{self.name}.#{relationship.name} can't be included when paging #{self.name.pluralize.downcase}"
51
+ end
52
+ end
53
+
54
+ side_loaded_entities.uniq!
55
+ side_loaded_entities.compact!
56
+
57
+ resource[association] = side_loaded_entities
15
58
  end
16
59
 
17
60
  def build_single_options(params, overrides)
@@ -23,13 +66,12 @@ module RestPack
23
66
  options.reverse_merge!( #defaults
24
67
  :includes => []
25
68
  )
26
-
69
+
27
70
  raise InvalidArguments, "id must be specified" unless params[:id]
28
71
 
29
- resource_validate_includes! options[:includes]
30
-
72
+ resource_normalise_options!(options)
73
+ resource_validate_options!(options)
31
74
  #TODO: GJ: other validations
32
-
33
75
  options
34
76
  end
35
77
  end
@@ -1,5 +1,5 @@
1
1
  module RestPack
2
2
  module Resource
3
- VERSION = "0.0.8"
3
+ VERSION = "0.0.9"
4
4
  end
5
5
  end
@@ -12,11 +12,37 @@ describe RestPack::Resource do
12
12
  end.to raise_error(RestPack::Resource::InvalidArguments, "id must be specified")
13
13
  end
14
14
 
15
+ pending "handles unfound ids"
16
+
15
17
  it "return correct model #as_resource" do
16
18
  result = Song.single_resource({ :id => @song.id })
17
19
  result[:id].should == @song.id
18
20
  result[:url].should == "/api/v1/songs/#{@song.id}"
19
21
  end
22
+
23
+ it "sideloads ManyToOne" do
24
+ result = Song.single_resource(:id => @song.id, :includes => 'artists')
25
+ result[:id].should == @song.id
26
+
27
+ result[:artists].should_not == nil
28
+ result[:artists].count.should == 1
29
+ result[:artists][0][:url].should == "/api/v1/artists/#{@song.artist.id}"
30
+ end
31
+
32
+ describe "OneToMany" do
33
+ before(:each) do
34
+ @artist = create(:artist)
35
+ 3.times { create(:song, :artist => @artist) }
36
+ end
37
+
38
+ it "sideloads OneToMany relations" do
39
+ result = Artist.single_resource(:id => @artist.id, :includes => 'songs')
40
+ result[:id].should == @artist.id
41
+
42
+ result[:songs].should_not == nil
43
+ result[:songs].count.should == 3
44
+ end
45
+ end
20
46
 
21
47
  end
22
48
  end
data/spec/spec_helper.rb CHANGED
@@ -33,6 +33,14 @@ class Artist
33
33
 
34
34
  resource_can_include :songs
35
35
  resource_can_sort_by :id, :name
36
+
37
+ def as_resource
38
+ {
39
+ id: id,
40
+ name: name,
41
+ url: "/api/v1/artists/#{id}"
42
+ }
43
+ end
36
44
  end
37
45
 
38
46
  class Song
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: restpack-resource
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -104,7 +104,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
104
104
  version: '0'
105
105
  segments:
106
106
  - 0
107
- hash: 840564972735635958
107
+ hash: 1427584335195097292
108
108
  required_rubygems_version: !ruby/object:Gem::Requirement
109
109
  none: false
110
110
  requirements:
@@ -113,7 +113,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
113
  version: '0'
114
114
  segments:
115
115
  - 0
116
- hash: 840564972735635958
116
+ hash: 1427584335195097292
117
117
  requirements: []
118
118
  rubyforge_project:
119
119
  rubygems_version: 1.8.25