smart_adapters 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +215 -8
  3. data/lib/smart_adapters/version.rb +1 -1
  4. metadata +2 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7ff08aa5ca3d972fa315b5bcb3f9f3b716221cbff7e6c6318fab4bb4529a0448
4
- data.tar.gz: fb1e5e836802441405daac310352ebe31604acac6c96846cb3d076393be8a6c6
3
+ metadata.gz: 6bc9acf4e7970034d8d7686621dd8e3d796db5e2f6a0be6b95019fc4907fd0a1
4
+ data.tar.gz: e072efc3832e85caed186bf930361f742e06635d23018fdd3c8243b80c7d2c75
5
5
  SHA512:
6
- metadata.gz: 4feb3505ba4a7f2ce62da178104f75c7c25cede1d9072dc45c92ab5d64475fa92f531e7b7be9a83f36d22a693b97369870d90fcc505f848ba1f2debf3dd7be39
7
- data.tar.gz: d8226283bb31a841978fcf7ed9e95199573eb35ed08ad958b84f0b54351ab274f99297cb405723f6d0116489e5ad389e53386586f9d12bfac025b188b3e8f198
6
+ metadata.gz: 8a9c3baba90c72167965bf87cf4b277e2c56b64d81b61e1f60ce5fcecb4bfe6c033f7cda52528cfcd343c0730610f4fbcdd568ff6172dc394a0ca976f6c75902
7
+ data.tar.gz: 93101103f2e19c2c72161d7af7042f5748675f8e9f326d9e30792992d3b98f6543d3a14d5920cb74e0fc95d5eb4127759223e986c0d787f5a30be6e82d2acd25
data/README.md CHANGED
@@ -1,10 +1,52 @@
1
- # WIP
2
-
3
1
  # SmartAdapters
4
- Short description and motivation.
5
2
 
