lanes 0.0.5 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/Gemfile +0 -1
  4. data/README.md +2 -0
  5. data/client/lanes/data/Bootstrap.coffee +2 -2
  6. data/client/lanes/data/Collection.coffee +4 -0
  7. data/client/lanes/data/Config.coffee +0 -5
  8. data/client/lanes/data/Model.coffee +236 -150
  9. data/client/lanes/data/PubSub.coffee +6 -12
  10. data/client/lanes/data/Sync.coffee +1 -0
  11. data/client/lanes/extension/Extensions.coffee +4 -2
  12. data/client/lanes/lib/MakeBaseClass.coffee +1 -1
  13. data/client/lanes/minimal.js +11 -0
  14. data/client/lanes/minimal.scss.erb +12 -0
  15. data/client/lanes/screens/Base.coffee +1 -2
  16. data/client/lanes/screens/Instance.coffee +52 -0
  17. data/client/lanes/vendor/packaged.js +1 -2
  18. data/client/lanes/views/Base.coffee +12 -10
  19. data/client/lanes/workspace.scss.erb +3 -0
  20. data/client/lanes/workspace/index.js +2 -12
  21. data/docs/command.md +111 -0
  22. data/docs/model.md +188 -0
  23. data/docs/todo-example-part-1.md +71 -0
  24. data/docs/view.md +275 -0
  25. data/{spec/client/jasmine_examples/PlayerSpec.js → docs/welcome.md} +0 -0
  26. data/lanes.gemspec +3 -1
  27. data/lib/lanes/api/helper_methods.rb +8 -0
  28. data/lib/lanes/api/javascript_processor.rb +14 -10
  29. data/lib/lanes/api/pub_sub.rb +7 -7
  30. data/lib/lanes/api/request_wrapper.rb +1 -0
  31. data/lib/lanes/api/root.rb +2 -7
  32. data/lib/lanes/api/sprockets_compressor.rb +6 -2
  33. data/lib/lanes/api/sprockets_extension.rb +25 -9
  34. data/lib/lanes/api/test_specs.rb +13 -9
  35. data/lib/lanes/command.rb +16 -6
  36. data/lib/lanes/command/app.rb +11 -5
  37. data/lib/lanes/command/generate_model.rb +4 -3
  38. data/lib/lanes/command/generate_screen.rb +2 -1
  39. data/lib/lanes/command/generate_view.rb +1 -1
  40. data/lib/lanes/command/named_command.rb +5 -4
  41. data/lib/lanes/command/templates/Gemfile +1 -2
  42. data/lib/lanes/command/templates/client/data/Model.coffee +3 -3
  43. data/lib/lanes/command/templates/client/{namespace-extension.js → index.js} +0 -0
  44. data/lib/lanes/command/templates/client/screens/Screen.coffee +1 -3
  45. data/lib/lanes/command/templates/client/{styles/styles.scss → styles.scss} +0 -0
  46. data/lib/lanes/command/templates/client/views/View.coffee +1 -3
  47. data/lib/lanes/command/templates/config/lanes.rb +1 -1
  48. data/lib/lanes/command/templates/gitignore +1 -0
  49. data/lib/lanes/command/templates/lib/namespace/screen.rb +1 -1
  50. data/lib/lanes/command/templates/public/.gitkeep +0 -0
  51. data/lib/lanes/command/templates/spec/client/Screen.coffee +7 -0
  52. data/lib/lanes/command/templates/spec/client/views/ViewSpec.coffee +2 -2
  53. data/lib/lanes/concerns/all.rb +1 -1
  54. data/lib/lanes/concerns/sanitize_fields.rb +32 -0
  55. data/lib/lanes/concerns/set_attribute_data.rb +4 -4
  56. data/lib/lanes/db.rb +7 -8
  57. data/lib/lanes/extension.rb +37 -3
  58. data/lib/lanes/guard_tasks.rb +2 -2
  59. data/lib/lanes/model.rb +2 -2
  60. data/lib/lanes/screens.rb +1 -0
  61. data/lib/lanes/spec_helper.rb +17 -6
  62. data/{spec → lib/lanes}/testing_models.rb +1 -1
  63. data/lib/lanes/version.rb +1 -1
  64. data/npm-build/compile.coffee +1 -6
  65. data/public/javascripts/jasmine_examples/Player.js +22 -0
  66. data/public/javascripts/jasmine_examples/Song.js +7 -0
  67. data/spec/api/javascript_processor_spec.rb +6 -3
  68. data/spec/concerns/api_path_spec.rb +1 -1
  69. data/spec/concerns/association_extensions_spec.rb +7 -3
  70. data/spec/concerns/attr_accessor_with_default_spec.rb +1 -1
  71. data/spec/concerns/code_identifier_spec.rb +1 -1
  72. data/spec/concerns/export_associations_spec.rb +1 -1
  73. data/spec/concerns/export_methods_spec.rb +1 -14
  74. data/spec/concerns/export_scope_spec.rb +7 -9
  75. data/spec/concerns/exported_limits_spec.rb +1 -1
  76. data/spec/concerns/pub_sub_spec.rb +1 -1
  77. data/spec/concerns/set_attribute_data_spec.rb +16 -24
  78. data/spec/configuration_spec.rb +1 -1
  79. data/spec/helpers/lanes-helpers.coffee +61 -0
  80. data/spec/lanes/data/ModelSpec.coffee +152 -0
  81. data/spec/lanes/data/PubSubSpec.coffee +21 -0
  82. data/spec/{client/view → lanes/views}/BaseSpec.coffee +6 -26
  83. data/spec/numbers_spec.rb +1 -1
  84. data/spec/strings_spec.rb +1 -1
  85. data/views/index.erb +3 -10
  86. data/views/specs.erb +4 -1
  87. metadata +62 -16
  88. data/client/lanes/plugins/trigger.coffee +0 -15
  89. data/client/lanes/workspace/Instance.es6 +0 -64
  90. data/lib/lanes/concerns/sanitize_api_data.rb +0 -15
  91. data/spec/api/user_spec.rb +0 -52
  92. data/spec/fixtures/lanes/users.yml +0 -13
  93. data/spec/locked_fields_spec.rb +0 -27
  94. data/spec/role_collection_spec.rb +0 -19
  95. data/spec/user_role_spec.rb +0 -7
  96. data/spec/user_spec.rb +0 -53
