rails-and-solid 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -1,3 +1,8 @@
1
+ # What is this?
2
+
3
+ This is a gem that changes Rails behavior to allow you to code more freely, without coupling
4
+ yourself to inheritance issues. Take a look at the examples to see what it changes.
5
+
1
6
  # Installing
2
7
 
3
8
  Configure the gem in your Gemfile:
@@ -11,22 +16,194 @@ and make it believe you have the controller he wants, just trick him:
11
16
 
12
17
  class ApplicationController < ActionController::Base
13
18
 
14
- protect_from_forgery
15
- include RailsAndSolid::TrickHim
19
+ solidify
20
+
21
+ end
22
+
23
+ # Inheritance coupling in controllers
24
+
25
+ Ok. Time for some goodies. First example, let's unpimp :
26
+
27
+ [code]
28
+ RailsAndSolid.pimp :clients
29
+
30
+ class ClientsControl
31
+
32
+ def show(id)
33
+ @client = Client.find(id)
34
+ end
35
+
36
+ end
37
+ [/code]
38
+
39
+ Notice that *id* is the parameter *id* from your http request. No inheritance required.
40
+ Same old behavior. No http params appeared. You can unit test for real, without all
41
+ its inherited behavior.
42
+
43
+ Why? Am I really coupled to something when inheriting?
44
+
45
+ [code]
46
+ rails console
47
+ > ActionController::Base.instance_methods.size
48
+ 374
49
+ > (ActionController::Base.instance_methods + ActionController::Base.instance_methods - Object.instance_methods - Object.private_instance_methods).size
50
+ 560
51
+ > ActionController::Base.methods.size
52
+ 353
53
+ > ActionController::Base.ancestors.size
54
+ 36
55
+ [/code]
56
+
57
+ By default, when creating a new controller in Rails, you are coupled
58
+ with 374 public methods (*542 in total*), inheriting behavior from *36 different* sources.
59
+
60
+ # Session parameters
61
+
62
+ [code]
63
+ class ClientsControl
64
+
65
+ def show(current_user, id)
66
+ # if session[:current_user] exists, guess who is here?
67
+ end
68
+
69
+ end
70
+ [/code]
71
+
72
+ Again, unit testable. Non-http intrusive.
73
+
74
+ # Session parameters
75
+
76
+ [code]
77
+ class ClientsControl
78
+
79
+ def show(current_user, id)
80
+ # if session[:current_user] exists, guess who is here?
81
+ end
82
+
83
+ end
84
+ [/code]
85
+
86
+ # What about creating a client?
87
+
88
+ Well, just create it:
89
+
90
+ [code]
91
+ class ClientsControl
16
92
 
93
+ def create(client)
94
+ client.save
17
95
  end
96
+
97
+ end
98
+ [/code]
99
+
100
+ # But you can't load, right?
101
+
102
+ I don't think so:
103
+
104
+ [code]
105
+ class ClientsControl
106
+
107
+ def show(loaded_client)
108
+ @client = loaded_client
109
+ end
110
+
111
+ end
112
+ [/code]
18
113
 
19
- # Using
114
+ # But what about responses? Sessions? Http stuff?
20
115
 
21
- NO INHERITANCE
116
+ Just bind to what you need, nothing more than that:
117
+
118
+ [code]
119
+ def logout(session, redirect_to, flash)
120
+ session[:current_user] = nil
121
+ flash[:message] = "Logged out..."
122
+ redirect_to.root_path
123
+ end
124
+ [/code]
125
+
126
+ # Internally: Helpers
127
+
128
+ Helpers are the classes that help passing parameters to those
129
+ methods by using a key based lookup algorithm. For example
130
+ if a 'json' parameter is received, one will use the Json helper
131
+ to return it:
132
+
133
+ [code]
134
+ class ApplicationController < ActionController::Base
135
+
136
+ protect_from_forgery
137
+ solidify
138
+
139
+ class JsonHelper
140
+ def initialize(controller)
141
+ @controller = controller
142
+ end
143
+ def message(x)
144
+ @controller.render :json => {'message' => x}
145
+ end
146
+ end
22
147
 
