darwinjs-rails 1.0.1 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +117 -3
- data/app/assets/javascripts/darwin/controller.coffee +4 -1
- data/darwinjs-rails.gemspec +3 -3
- data/doc/introduction.md +1 -1
- data/lib/darwinjs/rails/version.rb +1 -1
- metadata +8 -8
data/README.md
CHANGED
@@ -26,7 +26,11 @@ Or install it yourself as:
|
|
26
26
|
First, as one time configuration, add autoloader in your
|
27
27
|
application.coffee file :
|
28
28
|
|
29
|
-
```
|
29
|
+
```coffee
|
30
|
+
#= require 'darwin'
|
31
|
+
#= require_tree ./views
|
32
|
+
#= require_tree ./controllers
|
33
|
+
|
30
34
|
$(->
|
31
35
|
Darwin.Loader.run()
|
32
36
|
)
|
@@ -69,7 +73,7 @@ A module is composed of two files :
|
|
69
73
|
Here is a typical view :
|
70
74
|
|
71
75
|
```coffee
|
72
|
-
class App.Views.Users.Index extends Darwin.
|
76
|
+
class App.Views.Users.Index extends Darwin.View
|
73
77
|
@options {
|
74
78
|
selectors:
|
75
79
|
show_users: 'a#show_users'
|
@@ -117,7 +121,7 @@ class App.Controllers.Users.Index extends Darwin.Controller
|
|
117
121
|
```
|
118
122
|
|
119
123
|
As you see, a view acts as single point of configuration for selectors.
|
120
|
-
Any change
|
124
|
+
Any change made then reflect to the whole javascript codebase.
|
121
125
|
|
122
126
|
In the same way, controller acts as a single point of configuration
|
123
127
|
for events. You can tell what a module does looking at the first
|
@@ -136,6 +140,116 @@ notice something got wrong.
|
|
136
140
|
|
137
141
|
Ready for more ? See [introduction](doc/introduction.md).
|
138
142
|
|
143
|
+
|
144
|
+
## Philosophy
|
145
|
+
|
146
|
+
If I had to choose a catchphrase for darwin, it probably would be :
|
147
|
+
|
148
|
+
Darwin knows client side isn't server side.
|
149
|
+
|
150
|
+
|
151
|
+
### You don't execute any code
|
152
|
+
|
153
|
+
There is something very cool with server generated pages : if it works for
|
154
|
+
you, it works for everyone. If something goes wrong, you probably receive
|
155
|
+
mail about the exception (you do, right ?). We have all of this for free,
|
156
|
+
because there is a single or a small set of machines doing the work.
|
157
|
+
|
158
|
+
Now, consider who is doing the work with a javascript codebase. It's your
|
159
|
+
visitors. That's really cool : charge on server is lowered and you don't
|
160
|
+
need to wait for the network to do stuff.
|
161
|
+
|
162
|
+
But you have as much execution environments as you have visitors. We could
|
163
|
+
even say you have as much execution environments as you have visits, because
|
164
|
+
you can't expect your visitor to have a stable and coherent environment.
|
165
|
+
What's the state of memory usage of your visitor ? Is his bandwith saturated
|
166
|
+
by multiple parallel downloads ? What extensions his browser is running ?
|
167
|
+
|
168
|
+
And now, the true question : what happens to your page when an error occurs ?
|
169
|
+
|
170
|
+
Links having "#" as href are a plea : if your javascript crashed, they will
|
171
|
+
simply do nothing. Think of what people do when they click a link that does
|
172
|
+
nothing. If you're a developer, you probably will instinctively reload the
|
173
|
+
page. If you're a lambda user, you probably get frustrated, yell "it doesn't
|
174
|
+
work !" and go somewhere else. How do we solve that ?
|
175
|
+
|
176
|
+
Darwin suggest that we do so through progessive enhancement and graceful
|
177
|
+
degradation. Your application should work perfectly without javascript. When
|
178
|
+
javascript runs, it enhances your interface to add all its cool features.
|
179
|
+
If something wrong occurs, interface is reverted back to its initial state,
|
180
|
+
and event callbacks are deactivated, so that feature works again and
|
181
|
+
promises made to user are fullfilled. I call that server side fallback.
|
182
|
+
|
183
|
+
|
184
|
+
### Your js application is an interactive presenter
|
185
|
+
|
186
|
+
On server side, we like to think about our application as a collection of
|
187
|
+
resources. Resources on the lower level are mapped to database tables.
|
188
|
+
Then we have model that abstracts operations on table data. Then we have
|
189
|
+
controllers that map requests on resources. And finally, we have views
|
190
|
+
that handles presenting our UI.
|
191
|
+
|
192
|
+
Should we use this same approach for client side ? In a previous version,
|
193
|
+
darwin did have a Model class. This turned out to be unintuitive and globally
|
194
|
+
useless : most operations on data (computation, translations, etc) are
|
195
|
+
already done by the server side. The model class was only called by
|
196
|
+
controllers to fire requests and then immediately pass data as callback.
|
197
|
+
Well, `$.getJSON` and `$.post` handle that pretty well. And since you conceived
|
198
|
+
your application through progressive enhancement and graceful degration,
|
199
|
+
chances are there's a form somewhere containing all the data and ready to
|
200
|
+
be serialized when lot of "model" data have to be saved.
|
201
|
+
|
202
|
+
But anyway, this does even not makes sense. Your server side app is built
|
203
|
+
around a database. Your client side app is built around html data. It's
|
204
|
+
a presenter that handles user feedback.
|
205
|
+
|
206
|
+
What we really need is a layer that handles DOM manipulation, and a layer
|
207
|
+
that handles interruptions (events and requests). They are the view layer
|
208
|
+
and the controller layer.
|
209
|
+
|
210
|
+
A view handles DOM manipulation. It abstracts selectors so that if anything
|
211
|
+
change in your HTML, you won't have to change it all over your codebase,
|
212
|
+
but just in one place. This acts as a single point of configuration for
|
213
|
+
retrieving DOM elements. In a view, you add all methods that do
|
214
|
+
special DOM manipulation, and especialy the setup (progressive enhancement)
|
215
|
+
and tear down (graceful degradation) code.
|
216
|
+
|
217
|
+
A controller handles events and requests. A configuration method is
|
218
|
+
used at the top of controller with descriptive comment keys, so that
|
219
|
+
you can see at a glance what controller does. Callback names are infered
|
220
|
+
from event descriptions, and they are all deactivated if a crash occurs.
|
221
|
+
|
222
|
+
Thus, view handles the presenter part, and controller handles interactivity.
|
223
|
+
|
224
|
+
|
225
|
+
### You may have several features on a page
|
226
|
+
|
227
|
+
Again, on server side, we love to think of application in terms of resources.
|
228
|
+
But on client side, it's difficult to stick to that pattern : we often
|
229
|
+
use a composition of resources to provide a feature. You may have a list
|
230
|
+
of users who you want to be able to create / edit / update / delete and
|
231
|
+
you can stick to single resource feature. But you may also want to display
|
232
|
+
a list of customer - a special kind of user - and to display for each their
|
233
|
+
last purchases. Now, you also want to do nifty javascript stuff on those
|
234
|
+
purchases, which are an other resource.
|
235
|
+
|
236
|
+
Instead of having a big javascript controller that handles things pretty
|
237
|
+
unrelated, darwin let you decompose a page in features with modules.
|
238
|
+
|
239
|
+
A module is a controller and a view bound to a subset of your html page.
|
240
|
+
The root element acts as a sandbox for your module : controller and view
|
241
|
+
can't access anything outside it. So you can have a module on the whole
|
242
|
+
page if it's a single feature page, or you can sandbox your module to a
|
243
|
+
given part of the DOM and have multiple modules, you can even have a
|
244
|
+
module sandboxed to a part of the DOM which is contained in the root element
|
245
|
+
of an other module. This ensures your modules respect single responsibility
|
246
|
+
principle.
|
247
|
+
|
248
|
+
And of course, modules are able to communicate with each other if needed,
|
249
|
+
through class events : any controller or view can fire and bind events,
|
250
|
+
just like you would do with a DOM element.
|
251
|
+
|
252
|
+
|
139
253
|
## Contributing
|
140
254
|
|
141
255
|
1. Fork it
|
@@ -56,7 +56,10 @@ class Darwin.Controller extends Darwin.Base
|
|
56
56
|
|
57
57
|
$target = $target.parents( sel ).first() unless $target.is( sel )
|
58
58
|
|
59
|
-
|
59
|
+
args = [ $target, event ]
|
60
|
+
args.push arguments[i] for i in [1..(arguments.length - 1)] if arguments.length > 1
|
61
|
+
|
62
|
+
callback( args... )
|
60
63
|
|
61
64
|
definition.stop = true if definition.type == 'click' and ! definition.stop?
|
62
65
|
|
data/darwinjs-rails.gemspec
CHANGED
@@ -18,9 +18,9 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency 'railties', '~>
|
22
|
-
spec.add_dependency 'coffee-rails', '~>
|
23
|
-
spec.add_dependency 'jquery-rails', '~>
|
21
|
+
spec.add_dependency 'railties', '~> 4.0'
|
22
|
+
spec.add_dependency 'coffee-rails', '~> 4.0'
|
23
|
+
spec.add_dependency 'jquery-rails', '~> 3.0'
|
24
24
|
spec.add_development_dependency "bundler", "~> 1.3"
|
25
25
|
spec.add_development_dependency "rake"
|
26
26
|
end
|
data/doc/introduction.md
CHANGED
@@ -46,7 +46,7 @@ controllers/, as controllers depend on views.
|
|
46
46
|
You can easily create a module using the generator provided :
|
47
47
|
|
48
48
|
```
|
49
|
-
$ rails generate
|
49
|
+
$ rails generate darwinjs:assets admin_area/users/index
|
50
50
|
|
51
51
|
create app/assets/javascripts/controllers/admin_area.coffee
|
52
52
|
create app/assets/javascripts/views/admin_area.coffee
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: darwinjs-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: '1.1'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-08-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: railties
|
@@ -18,7 +18,7 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: '
|
21
|
+
version: '4.0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '
|
29
|
+
version: '4.0'
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: coffee-rails
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -34,7 +34,7 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - ~>
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version: '
|
37
|
+
version: '4.0'
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,7 +42,7 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: '
|
45
|
+
version: '4.0'
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: jquery-rails
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - ~>
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: '
|
53
|
+
version: '3.0'
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -58,7 +58,7 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '3.0'
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
63
|
name: bundler
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|