6
- ## Usage
7
- How to use my plugin.
3
+ [![Gem Version](https://badge.fury.io/rb/smart_adapters.svg)](https://badge.fury.io/rb/smart_adapters) [![Build Status](https://travis-ci.org/andrearampin/smart_adapters.svg?branch=master)](https://travis-ci.org/andrearampin/smart_adapters) [![Maintainability](https://api.codeclimate.com/v1/badges/9d55d1d054401ab93a6e/maintainability)](https://codeclimate.com/github/andrearampin/smart_adapters/maintainability)
4
+
5
+ Smart Adapters were born from the need to fully decouple the controller logic from the rendering of the response.
6
+ In the [Ruby on Rails documentation](https://apidock.com/rails/ActionController/MimeResponds/InstanceMethods/respond_to), the controller has to decide the format of the answer based on the (Content-Type) request:
7
+
8
+ ```ruby
9
+ # app/controllers/people_controller.rb
10
+ def index
11
+ @people = Person.all
12
+ respond_to do |format|
13
+ format.html
14
+ format.xml { render :xml => @people.to_xml }
15
+ end
16
+ end
17
+ ```
18
+
19
+ Although, this method looks simple it's already highlighting how two distinct formats might have a slightly different implementation. The problem here is that over time this controller might inherit unnecessary complexity by simply introducting new properties or formats.
20
+
21
+ The Smart Adapters solve this problem by delegating the task of properly render the response based on the request format to well-defined classes, one per format. The following implementation makes use of the Smart Adapters:
22
+
23
+ ```ruby
24
+ # app/controllers/people_controller.rb
25
+ def index
26
+ current_adapter.success Person.all
27
+ end
28
+
29
+ # app/models/smart_adapters/people/index/html_adapter.rb
30
+ def success(people)
31
+ render 'people/show', locals: { people: people }
32
+ end
33
+
34
+ # app/models/smart_adapters/people/index/xml_adapter.rb
35
+ def success(people)
36
+ render xml: people, status: :ok
37
+ end
38
+ ```
39
+
40
+ Now that the application has a class per format, it is easy to keep the controller dry while implementing format specific features. For instance, in case of an XML request, the adapter could add more details to the `people` collection or track some metrics without bloating the controller.
41
+
42
+ ```ruby
43
+ # app/models/smart_adapters/people/index/xml_adapter.rb
44
+ def success(people)
45
+ metric_tracker.push('New XML request')
46
+ people.filter_private_details!
47
+ render xml: people, status: :ok
48
+ end
49
+ ```
8
50
 
9
51
  ## Installation
10
52
  Add this line to your application's Gemfile:
@@ -18,7 +60,172 @@ And then execute:
18
60
  $ bundle
19
61
  ```
20
62
 
21
- Or install it yourself as:
22
- ```bash
23
- $ gem install smart_adapters
63
+ Update the `ApplicationController` by adding the `SmartAdapters` concern:
64
+ ```ruby
65
+ class ApplicationController < ActionController::Base
66
+ include SmartAdapters
67
+ end
68
+ ```
69
+
70
+ Add the adapters for your **controller/action/format**.
71
+
72
+ ### Example
73
+
74
+ `app/controlles/users_controller.rb`
75
+ ```ruby
76
+ class UsersController < ApplicationController
77
+ # GET /users
78
+ def index
79
+ current_adapter.success User.all
80
+ end
81
+
82
+ # GET /users/1
83
+ def show
84
+ if user
85
+ current_adapter.success(user)
86
+ else
87
+ current_adapter.failure(user)
88
+ end
89
+ end
90
+
91
+ # PATCH/PUT /users/1
92
+ def update
93
+ if user.update_attributes(update_params)
94
+ current_adapter.success(user)
95
+ else
96
+ current_adapter.failure(user)
97
+ end
98
+ end
99
+
100
+ private
101
+
102
+ def update_params
103
+ params.require(:user).permit(:first_name, :last_name)
104
+ end
105
+
106
+ def user
107
+ @user ||= User.find_by(id: params[:id])
108
+ end
109
+ end
110
+ ```
111
+ `app/models/smart_adapters/users/index/html_adapter.rb`
112
+ ```ruby
113
+ module SmartAdapters
114
+ module Users
115
+ module Index
116
+ class HtmlAdapter < SimpleDelegator
117
+ include SmartAdapters::Util::Adapters::Html::Default
118
+
119
+ def success(resource)
120
+ render 'users/show', locals: { resource: resource }
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ ```
127
+ `app/models/smart_adapters/users/index/json_adapter.rb`
128
+ ```ruby
129
+ module SmartAdapters
130
+ module Users
131
+ module Index
132
+ class JsonAdapter < SimpleDelegator
133
+ include SmartAdapters::Util::Adapters::Json::Default
134
+
135
+ def success(resource)
136
+ render json: resource, status: :ok
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ ```
144
+ `app/models/smart_adapters/users/show/html_adapter.rb`
145
+ ```ruby
146
+ module SmartAdapters
147
+ module Users
148
+ module Show
149
+ class HtmlAdapter < SimpleDelegator
150
+ include SmartAdapters::Util::Adapters::Html::Default
151
+
152
+ def success(resource)
153
+ render 'objects/show', locals: { resource: resource }
154
+ end
155
+
156
+ def failure(resource)
157
+ redirect_back fallback_location: root_path, flash: { error: 'Resource not found' }
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
24
163
  ```
164
+ `app/models/smart_adapters/users/show/json_adapter.rb`
165
+ ```ruby
166
+ module SmartAdapters
167
+ module Users
168
+ module Show
169
+ class JsonAdapter < SimpleDelegator
170
+ include SmartAdapters::Util::Adapters::Json::Default
171
+
172
+ def success(resource)
173
+ render json: resource, status: :ok
174
+ end
175
+
176
+ def failure(resource)
177
+ render json: {}, status: :not_found
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end
183
+ ```
184
+ `app/models/smart_adapters/users/update/html_adapter.rb`
185
+ ```ruby
186
+ module SmartAdapters
187
+ module Users
188
+ module Update
189
+ class HtmlAdapter < SimpleDelegator
190
+ include SmartAdapters::Util::Adapters::Html::Default
191
+
192
+ def success(resource)
193
+ render 'objects/show', locals: { resource: resource }
194
+ end
195
+
196
+ def failure(resource)
197
+ unless resource.present?
198
+ return redirect_back fallback_location: root_path, flash: { error: 'Resource not found' }
199
+ end
200
+ return redirect_back fallback_location: root_path, flash: { error: resource.errors }
201
+ end
202
+ end
203
+ end
204
+ end
205
+ end
206
+ ```
207
+ `app/models/smart_adapters/users/update/json_adapter.rb`
208
+ ```ruby
209
+ module SmartAdapters
210
+ module Users
211
+ module Update
212
+ class JsonAdapter < SimpleDelegator
213
+ include SmartAdapters::Util::Adapters::Json::Default
214
+
215
+ def success(resource)
216
+ render json: resource, status: :ok
217
+ end
218
+
219
+ def failure(resource)
220
+ return render json: {}, status: :not_found unless resource.present?
221
+ render json: { errors: resource.errors }, status: :bad_request
222
+ end
223
+ end
224
+ end
225
+ end
226
+ end
227
+ ```
228
+
229
+ ## TODO
230
+ - Add remaining formats: `:text`, `:ics`, `:csv`, `:yaml`, `:rss`, `:atom`
231
+ - Add generator
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SmartAdapters
4
- VERSION = '0.1.0'
4
+ VERSION = '0.1.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_adapters
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrea Rampin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-10 00:00:00.000000000 Z
11
+ date: 2018-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -38,34 +38,6 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: sqlite3
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: byebug
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
41
  - !ruby/object:Gem::Dependency
70
42
  name: rspec-rails
71
43
  requirement: !ruby/object:Gem::Requirement