@@ -0,0 +1,71 @@
1
+ ---
2
+ title: TODO MVC Example
3
+ position_after: command
4
+ ---
5
+
6
+ As is required by all new frameworks, this is an example of creating a TODO application using the Lanes framework.
7
+
8
+ First install Lanes via Rubygems. `gem install lanes`
9
+
10
+ As always when using Lanes, the first thing you'll need to do is generate your application. We will name this app simply as `todo`
11
+
12
+ {% highlight bash %}
13
+ lanes new todo
14
+ {% endhighlight %}
15
+
16
+ This will create a new directory with a skeleton Lanes application. Read more about the directories and what their purposes are at {% doc_link command heading:'lanes new' %}.
17
+
18
+ [Our example app at this point](https://github.com/argosity/lanes-todo-demo/tree/2d649b314a826cbbdbf54e3f72041caeeee8e428)
19
+
20
+ # Setup
21
+
22
+ A sample database configuration file is located in `config/database.yml` which will use a postgresql database named todo_dev. For the purposes of this example, we'll just create a new postgresql database that matches the configuration: `createdb todo_dev`
23
+
24
+ Fire up the lanes testing server: `lanes serve`. The test server will start the app and you can view it at: `http://localhost:8888/`. You should see a simple "Todo" message. You can also view the Jasmine specs at `http://localhost:8888/spec`
25
+
26
+ We'll copy the styles from the [TodoMVC template](https://github.com/tastejs/todomvc/tree/master/template).
27
+
28
+ Looking at the Todo app, it has four distinct areas. A `sidebar`, `header`, `footer` and `listing` views. We can create views for them by executing `lanes generate view <name>`, where '< name >' is the view to create. [commit](https://github.com/argosity/lanes-todo-demo/commit/758d0e63359db18ee0291467656454c9fc1c3573)
29
+
30
+ First we take the TodoMVC html template and break it apart into sections and copy them to each view. We're then able to plug each view's reference into the Screen as subviews. [commit](https://github.com/argosity/lanes-todo-demo/commit/8c5178a76f2a8abc0ffadbafb1239f7a8ba113b9)
31
+
32
+ Next we'll create a data model `lanes generate model task title:string{80} completed:boolean` [commit](https://github.com/argosity/lanes-todo-demo/commit/5080c286aa4fb35a2b8372cc86ca4e9e18a18c3f)
33
+
34
+ Since a task should default to being non-completed, we'll edit the migration to default that field to `false` and add a validation to the model [commit](https://github.com/argosity/lanes-todo-demo/commit/e3f7edf9f2863f0669cccac13f7f8e2b88276b5a)
35
+
36
+ Run migration: `lanes db migrate`
37
+
38
+ We'll also create a TaskSummary model that is in charge of summarizing the state of the tasks. It will listen to the tasks collection and perform calculations when events occur. [commit](https://github.com/argosity/lanes-todo-demo/commit/65da191ee749ab749855e06ce69c3bd09662e0d5)
39
+
40
+ # Data and events
41
+
42
+ ## Header View
43
+ It's responsible for interaction with the "What needs to be done?" input. When text is present and the "enter" key is pressed, it should save a record and add it to the collection. We're able to do so in [just a few lines of code](https://github.com/argosity/lanes-todo-demo/blob/master/client/todo/views/Header.coffee#L22-L25)
44
+
45
+ We can easily test that it performs as it should by [adding a few specs](https://github.com/argosity/lanes-todo-demo/blob/master/spec/todo/views/HeaderSpec.coffee#L18-L29).
46
+
47
+ ## Listing View
48
+ This view is a bit more complex. It has a parent view which handles toggling all todo's between being complete and pending, and a collection of subviews that model each individual task. [ListingView](https://github.com/argosity/lanes-todo-demo/blob/master/client/todo/views/Listing.coffee)
49
+
50
+ Each TaskView is responsible for handling it's own editing state and saving value to it's model.
51
+
52
+ ## Footer View
53
+ The only action this view takes is to delete any tasks that are marked as complete when the "Clear Completed" button is clicked. It also displays quite a few values from our TasksSummary. Lane's declarative bindings make these easy to wire up. [FooterView](https://github.com/argosity/lanes-todo-demo/blob/master/client/todo/views/Footer.coffee)
54
+
55
+ You might notice that Lanes makes it super easy to batch update or delete a collection. The footer simply calls destroyAll on the "completed" sub-collection provided by the TaskSummary. Since that sub-collection filters the main collection to only contain "completed" tasks, it's safe to just destroy all the model's in one go. It's so easy in fact that the FooterView demonstrates an alternative use of events. The function is directly given to the "events" property, rather than a method reference. [Save Call](https://github.com/argosity/lanes-todo-demo/blob/master/client/todo/views/Footer.coffee#L27)
56
+
57
+ # Routing
58
+
59
+ For a simple app like the this one, it's easiest to just allow the URL change to trigger what the filtered collection is displaying. We set that up when the screen is initialized. [Routing](https://github.com/argosity/lanes-todo-demo/blob/master/client/todo/Router.coffee)
60
+
61
+ # Deploying
62
+
63
+ For the example we'll host it on Heroku. Other deployments should be similar to deploying a Rails application.
64
+
65
+ Simply commit the source and add a remote per Heroku's instructions: [https://devcenter.heroku.com/articles/git](https://devcenter.heroku.com/articles/git)
66
+
67
+ When you `git push heroku`, Heroku will notice that Lanes uses sprockets and will automatically run `rake assets:precompile`, and then run the application using the puma webserver.
68
+
69
+ On first deploy and when your db schema has changed, you will have to provision and migrate the database on Heroku by running: `heroku run rake db:migrate`
70
+
71
+
data/docs/view.md ADDED
@@ -0,0 +1,275 @@
1
+ ---
2
+ title: View
3
+ heading: Lanes.Data.View
4
+ ---
5
+
6
+ Lanes provides a Lanes.Views.Base class that all other views extend from.
7
+
8
+ In their simplest form, a view simply renders a string into a DOM element. They provide a mediating interface between data and the DOM.
9
+
10
+ Since both Models, Collections, and the DOM emit events, a view's job is to listen to the events and then manipulate the other parties data structures.
11
+
12
+ Lanes' base view provides numerous hooks and helper functions to make the process of responding to events and relaying them easier.
13
+
14
+ Views can also be nested inside other views and will bubble relevant events up to thier parent views.
15
+
16
+ Views inherit from [Ampersand State](http://ampersandjs.com/docs#ampersand-state), and therefore support all the same methods and declarations that it does.
17
+
18
+ <aside>
19
+ Unlike Backbone.js, when the view is rendered the old el (if present)
20
+ is discared and an new one is created at the same point in the DOM.
21
+ This prevents the doubly nested divs issue that Backbone experiences,
22
+ but can be suprising behaviour for those who aren't expecting it.
23
+ </aside>
24
+
25
+ ### API Reference
26
+
27
+ # initialize
28
+
29
+ `new View({options})`
30
+
31
+ Called by the constructor after the view is initialized. initialize can be used by your views for performing initialization of the class.
32
+
33
+ Views have several options that will be copied to the view if they are given to initialize. Those options and their types are el (element), model (state), collection (collection), pubSub (boolean), parent (object), subviewId (string).
34
+
35
+ ``` coffee
36
+
37
+ class MyView extends Lanes.Views.Base
38
+
39
+ initialize: (options)->
40
+ this.magic = options.answer
41
+
42
+ view = new MyView( answer: 42 )
43
+ # view.magic => 42
44
+
45
+ ```
46
+
47
+ # source
48
+
49
+ The "source" property is a way for Lanes to detect where the view was loaded from. When Lanes sets up a new class it sets it to the "magic" FILE variable. Lanes Coffeescript pre-processor will set the FILE to the proper values for each file. The Base View uses the information contained in source to auto-load views and models from the correct location.
50
+
51
+ # el
52
+
53
+ A reference to a DOM element that is controlled by the view.
54
+
55
+ All views have a single DOM element. If a view does is not provided an el when it's created, it will construct one when the render method is called.
56
+
57
+ # template
58
+
59
+ Either an string or a function that returns a string. The string can be either a path to a pre-compiled template, or a HTML string.
60
+
61
+
62
+ ``` coffee
63
+ class MyView extends Lanes.Views.Base
64
+ template: "<div><p>Hello World</p></div>"
65
+
66
+ view = new MyView
67
+ view.render()
68
+
69
+ # view.el.innerHTML => <div><p>Hello World</p></div>
70
+ ```
71
+
72
+
73
+
74
+ ``` coffee
75
+ class MyView extends Lanes.Views.Base
76
+ template: "views/myview"
77
+
78
+ view = new MyView
79
+ # attempt to render a template from path "views/myview"
80
+ view.render()
81
+ ```
82
+
83
+
84
+ ``` coffee
85
+ # Contained in file MyView.coffee
86
+
87
+ class MyApp.Views.MyView extends Lanes.Views.Base
88
+ source: FILE
89
+
90
+ view = new MyView
91
+ # will use the "source" information to render
92
+ # a template from "myapp/views/my_view"
93
+ view.render()
94
+ ```
95
+
96
+ # templateName
97
+
98
+ A string (or function that returns one) that contains the name of a template. The template will be loaded from the same path but using the templateName instead of one with the same name as the file.
99
+
100
+ ``` coffee
101
+ class MyApp.Views.MyView extends Lanes.Views.Base
102
+ source: FILE
103
+ templateName: "contents"
104
+
105
+ view = new MyView
106
+ # will use the "source" information to render
107
+ # a template from "myapp/views/contents"
108
+ view.render()
109
+ ```
110
+
111
+ # subviews
112
+
113
+ Subviews are View classes that should be rendered at a given point on the DOM once conditions are met.
114
+
115
+ In order for a subview to render, the parent's el must have a valid reference to the DOM element to render the subview into, as well as all data for the subview being present.
116
+
117
+ When Subviews are created they are passed the parent view and any other options that were specified.
118
+
119
+ Definitions for subviews apre specified using:
120
+
121
+ * A "view" or "component" key, given either as a class or a string that contains the keypath to the object.
122
+ * Either a "container" or "hook" reference. If one is not given, it will default to a hook with the same name as the subview reference. For instace the "heading" subview below will default to `data-hook="heading"`
123
+ * A model or collection reference. If a collection reference is given, the collection will render using a collectionView.
124
+ * Options. Either a object, a function, or a reference to a class method to call.
125
+
126
+
127
+ ``` coffee
128
+ class MyApp.Views.MyView extends Lanes.Views.Base
129
+ subviews:
130
+ heading:
131
+ view: MyApp.WeirdNamespace.Heading
132
+ model: 'model.person'
133
+ options: {uppercase: true}
134
+ grid:
135
+ component: "Grid"
136
+ container: 'div.grid'
137
+ options: 'gridOptions'
138
+ names:
139
+ view: "NamesItem"
140
+ container: "div.names"
141
+ collection: 'collection'
142
+ gridOptions: -> { count: this.count() }
143
+ template: "<div>
144
+ <div data-hook='heading'></div>
145
+ <div data-hook='finder'></div>
146
+ <div class='grid'></div>
147
+ <div class='names'></div>
148
+ </div>"
149
+ ```
150
+
151
+ Notes:
152
+
153
+ * **heading**
154
+ * Is specified as a class object. `MyApp.WeirdNamespace.Heading` must be defined prior to the file being read and should be a "view like" object.
155
+ * It's model will be set to the value from `model.person`, and it will not be rendered until `model.person` is set to a truthy value.
156
+ * When the view is created it will be passed `{uppercase: true}` as it's options.
157
+ * No `selector` or `hook` was provided. It will default to rendering to `data-hook="heading"`
158
+ * **grid**
159
+ * is using a component named "Grid". When the subview is ready to be created, Lanes will look for a class in the "Components" namespace: `Lanes.Components.Grid`
160
+ * Will render to the "div.grid" element.
161
+ * It's options will be set from the value returned by calling the `gridOptions` method.
162
+ * **names**
163
+ * Since the "view" is given as a simple string, Lanes will search for it in the MyApp namespace, and will expect `MyApp.Views.NamesItem` to be defined
164
+ * A collection is specified. A collectionView will be created and the NamesItem class given as the child view to the collectionView. The collectionView will then handle rendering the collection whenever it has items added/removed.
165
+
166
+
167
+ # subviewOptions(name,def)
168
+
169
+ When subviews are created, they are initialized with an options object containing the parent view, and any other options that are returned by the `subviewOptions` method.
170
+
171
+ The base view's implementation simply returns any options that were given on the subview's definition.
172
+
173
+ Other views may override this method as a convienct way to specify the same options for all subviews.
174
+
175
+ In the below example, each of the subviews will be initialied with:
176
+ `{ parent: (MyView instance), model: (MyView instance).model, status: "red"}`
177
+
178
+
179
+ ``` coffee
180
+ class MyApp.Views.MyView extends Lanes.Views.Base
181
+ subviews:
182
+ heading:
183
+ view: 'Heading'
184
+ footer:
185
+ view: 'Footer'
186
+ subviewOptions: ->
187
+ {model: @model, status: "red"}
188
+
189
+ ```
190
+
191
+
192
+
193
+ # events
194
+
195
+ Listens for DOM events that occur within the view _(under it's el)_. Events are specified as a
196
+ hash containing "event selector" for the key and either a name of a method or function for the value.
197
+
198
+ If the selector is ommited, the event will be bound to the root element.
199
+
200
+
201
+ ``` coffee
202
+ class MyApp.Views.MyView extends Lanes.Views.Base
203
+ template: "<div><a class='title'>click me!</a></div>"
204
+ events:
205
+ "click .title": "onTitleClick"
206
+ "click": -> console.log("I feel like I was clicked somewhere")
207
+ onTitleClick: ->
208
+ console.log "Title Was Clicked!"
209
+ ```
210
+
211
+ # ui
212
+
213
+ A View will often need to access a given DOM element repeatedly. By specifying a the elements as part of the UI property, they will be cached when the view is rendered for speedy access.
214
+
215
+ Additionally elements cached in the UI can be refered to in bindings as a convience.
216
+
217
+
218
+ ``` coffee
219
+ class MyApp.Views.MyView extends Lanes.Views.Base
220
+ ui:
221
+ title: "a.title"
222
+ template: "<div><a class='title'>click me!</a></div>"
223
+ events:
224
+ "click @ui.title": "onTitleClick"
225
+ onTitleClick: ->
226
+ console.log "Title Was Clicked!"
227
+ performOperation: ->
228
+ this.ui.title.hide()
229
+ runOperation()
230
+ this.ui.title.show()
231
+ ```
232
+
233
+ ### _Note:_ UI elements are not accessible until the view is rendered.
234
+
235
+ # query(selector)
236
+
237
+ Returns a single element based on CSS selector scoped to this.el
238
+ if you pass an empty string it return `this.el`.
239
+
240
+ Is more efficient that using the `$` method which calls out to jQuery
241
+
242
+ ``` coffee
243
+ class MyView extends Lanes.Views.Base
244
+ template: "<div><a class='title'>click me!</a></div>"
245
+
246
+ view = new MyView
247
+ view.render()
248
+ # get the first element the class "title"
249
+ view.query('.title').click()
250
+ ```
251
+
252
+ # $(selector)
253
+
254
+ The same as `query`, but uses jQuery to find the selection, and may return more than just one
255
+ element. Is essentially just a shortcut to running $el.find. It runs queries scoped within the view's element.
256
+
257
+ ``` coffee
258
+ class MyView extends Lanes.Views.Base
259
+ template: "<div><a class='title'>click me!</a></div>"
260
+
261
+ view = new MyView
262
+ view.render()
263
+ # get the first element the class "title"
264
+ view.$('.title').click()
265
+ ```
266
+
267
+ # parentScreen()
268
+
269
+ Walks up the parent chain, attempting to find a screen. If it's found once is returned, otherwise returns null.
270
+
271
+ It's sometimes useful to relay events up to a level where the user can make note of them. This method provides a way to obtain a reference to the owning screen.
272
+
273
+ # remove()
274
+
275
+ Recursively calls remove() on all subviews, than removes itself form the DOM and unbinds all event listeners.
data/lanes.gemspec CHANGED
@@ -41,13 +41,15 @@ Gem::Specification.new do |spec|
41
41
  spec.add_dependency "hashie", "~> 3.3"
42
42
  spec.add_dependency "rack-test", "~> 0.6"
43
43
  spec.add_dependency "minitest-around", "~> 0.2"
44
+ spec.add_dependency "mocha", "~> 1.1"
44
45
  spec.add_dependency "guard-minitest", "~> 2.3"
45
46
  spec.add_dependency "yui-compressor", "~> 0.12"
47
+ spec.add_dependency "closure-compiler", "~> 1.1"
46
48
  spec.add_dependency "guard-jasmine", "~> 2.0"
47
49
  spec.add_dependency "rake", "~> 10.0"
48
50
  spec.add_dependency "jasmine-core", "~> 2.0"
49
51
  spec.add_dependency "require_all", "~> 1.3"
50
-
52
+ spec.add_dependency "sanitize", "~> 3.0"
51
53
  spec.add_development_dependency "bundler", "~> 1.5"
52
54
  spec.add_development_dependency "growl", "~> 1.0"
53
55
  spec.add_development_dependency "pry-byebug", "~> 2.0"
@@ -3,6 +3,14 @@ module Lanes
3
3
 
4
4
  module HelperMethods
5
5
 
6
+ def lanes_javascript_tag
7
+ javascript_tag( Extensions.require_workspace? ? 'lanes/workspace' : 'lanes/minimal' )
8
+ end
9
+
10
+ def lanes_stylesheet_tag
11
+ stylesheet_tag( Extensions.require_workspace? ? 'lanes/workspace' : 'lanes/minimal' )
12
+ end
13
+
6
14
  def client_bootstrap_data
7
15
  Oj.dump(Extensions.client_bootstrap_data(self), mode: :compat)
8
16
  end
@@ -20,19 +20,23 @@ module Lanes
20
20
  end
21
21
 
22
22
  def wrap_js(scope, js)
23
- ns = namespace(scope)
23
+ dirs = scope.logical_path.split(File::SEPARATOR)
24
+ ns = dirs.many? ? dirs.first.camelize : nil
25
+ file = dirs.last
26
+ # if the file is being loaded under the "lanes" directory
27
+ # it's not an extension
24
28
  if ns && ns != "Lanes"
25
29
  ref = "(window.Lanes ? window.Lanes['#{ns}'] : null)"
26
- "(function(Lanes, #{ns}, NAMESPACE, _, window, undefined) {\n#{js}\n})(window.Lanes, #{ref}, {ref:#{ref},name:'#{ns}'}, window._, window);"
30
+ "(function(Lanes, #{ns}, _, window, FILE, undefined)"\
31
+ "{\n#{js}\n})(window.Lanes,#{ref},window._, window,"\
32
+ "{namespace:#{ref},extension:'#{ns}',file:'#{file}'});"
27
33
  else
28
- "(function(Lanes, NAMESPACE, _, window, undefined) {\n#{js}\n})(window.Lanes, {ref:window.Lanes,name:'Lanes'}, window._, window);"
34
+ "(function(Lanes, _, window, FILE, undefined)"\
35
+ "{\n#{js}\n})(window.Lanes,window._, window,"\
36
+ "{namespace:window.Lanes,extension:'Lanes',file:'#{file}'});"
29
37
  end
30
38
  end
31
39
 
32
- def namespace(scope)
33
- dirs = scope.logical_path.split(File::SEPARATOR)
34
- return dirs.many? ? dirs.first.camelize : nil
35
- end
36
40
  end
37
41
 
38
42
  class CoffeeScriptWrapper < JsAssetCompiler
@@ -41,10 +45,10 @@ module Lanes
41
45
  CONSTRUCTOR = /constructor\s*:/
42
46
  EXTENDING_CLASS = /class\s+([\w|\.]+)\s+extends\s+([\w|\.]+)\s*?\n/
43
47
 
44
- # Coffeescript has two shortcomings with regards to Ampersandjs
48
+ # Coffeescript has two shortcomings with regards to Lanes
45
49
  #
46
- # The first is that it's extends format is incompatible with Ampersandjs,
47
- # Ampersandjs does quite a bit more via it's own .extend methods.
50
+ # The first is that it's extends format is incompatible with AmpersandState,
51
+ # State does quite a bit more via it's own .extend methods.
48
52
  # Accordingly, we substitute our own "extend" call whenever we encounter a coffeescript extends
49
53
  #
50
54
  # The second issue is that if a constructor isn't present, coffeescript with generate it's own
@@ -1,9 +1,3 @@
1
- require "oj"
2
-
3
- require_relative "updates"
4
-
5
- require 'message_bus'
6
-
7
1
  module Lanes
8
2
  module API
9
3
 
@@ -13,7 +7,13 @@ module Lanes
13
7
  MessageBus.publish channel, data #Oj.dump(data, mode: :compat)
14
8
  end
15
9
 
16
- def self.initialize
10
+ def self.initialize(api)
11
+ return unless Extensions.require_pub_sub?
12
+ require "oj"
13
+ require_relative "updates"
14
+ require 'message_bus'
15
+ api.use MessageBus::Rack::Middleware
16
+
17
17
  # Use OJ - it encodes dates properly as ISO 8601
18
18
  # https://github.com/moment/moment/issues/1407
19
19
  Oj.mimic_JSON()