jskit_rails 2.0.1 → 3.0.0
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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c91237c5bcdcaf3e07c63d3ea1d8fdf695f3d8cc
|
4
|
+
data.tar.gz: a97db69c109e60868568b1c96f700f1ceddbe860
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd161b20e817067d9aba06c9237685fe769eb525b6f1291435e1cfbce738cb7f4619fa8d2356ee8de88d1db6af713e4cf50838f57669103db1c4d87c8152717e
|
7
|
+
data.tar.gz: 0db0caed9c124a807fb1409987c6cc03f342d6f53cea306a0fe7100fb2c1cecc3a48ae4846594639a3e05164dd3c5655722090568a2cd955a2c14ac2c7625b61
|
data/README.md
CHANGED
@@ -18,6 +18,9 @@ Bundle it up:
|
|
18
18
|
bundle install
|
19
19
|
```
|
20
20
|
|
21
|
+
Usage
|
22
|
+
-----
|
23
|
+
|
21
24
|
Add the `jskit` helper to your layout (i.e. `app/views/layouts/application.html.erb`):
|
22
25
|
|
23
26
|
```html
|
@@ -30,26 +33,169 @@ Add the jskit javascript (i.e. `app/assets/javascripts/application.js`):
|
|
30
33
|
//= require jskit_rails
|
31
34
|
```
|
32
35
|
|
33
|
-
That's it, now all controller actions will be triggered on the `JSKit` dispatcher.
|
36
|
+
That's it, now all controller actions will be triggered on the `JSKit` dispatcher.
|
37
|
+
|
38
|
+
### Controllers
|
39
|
+
|
40
|
+
JSKit offers controllers as a basic building block for JavaScript functionality. Making a folder inside `app/assets/javascripts` named `controllers` is a great place to put these:
|
41
|
+
|
42
|
+
```sh
|
43
|
+
mkdir app/assets/javascripts/controllers
|
44
|
+
```
|
45
|
+
|
46
|
+
Now simply require that entire directory in your `application.js` file:
|
34
47
|
|
35
48
|
```js
|
49
|
+
//= require_tree ./controllers
|
50
|
+
```
|
51
|
+
|
52
|
+
#### Events
|
53
|
+
|
54
|
+
There are three events triggered on every page rendered: an application controller global event, a controller global event and a controller action event. Given a `Posts` controller, when rendering the `index` action, you will notice the three events triggered where the `<%= jskit %>` snippet was placed:
|
55
|
+
|
56
|
+
```js
|
57
|
+
App.Dispatcher.trigger("controller:application:all");
|
58
|
+
App.Dispatcher.trigger("controller:pages:all");
|
36
59
|
App.Dispatcher.trigger("controller:pages:index");
|
37
60
|
```
|
38
61
|
|
39
|
-
|
62
|
+
This allows you to integrate your JavaScript at key points in your rails application with minimal coupling. An event triggered with no corresponding `JSKit` controller or action defined has no effect.
|
63
|
+
|
64
|
+
#### Application Controller
|
65
|
+
|
66
|
+
It's common to have some JavaScript that runs on every page of your application. In the past, you may have slapped random bits of code inside a jQuery `$(document).ready` block but not with JSKit. JSKit makes an explicit yet minimally coupled connection between your Rails app and your client-side code. To define application-wide behavior, define an application controller in `app/assets/controller/application_controller.js`:
|
67
|
+
|
68
|
+
```js
|
69
|
+
App.createController("Application", {
|
70
|
+
all: function() {
|
71
|
+
// This handler will be triggered on all pages
|
72
|
+
}
|
73
|
+
});
|
74
|
+
```
|
75
|
+
|
76
|
+
The `all` method is automatically wired to the `controller:application:all` event, which is automatically triggered on each page via the `<%= jskit %>` snippet. You now have a simple, testable controller to define behavior in your application.
|
77
|
+
|
78
|
+
All other controllers are defined in the same way, the only difference is that your other controllers will have actions defined. Assuming you have a `Posts` controller in ruby, whose index action needs a bit of JavaScript to spice up the template. You would simply create a corresponding `Posts` controller in `app/assets/javascripts/posts_controller.js`:
|
79
|
+
|
80
|
+
```js
|
81
|
+
App.createController("Posts", {
|
82
|
+
actions: ["index"],
|
83
|
+
|
84
|
+
index: function() {
|
85
|
+
// do stuff on the index page
|
86
|
+
}
|
87
|
+
});
|
88
|
+
```
|
89
|
+
|
90
|
+
Here you can see that the `actions` array tells JSKit to wire up the `index` method to the `controller:posts:index` event. This event is automatically fired by the `<%= jskit %>` snippet.
|
91
|
+
|
92
|
+
#### Mapped Events
|
93
|
+
|
94
|
+
Sometimes you may want to map and action to a method with a different name, or you may want to map multiple actions to the same method. This is accomplished using mapped actions. Instead of using a string in the actions array, use an object to map the action name to the controller's method:
|
95
|
+
|
96
|
+
```js
|
97
|
+
App.createController("Posts", {
|
98
|
+
actions: [
|
99
|
+
"index",
|
100
|
+
{ new: "setupForm" },
|
101
|
+
{ edit: "setupForm" },
|
102
|
+
{ create: "setupForm" }
|
103
|
+
],
|
104
|
+
|
105
|
+
index: function() {
|
106
|
+
// do stuff on the index page
|
107
|
+
},
|
108
|
+
|
109
|
+
setupForm: function() {
|
110
|
+
// setup the posts form
|
111
|
+
}
|
112
|
+
});
|
113
|
+
```
|
114
|
+
|
115
|
+
Here you can see that the `new`, `edit`, and `create` actions are all being wired up to the same method `setupForm`. This allows you to reuse common behavior that is needed accross multiple actions.
|
116
|
+
|
117
|
+
Finally, you may wish to have some functionality that runs on every action of a controller, to do this, simply define an all method. The `all` method is automatically wired to the `controller:<controller name>:all` event:
|
118
|
+
|
119
|
+
```js
|
120
|
+
App.createController("Posts", {
|
121
|
+
...
|
122
|
+
|
123
|
+
all: function() {
|
124
|
+
// do something on every action of the controller
|
125
|
+
},
|
126
|
+
|
127
|
+
...
|
128
|
+
});
|
129
|
+
```
|
130
|
+
|
131
|
+
This event structure is a simple and powerful way to coordinate your Rails application with the client-side code.
|
132
|
+
|
133
|
+
### Event Payloads
|
134
|
+
|
135
|
+
In addition to simply triggering events, you may optionally pass data to these events. You can pass arbitrary data to any of the three events triggered on page render. To pass data to the application controller's `all` event:
|
136
|
+
|
40
137
|
|
41
138
|
```rb
|
42
|
-
class
|
43
|
-
|
44
|
-
|
139
|
+
class ApplicationController < ApplicationController
|
140
|
+
before_action :set_jskit_payload
|
141
|
+
|
142
|
+
...
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def set_jskit_payload
|
147
|
+
set_app_payload(current_user)
|
45
148
|
end
|
46
149
|
end
|
47
150
|
```
|
48
151
|
|
49
|
-
|
152
|
+
This will pass the current user object to the `Application` controller. You can set the payload as an array if you wish to pass multiple values:
|
153
|
+
|
154
|
+
```rb
|
155
|
+
class ApplicationController < ApplicationController
|
156
|
+
before_action :set_jskit_payload
|
157
|
+
|
158
|
+
...
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
def set_jskit_payload
|
163
|
+
set_app_payload(current_user, [1, 2, 3], { some: "hash" })
|
164
|
+
end
|
165
|
+
end
|
166
|
+
```
|
167
|
+
|
168
|
+
This will pass each item in the array as an argument to the event handler on the controller. Note that each item will have `to_json` called on it automatically, so there is no need to do it yourself. The above example will produce the following triggered event:
|
50
169
|
|
51
170
|
```js
|
52
|
-
|
171
|
+
...
|
172
|
+
App.Dispatcher.trigger("controller:application:all", { first_name: "John", last_name: "Doe" }, [1, 2, 3], { "some": "hash" });
|
173
|
+
...
|
53
174
|
```
|
54
175
|
|
55
|
-
|
176
|
+
This allows you to share data from your Rails app without explicit knowldge of how your client-side code will consume it. You may also set the controller and action event payloads in the same way:
|
177
|
+
|
178
|
+
```rb
|
179
|
+
class PostsController < ApplicationController
|
180
|
+
before_action :set_jskit_payload
|
181
|
+
|
182
|
+
def index
|
183
|
+
set_action_payload("PostsController#index")
|
184
|
+
end
|
185
|
+
|
186
|
+
private
|
187
|
+
|
188
|
+
def set_jskit_payload
|
189
|
+
set_controller_payload("PostsController")
|
190
|
+
end
|
191
|
+
end
|
192
|
+
```
|
193
|
+
|
194
|
+
This should be everything you need to design and test basic client-side interactions with JSKit. If you'd like to see a working example check out [this repo](https://github.com/daytonn/jskit_rails-example).
|
195
|
+
|
196
|
+
Traceur Compiler
|
197
|
+
----------------
|
198
|
+
|
199
|
+
The [jskit](https://github.com/daytonn/jskit) library is written with JavaScript [ES6 features](https://github.com/google/traceur-compiler/wiki/LanguageFeatures) using the [Traceur compiler](https://github.com/google/traceur-compiler). The [traceur runtime](https://github.com/google/traceur-compiler/wiki/Building-custom-Traceur-runtimes) is included in jskit to provide these features.
|
200
|
+
|
201
|
+
_Note: While the traceur-runtime is included with jskit, if you wish to write your own code with ES6 features, you will need a separate traceur-compiler for use with the asset pipeline. Something like: [sprockets-traceur](https://github.com/gunpowderlabs/sprockets-traceur) or [traceur-rails](https://github.com/aackerman/traceur-rails). You would not need to include the `traceur-runtime` from these tools since it is included in the jskit library itself. All of your es6 scripts would need to be loaded after jskit to take advantage of it's included runtime._
|
@@ -1,68 +1,59 @@
|
|
1
1
|
ApplicationController.class_eval do
|
2
2
|
helper_method :jskit
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
11
|
-
|
12
|
-
def controller_payload=(payload)
|
13
|
-
@@controller_payload = payload_js([*payload])
|
14
|
-
end
|
4
|
+
def jskit(config = { namespace: nil })
|
5
|
+
events = [
|
6
|
+
application_event(config),
|
7
|
+
controller_event(config),
|
8
|
+
action_event(config)
|
9
|
+
].join("\n")
|
15
10
|
|
16
|
-
|
17
|
-
|
18
|
-
end
|
11
|
+
view_context.javascript_tag(events)
|
12
|
+
end
|
19
13
|
|
20
|
-
|
14
|
+
def set_action_payload(*args)
|
15
|
+
@action_payload = payload_js(args)
|
16
|
+
end
|
21
17
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
"Dispatcher",
|
26
|
-
%Q(trigger("#{[event_namespace, "controller", controller_name, action_name].compact.join(":")}"#{JSKit.action_payload});)
|
27
|
-
].join(".")
|
28
|
-
end
|
18
|
+
def set_controller_payload(*args)
|
19
|
+
@controller_payload = payload_js(args)
|
20
|
+
end
|
29
21
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
"Dispatcher",
|
34
|
-
%Q(trigger("#{[event_namespace, "controller", controller_name, "all"].compact.join(":")}"#{JSKit.controller_payload});)
|
35
|
-
].join(".")
|
36
|
-
end
|
22
|
+
def set_app_payload(*args)
|
23
|
+
@app_payload = payload_js(args)
|
24
|
+
end
|
37
25
|
|
26
|
+
private
|
38
27
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
%Q(trigger("#{[event_namespace, "controller", "application", "all"].compact.join(":")}"#{JSKit.app_payload});)
|
44
|
-
].join(".")
|
45
|
-
end
|
28
|
+
def payload_js(payload)
|
29
|
+
comma = ", "
|
30
|
+
comma + payload.map(&:to_json).join(comma)
|
31
|
+
end
|
46
32
|
|
47
|
-
|
48
|
-
|
49
|
-
|
33
|
+
def action_event(config)
|
34
|
+
build_event_trigger(config, controller_name, action_name, @action_payload)
|
35
|
+
end
|
50
36
|
|
51
|
-
|
52
|
-
|
53
|
-
:app_payload=,
|
54
|
-
:controller_payload=,
|
55
|
-
:payload_js,
|
56
|
-
:application_event,
|
57
|
-
:action_event,
|
58
|
-
:controller_event)
|
37
|
+
def controller_event(config)
|
38
|
+
build_event_trigger(config, controller_name, "all", @controller_payload)
|
59
39
|
end
|
60
40
|
|
61
|
-
def
|
62
|
-
|
63
|
-
|
64
|
-
JSKit.action_name = action_name
|
41
|
+
def application_event(config)
|
42
|
+
build_event_trigger(config, "application", "all", @app_payload)
|
43
|
+
end
|
65
44
|
|
66
|
-
|
45
|
+
def build_event_trigger(config, middle_namespace, final_namespace, payload)
|
46
|
+
event = [
|
47
|
+
config[:namespace],
|
48
|
+
"controller",
|
49
|
+
middle_namespace,
|
50
|
+
final_namespace
|
51
|
+
].compact.join(":")
|
52
|
+
|
53
|
+
[
|
54
|
+
JskitRails.configuration.app_namespace,
|
55
|
+
"Dispatcher",
|
56
|
+
%Q(trigger("#{event}"#{payload});)
|
57
|
+
].join(".")
|
67
58
|
end
|
68
59
|
end
|
@@ -1,43 +1,59 @@
|
|
1
1
|
require "rails_helper"
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
it "sets the action_payload to an array of the arguments passed" do
|
6
|
-
ApplicationController::JSKit.action_payload = "foo"
|
7
|
-
expect(ApplicationController::JSKit.action_payload).to eq(', "foo"')
|
8
|
-
ApplicationController::JSKit.action_payload = ["foo", "bar", "baz"]
|
9
|
-
expect(ApplicationController::JSKit.action_payload).to eq(', "foo", "bar", "baz"')
|
10
|
-
end
|
11
|
-
end
|
3
|
+
class OrdersController < ApplicationController
|
4
|
+
end
|
12
5
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
20
|
-
end
|
6
|
+
describe OrdersController, type: :controller do
|
7
|
+
shared_examples "a payload setter" do |payload_type|
|
8
|
+
describe "#set_#{payload_type}_payload" do
|
9
|
+
it "sets the #{payload_type}_payload to an array of the passed arguments" do
|
10
|
+
controller.send("set_#{payload_type}_payload", "foo")
|
11
|
+
expect(assigns("#{payload_type}_payload")).to eq(', "foo"')
|
21
12
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
13
|
+
controller.send("set_#{payload_type}_payload", "foo", "bar", "baz")
|
14
|
+
expect(assigns("#{payload_type}_payload")).to eq(', "foo", "bar", "baz"')
|
15
|
+
|
16
|
+
controller.send("set_#{payload_type}_payload", ["foo", "bar", "baz"])
|
17
|
+
expect(assigns("#{payload_type}_payload")).to eq(', ["foo","bar","baz"]')
|
18
|
+
end
|
28
19
|
end
|
29
20
|
end
|
30
21
|
|
22
|
+
it_behaves_like "a payload setter", :action
|
23
|
+
it_behaves_like "a payload setter", :controller
|
24
|
+
it_behaves_like "a payload setter", :app
|
25
|
+
|
31
26
|
describe "#jskit" do
|
27
|
+
let(:view_context) { controller.view_context }
|
28
|
+
|
29
|
+
before do
|
30
|
+
controller.action_name = "action"
|
31
|
+
end
|
32
|
+
|
32
33
|
it "returns a script tag with the global event and the controller event" do
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
34
|
+
app_event = "App.Dispatcher.trigger(\"controller:application:all\", \"baz\");"
|
35
|
+
controller_event = "App.Dispatcher.trigger(\"controller:orders:all\", \"bar\");"
|
36
|
+
action_event = "App.Dispatcher.trigger(\"controller:orders:action\", \"foo\");"
|
37
|
+
expected_js = view_context.javascript_tag([app_event, controller_event, action_event].join("\n"))
|
38
|
+
|
39
|
+
controller.set_action_payload("foo")
|
40
|
+
controller.set_controller_payload("bar")
|
41
|
+
controller.set_app_payload("baz")
|
42
|
+
|
43
|
+
expect(controller.jskit).to eq(expected_js)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "is exposed as a helper method" do
|
47
|
+
expect(controller.view_context.jskit).to eq(controller.jskit)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "namespaces events based on the config" do
|
51
|
+
app_event = "App.Dispatcher.trigger(\"some_namespace:controller:application:all\");"
|
52
|
+
controller_event = "App.Dispatcher.trigger(\"some_namespace:controller:orders:all\");"
|
53
|
+
action_event = "App.Dispatcher.trigger(\"some_namespace:controller:orders:action\");"
|
54
|
+
expected_js = view_context.javascript_tag([app_event, controller_event, action_event].join("\n"))
|
55
|
+
|
56
|
+
expect(controller.jskit(namespace: "some_namespace")).to eq(expected_js)
|
41
57
|
end
|
42
58
|
end
|
43
59
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jskit_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dayton Nolan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|