23
- GIVE A SIMPLE EXAMPLE
148
+ KEYS["json"] = JsonHelper
149
+
150
+ end
151
+ [/code]
24
152
 
25
- GIVE A LOAD EXAMPLE
153
+ Now you can receive json and use the message:
26
154
 
27
- GIVE AN AMAZING EXAMPLE
155
+ [code]
156
+ def some_action(json)
157
+ json.message("Well done!")
158
+ end
159
+ [/code]
28
160
 
29
- # Helpers
161
+ You can use those auxiliary objects to compose any kind of behavior (not just rendering)
162
+ by just receiving the expected coupled semantic value instead of inheriting everything.
30
163
 
31
164
  # Handlers
32
165
 
166
+ Handlers are not key-fixed parameter providers. For instance, the param lookup:
167
+
168
+ [code]
169
+ module RailsAndSolid
170
+ module Handler
171
+ class Param
172
+ def extract(controller, name)
173
+ controller.params[name]
174
+ end
175
+ def handles?(controller, name)
176
+ controller.params[name]
177
+ end
178
+ end
179
+ end
180
+ end[/code]
181
+
182
+ It will be asked whether it can handle this parameter and the provide it.
183
+
184
+ # TODO List
185
+
186
+ Help?
187
+
188
+ First, simple unit tests.
189
+
190
+ Units are split and behavior is composed. This was only to
191
+ show that its possible to achieve the same (and better results) with less coupling and a different
192
+ OO design approach. So what about start unit testing, providing new handlers, new helpers or
193
+ just doing a blog post on it? Refactoring trick_him would also be nice. Removing the
194
+ pimp method would be even better but that requires more refactoring on Rails internals,
195
+ not just tricking it.
196
+
197
+ Results from handlers "handles?" could be cached.
198
+
199
+ You can also implement DI support by correctly implementing di_instantiate(type) at TrickHim.
200
+
201
+ Finally, feel you can support named parameters in 1.8.7+ if not yet supported.
202
+
203
+ Everything is quite simple so far as this is just a concept
204
+
205
+ # Why not changing Rails internally?
206
+
207
+ One needs to know how all the mixin of Rails interact with each other (i.e. the 36 ancestors
208
+ of ActionController) in order to make safe changes. That is the coupling this proof of concept
209
+ is trying show how to avoid.
@@ -4,4 +4,15 @@ module RailsAndSolid
4
4
  autoload :TrickHim, 'rails-and-solid/trick_him'
5
5
  autoload :Handler, 'rails-and-solid/handler'
6
6
 
7
+ # Shortcut to hack rails.
8
+ def self.pimp(what)
9
+ Object.module_eval "class #{what.to_s.camelize}Controller < ApplicationController; end"
10
+ end
11
+
12
+ end
13
+
14
+ class ActionController::Base
15
+ def self.solidify
16
+ include RailsAndSolid::TrickHim
17
+ end
7
18
  end
@@ -1,9 +1,9 @@
1
1
  module RailsAndSolid
2
2
  module Handler
3
3
  class Instantiate
4
- def extract(controller, var)
5
- val = var.camelize.constantize.new(controller.params[p])
6
- controller.send :instance_variable_set ,"@#{var}", val
4
+ def extract(controller, name)
5
+ val = name.camelize.constantize.new(controller.params[p])
6
+ controller.send :instance_variable_set ,"@#{name}", val
7
7
  return val
8
8
  end
9
9
  def handles?(controller, name)
@@ -1,3 +1,3 @@
1
1
  module RailsAndSolid
2
- VERSION = "0.9.0"
2
+ VERSION = "0.9.1"
3
3
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 9
8
- - 0
9
- version: 0.9.0
8
+ - 1
9
+ version: 0.9.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Guilherme Silveira
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-03-08 00:00:00 -03:00
17
+ date: 2011-03-18 00:00:00 -03:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency