restpack_serializer 0.4.27 → 0.4.28

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d11e2c868b50066fc5b49f6b8d29e168faf2b796
4
- data.tar.gz: 00041f1def3a304b8ba4abbcebda28cd509b0f78
3
+ metadata.gz: 349f4fd2ffe9d0c1d9a7ccf4bcf724dd6ef59580
4
+ data.tar.gz: 9884153b0699c9f7fe9ced987b8284561cff48d3
5
5
  SHA512:
6
- metadata.gz: 1594047af58178562a684999fb18b5cb5089f334e741fa78572e6847e93248125fcad82a90f373dfba596264bc0f1023ec7c8dd9d27f91477fa0c454e200b5f3
7
- data.tar.gz: cf12374078885eb07db598c0a1d20c9c767a5e229becde7e9fab503e8851def1a4d2fd43378514b3166c5e50b620ab5c389857c80ae8b19b912125dfde103346
6
+ metadata.gz: b4792303f29da79c3dcf8518df080260d63dcdd89d620ca37b77388f2efdf0b2985d6e0d063624dc0d711c6aeadd6e12497ba0dc42266c2222bd5330bf1b88db
7
+ data.tar.gz: fb129097386e039f39fc6aa4964e97cdd36cf0a2825d53b27181c8d58486f5b9fef78856b76f083a0f9acae98aad29b4add0d5cb97b0c959179f4b900ef91b52
data/README.md CHANGED
@@ -12,6 +12,17 @@ restpack_serializer allows you to quickly provide a set of RESTful endpoints for
12
12
  * [An overview of RestPack](http://www.slideshare.net/gavinjoyce/taming-monolithic-monsters)
13
13
  * [JSON API](http://jsonapi.org/)
14
14
 
15
+ ## Getting Started
16
+
17
+ ### For rails projects:
18
+ After adding the gem `restpack_serializer` to your Gemfile, add this code to `config/initializers/restpack_serializer.rb`:
19
+
20
+ ```ruby
21
+ Dir[Rails.root.join('app/serializers/**/*.rb')].each do |path|
22
+ require path
23
+ end
24
+ ```
25
+
15
26
  ## Serialization
16
27
 
17
28
  Let's say we have an `Album` model:
@@ -1,5 +1,4 @@
1
1
  require 'kaminari'
2
- require 'protected_attributes'
3
2
 
4
3
  require 'restpack_serializer/version'
5
4
  require 'restpack_serializer/configuration'
@@ -7,9 +7,9 @@ module RestPack::Serializer
7
7
  def initialize(serializer, params = {}, scope = nil, context = {})
8
8
  params.symbolize_keys! if params.respond_to?(:symbolize_keys!)
9
9
 
10
- @page = 1
11
- @page_size = RestPack::Serializer.config.page_size
12
- @include = []
10
+ @page = params[:page] ? params[:page].to_i : 1
11
+ @page_size = params[:page_size] ? params[:page_size].to_i : RestPack::Serializer.config.page_size
12
+ @include = params[:include] ? params[:include].split(',').map(&:to_sym) : []
13
13
  @filters = filters_from_params(params, serializer)
14
14
  @sorting = sorting_from_params(params, serializer)
15
15
  @serializer = serializer
@@ -17,19 +17,13 @@ module RestPack::Serializer
17
17
  @scope = scope || model_class.send(:all)
18
18
  @context = context
19
19
  @include_links = true
20
-
21
- @page = params[:page].to_i if params[:page]
22
- @page_size = params[:page_size].to_i if params[:page_size]
23
- @include = params[:include].split(',').map(&:to_sym) if params[:include]
24
20
  end
25
21
 
26
22
  def scope_with_filters
27
23
  scope_filter = {}
24
+
28
25
  @filters.keys.each do |filter|
29
- value = @filters[filter]
30
- if value.is_a?(String)
31
- value = value.split(',')
32
- end
26
+ value = query_to_array(@filters[filter])
33
27
  scope_filter[filter] = value
34
28
  end
35
29
 
@@ -41,7 +35,7 @@ module RestPack::Serializer
41
35
  end
42
36
 
43
37
  def filters_as_url_params
44
- @filters.sort.map {|k,v| "#{k}=#{v.join(',')}" }.join('&')
38
+ @filters.sort.map { |k,v| map_filter_ids(k,v) }.join('&')
45
39
  end
46
40
 
47
41
  def sorting_as_url_params
@@ -73,5 +67,25 @@ module RestPack::Serializer
73
67
  end
74
68
  sorting_parameters
75
69
  end
70
+
71
+ def map_filter_ids(key,value)
72
+ case value
73
+ when Hash
74
+ value.map { |k,v| map_filter_ids(k,v) }
75
+ else
76
+ "#{key}=#{value.join(',')}"
77
+ end
78
+ end
79
+
80
+ def query_to_array(value)
81
+ case value
82
+ when String
83
+ value.split(',')
84
+ when Hash
85
+ value.each { |k, v| value[k] = query_to_array(v) }
86
+ else
87
+ value
88
+ end
89
+ end
76
90
  end
77
91
  end
@@ -71,6 +71,11 @@ module RestPack
71
71
  if foreign_key_value
72
72
  data[:links][association.name.to_sym] = foreign_key_value.to_s
73
73
  end
74
+ elsif association.macro == :has_many && association.options[:through]
75
+ ids = model.send(association.name).pluck(:id).map { |id| id.to_s }
76
+
77
+ data[:links] ||= {}
78
+ data[:links][association.name.to_sym] = ids
74
79
  end
75
80
  end
76
81
  data
@@ -85,10 +85,21 @@ module RestPack::Serializer::SideLoading
85
85
 
86
86
  def side_load_has_many(association, models, serializer)
87
87
  return {} if models.empty?
88
+
89
+ join_table = association.options[:through]
90
+
91
+ filters = if join_table
92
+ { join_table => { association.through_reflection.foreign_key.to_sym => models.map(&:id) } }
93
+ else
94
+ { association.foreign_key.to_sym => models.map(&:id) }
95
+ end
96
+
88
97
  options = RestPack::Serializer::Options.new(serializer.class)
89
- options.filters = { association.foreign_key.to_sym => models.map(&:id) }
98
+ options.scope = options.scope.joins(join_table) if join_table
99
+ options.filters = filters
90
100
  options.include_links = false
91
- return serializer.class.page_with_options(options)
101
+
102
+ serializer.class.page_with_options(options)
92
103
  end
93
104
 
94
105
  def association_from_include(include)
@@ -1,5 +1,5 @@
1
1
  module RestPack
2
2
  module Serializer
3
- VERSION = '0.4.27'
3
+ VERSION = '0.4.28'
4
4
  end
5
5
  end
@@ -19,7 +19,6 @@ Gem::Specification.new do |gem|
19
19
 
20
20
  gem.add_dependency 'activesupport', ['>= 4.0.3', '< 5.0']
21
21
  gem.add_dependency 'activerecord', ['>= 4.0.3', '< 5.0']
22
- gem.add_dependency 'protected_attributes', '~> 1.0.5'
23
22
  gem.add_dependency 'kaminari', '~> 0.15.1'
24
23
 
25
24
  gem.add_development_dependency 'restpack_gem', '~> 0.0.9'
@@ -31,4 +30,5 @@ Gem::Specification.new do |gem|
31
30
  gem.add_development_dependency 'database_cleaner', '~> 1.0.1'
32
31
  gem.add_development_dependency 'rspec'
33
32
  gem.add_development_dependency 'bump'
33
+ gem.add_development_dependency 'protected_attributes', '~> 1.0.5'
34
34
  end
data/spec/fixtures/db.rb CHANGED
@@ -41,6 +41,13 @@ ActiveRecord::Schema.define(:version => 1) do
41
41
  create_table "payments", :force => true do |t|
42
42
  t.integer "amount"
43
43
  t.integer "artist_id"
44
+ t.integer "fan_id"
45
+ t.datetime "created_at"
46
+ t.datetime "updated_at"
47
+ end
48
+
49
+ create_table "fans", :force => true do |t|
50
+ t.string "name"
44
51
  t.datetime "created_at"
45
52
  t.datetime "updated_at"
46
53
  end
@@ -53,6 +60,7 @@ module MyApp
53
60
  has_many :albums
54
61
  has_many :songs
55
62
  has_many :payments
63
+ has_many :fans, :through => :payments
56
64
  end
57
65
 
58
66
  class Album < ActiveRecord::Base
@@ -82,5 +90,12 @@ module MyApp
82
90
  attr_accessible :amount, :artist
83
91
 
84
92
  belongs_to :artist
93
+ belongs_to :fan
94
+ end
95
+
96
+ class Fan < ActiveRecord::Base
97
+ attr_accessible :name
98
+ has_many :payments
99
+ has_many :artists, :through => :albums
85
100
  end
86
101
  end
@@ -27,6 +27,11 @@ module MyApp
27
27
  class ArtistSerializer
28
28
  include RestPack::Serializer
29
29
  attributes :id, :name, :website
30
- can_include :albums, :songs
30
+ can_include :albums, :songs, :fans
31
+ end
32
+
33
+ class FanSerializer
34
+ include RestPack::Serializer
35
+ attributes :id, :name
31
36
  end
32
37
  end
@@ -139,14 +139,30 @@ describe RestPack::Serializer do
139
139
  end
140
140
 
141
141
  context "links" do
142
- let(:serializer) { MyApp::SongSerializer.new }
143
- it "includes 'links' data" do
144
- @album1 = FactoryGirl.create(:album_with_songs, song_count: 11)
145
- json = serializer.as_json(@album1.songs.first)
146
- json[:links].should == {
147
- artist: @album1.artist_id.to_s,
148
- album: @album1.id.to_s
149
- }
142
+ context "'belongs to' associations" do
143
+ let(:serializer) { MyApp::SongSerializer.new }
144
+
145
+ it "includes 'links' data for :belongs_to associations" do
146
+ @album1 = FactoryGirl.create(:album_with_songs, song_count: 11)
147
+ json = serializer.as_json(@album1.songs.first)
148
+ json[:links].should == {
149
+ artist: @album1.artist_id.to_s,
150
+ album: @album1.id.to_s
151
+ }
152
+ end
153
+ end
154
+
155
+ context "'has_many, through' associations" do
156
+ let(:artist_serializer) { MyApp::ArtistSerializer.new }
157
+
158
+ it "includes 'links' data when there are associated records" do
159
+ artist_with_fans = FactoryGirl.create :artist_with_fans
160
+
161
+ json = artist_serializer.as_json(artist_with_fans)
162
+ json[:links].should == {
163
+ fans: artist_with_fans.fans.collect {|obj| obj.id.to_s }
164
+ }
165
+ end
150
166
  end
151
167
  end
152
168
  end
@@ -2,13 +2,14 @@ require 'spec_helper'
2
2
 
3
3
  describe RestPack::Serializer::SideLoading do
4
4
  context "when side-loading" do
5
+ let(:side_loads) { MyApp::ArtistSerializer.side_loads(models, options) }
6
+
5
7
  describe ".has_many" do
6
8
 
7
9
  before(:each) do
8
10
  @artist1 = FactoryGirl.create(:artist_with_albums, album_count: 2)
9
11
  @artist2 = FactoryGirl.create(:artist_with_albums, album_count: 1)
10
12
  end
11
- let(:side_loads) { MyApp::ArtistSerializer.side_loads(models, options) }
12
13
 
13
14
  context "with a single model" do
14
15
  let(:models) { [@artist1] }
@@ -37,7 +38,35 @@ describe RestPack::Serializer::SideLoading do
37
38
  end
38
39
  end
39
40
  end
41
+ end
42
+
43
+ describe '.has_many through' do
44
+ context 'when including :fans' do
45
+ let(:options) { RestPack::Serializer::Options.new(MyApp::ArtistSerializer, { "include" => "fans" }) }
46
+ let(:artist_1) {FactoryGirl.create :artist_with_fans}
47
+ let(:artist_2) {FactoryGirl.create :artist_with_fans}
40
48
 
49
+ context "with a single model" do
50
+ let(:models) {[artist_1]}
51
+
52
+ it 'returns side-loaded fans' do
53
+ side_loads[:fans].count.should == artist_1.fans.count
54
+ side_loads[:meta][:fans][:page].should == 1
55
+ side_loads[:meta][:fans][:count].should == artist_1.fans.count
56
+ end
57
+ end
58
+ context "with a multiple models" do
59
+ let(:models) {[artist_1, artist_2]}
60
+
61
+ it 'returns side-loaded fans' do
62
+ expected_count = artist_1.fans.count + artist_2.fans.count
63
+
64
+ side_loads[:fans].count.should == expected_count
65
+ side_loads[:meta][:fans][:page].should == 1
66
+ side_loads[:meta][:fans][:count].should == expected_count
67
+ end
68
+ end
69
+ end
41
70
  end
42
71
  end
43
72
  end
@@ -14,6 +14,15 @@ FactoryGirl.define do
14
14
  create_list(:album_with_songs, evaluator.album_count, artist: artist)
15
15
  end
16
16
  end
17
+
18
+ factory :artist_with_fans do
19
+ ignore do
20
+ fans_count 3
21
+ end
22
+ after(:create) do |artist, evaluator|
23
+ create_list(:payment, evaluator.fans_count, artist: artist)
24
+ end
25
+ end
17
26
  end
18
27
 
19
28
  factory :album, :class => MyApp::Album do
@@ -41,5 +50,10 @@ FactoryGirl.define do
41
50
  factory :payment, :class => MyApp::Payment do
42
51
  amount 999
43
52
  artist
53
+ fan
54
+ end
55
+
56
+ factory :fan, :class => MyApp::Fan do
57
+ sequence(:name) {|n| "Fan ##{n}"}
44
58
  end
45
59
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: restpack_serializer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.27
4
+ version: 0.4.28
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gavin Joyce
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-12 00:00:00.000000000 Z
11
+ date: 2014-08-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -50,20 +50,6 @@ dependencies:
50
50
  - - "<"
51
51
  - !ruby/object:Gem::Version
52
52
  version: '5.0'
53
- - !ruby/object:Gem::Dependency
54
- name: protected_attributes
55
- requirement: !ruby/object:Gem::Requirement
56
- requirements:
57
- - - "~>"
58
- - !ruby/object:Gem::Version
59
- version: 1.0.5
60
- type: :runtime
61
- prerelease: false
62
- version_requirements: !ruby/object:Gem::Requirement
63
- requirements:
64
- - - "~>"
65
- - !ruby/object:Gem::Version
66
- version: 1.0.5
67
53
  - !ruby/object:Gem::Dependency
68
54
  name: kaminari
69
55
  requirement: !ruby/object:Gem::Requirement
@@ -204,6 +190,20 @@ dependencies:
204
190
  - - ">="
205
191
  - !ruby/object:Gem::Version
206
192
  version: '0'
193
+ - !ruby/object:Gem::Dependency
194
+ name: protected_attributes
195
+ requirement: !ruby/object:Gem::Requirement
196
+ requirements:
197
+ - - "~>"
198
+ - !ruby/object:Gem::Version
199
+ version: 1.0.5
200
+ type: :development
201
+ prerelease: false
202
+ version_requirements: !ruby/object:Gem::Requirement
203
+ requirements:
204
+ - - "~>"
205
+ - !ruby/object:Gem::Version
206
+ version: 1.0.5
207
207
  description: Model serialization, paging, side-loading and filtering
208
208
  email:
209
209
  - gavinjoyce@gmail.com