lanes 0.0.8 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/client/lanes/components/ChoicesInput.coffee +1 -1
- data/client/lanes/components/grid/Grid.coffee +4 -4
- data/client/lanes/components/grid/PopOverEditor.coffee +1 -1
- data/client/lanes/components/popover/PopOver.coffee +3 -3
- data/client/lanes/components/record_finder/RecordFinder.coffee +4 -4
- data/client/lanes/components/select_field/SelectField.coffee +1 -1
- data/client/lanes/extension/Base.coffee +1 -1
- data/client/lanes/extension/Extensions.coffee +3 -3
- data/client/lanes/extension/GlAccounts.coffee +2 -2
- data/client/lanes/lib/namespace.coffee +1 -1
- data/client/lanes/minimal.js +1 -1
- data/client/lanes/{data/Model.coffee → models/Base.coffee} +29 -47
- data/client/lanes/models/Bootstrap.coffee +8 -0
- data/client/lanes/{data → models}/ChangeSet.coffee +3 -3
- data/client/lanes/{data → models}/Collection.coffee +20 -40
- data/client/lanes/{data → models}/Config.coffee +2 -2
- data/client/lanes/{data → models}/PubSub.coffee +4 -3
- data/client/lanes/{data → models}/Query.coffee +7 -7
- data/client/lanes/{data → models}/Screens.coffee +12 -12
- data/client/lanes/models/Sync.coffee +86 -0
- data/client/lanes/{data → models}/User.coffee +8 -8
- data/client/lanes/{data → models}/index.js +1 -1
- data/client/lanes/{data → models}/mixins/HasCodeField.coffee +2 -2
- data/client/lanes/screens/Base.coffee +1 -1
- data/client/lanes/screens/ChangeListener.coffee +1 -1
- data/client/lanes/screens/Instance.coffee +3 -3
- data/client/lanes/screens/screen-definitions.js.erb +2 -2
- data/client/lanes/views/Base.coffee +10 -10
- data/client/lanes/views/ModelObserver.coffee +1 -1
- data/client/lanes/views/PubSub.coffee +4 -4
- data/client/lanes/views/Viewport.coffee +1 -1
- data/client/lanes/workspace/ActiveScreensSwitcher.coffee +1 -1
- data/client/lanes/workspace/Pages.coffee +2 -2
- data/client/lanes/workspace/ScreensMenu.coffee +1 -1
- data/lanes.gemspec +2 -1
- data/lib/lanes/command/generate_model.rb +6 -7
- data/lib/lanes/command/named_command.rb +1 -1
- data/lib/lanes/command/templates/client/index.js +1 -1
- data/lib/lanes/command/templates/client/{data → models}/Model.coffee +3 -7
- data/lib/lanes/command/templates/client/views/View.coffee +1 -1
- data/lib/lanes/command/templates/spec/client/models/ModelSpec.coffee +5 -0
- data/lib/lanes/command/update_model.rb +4 -11
- data/lib/lanes/command.rb +4 -3
- data/lib/lanes/version.rb +1 -1
- data/spec/helpers/lanes-helpers.coffee +5 -4
- data/spec/lanes/{data/ModelSpec.coffee → models/BaseSpec.coffee} +23 -11
- data/spec/lanes/{data → models}/PubSubSpec.coffee +6 -6
- data/views/specs.erb +1 -4
- metadata +19 -20
- data/client/lanes/data/Bootstrap.coffee +0 -8
- data/client/lanes/data/Sync.coffee +0 -63
- data/lib/lanes/command/templates/spec/client/data/ModelSpec.coffee +0 -5
- data/lib/lanes/spec_asset_expander.rb +0 -43
@@ -1,4 +1,4 @@
|
|
1
|
-
class ScreenView extends Lanes.
|
1
|
+
class ScreenView extends Lanes.Models.BasicModel
|
2
2
|
|
3
3
|
session:
|
4
4
|
screen: 'object'
|
@@ -18,18 +18,18 @@ class ScreenView extends Lanes.Data.BasicModel
|
|
18
18
|
initialize: (options)->
|
19
19
|
super
|
20
20
|
@screen=options.screen
|
21
|
-
Lanes.
|
21
|
+
Lanes.Models.Screens.displaying.add( this )
|
22
22
|
this.active=true
|
23
23
|
|
24
24
|
renderScreen: ->
|
25
25
|
this.view.render()
|
26
26
|
|
27
27
|
remove: ->
|
28
|
-
Lanes.
|
28
|
+
Lanes.Models.Screens.displaying.remove( this )
|
29
29
|
|
30
30
|
|
31
31
|
|
32
|
-
class ScreenDefinition extends Lanes.
|
32
|
+
class ScreenDefinition extends Lanes.Models.BasicModel
|
33
33
|
|
34
34
|
session:
|
35
35
|
id: 'string'
|
@@ -45,7 +45,7 @@ class ScreenDefinition extends Lanes.Data.BasicModel
|
|
45
45
|
derived:
|
46
46
|
model_type:
|
47
47
|
deps: ['model'], fn: ->
|
48
|
-
Lanes.getPath(this.model,"Lanes.
|
48
|
+
Lanes.getPath(this.model,"Lanes.Models")
|
49
49
|
|
50
50
|
initialize: ->
|
51
51
|
@views = []
|
@@ -95,7 +95,7 @@ class ScreenDefinition extends Lanes.Data.BasicModel
|
|
95
95
|
# Lanes.warn(failures)
|
96
96
|
|
97
97
|
|
98
|
-
class ScreenViewSet extends Lanes.
|
98
|
+
class ScreenViewSet extends Lanes.Models.BasicCollection
|
99
99
|
|
100
100
|
model: ScreenView
|
101
101
|
|
@@ -133,7 +133,7 @@ class ScreenViewSet extends Lanes.Data.BasicCollection
|
|
133
133
|
|
134
134
|
|
135
135
|
|
136
|
-
class ScreenSet extends Lanes.
|
136
|
+
class ScreenSet extends Lanes.Models.BasicCollection
|
137
137
|
|
138
138
|
model: ScreenDefinition
|
139
139
|
|
@@ -145,7 +145,7 @@ class ScreenSet extends Lanes.Data.BasicCollection
|
|
145
145
|
|
146
146
|
|
147
147
|
|
148
|
-
class MenuGroup extends Lanes.
|
148
|
+
class MenuGroup extends Lanes.Models.BasicModel
|
149
149
|
|
150
150
|
session:
|
151
151
|
id: 'string'
|
@@ -155,18 +155,18 @@ class MenuGroup extends Lanes.Data.BasicModel
|
|
155
155
|
active: ['boolean', true, false]
|
156
156
|
|
157
157
|
screens: ->
|
158
|
-
@avail ||= new Lanes.
|
158
|
+
@avail ||= new Lanes.Models.SubCollection( Lanes.Models.Screens.all, {
|
159
159
|
filter: (screen)=>
|
160
160
|
screen.group_id == @id && Lanes.current_user.canRead(screen.model_type)
|
161
161
|
watched: ['group_id']
|
162
162
|
})
|
163
163
|
|
164
|
-
class MenuGroupSet extends Lanes.
|
164
|
+
class MenuGroupSet extends Lanes.Models.BasicCollection
|
165
165
|
constructor: -> super
|
166
166
|
model: MenuGroup
|
167
167
|
|
168
168
|
available: ->
|
169
|
-
@avail ||= new Lanes.
|
169
|
+
@avail ||= new Lanes.Models.SubCollection(this, {
|
170
170
|
filter: (mgs)=>
|
171
171
|
mgs.screens().filter()
|
172
172
|
mgs.screens().length > 0
|
@@ -174,7 +174,7 @@ class MenuGroupSet extends Lanes.Data.BasicCollection
|
|
174
174
|
|
175
175
|
|
176
176
|
|
177
|
-
Lanes.
|
177
|
+
Lanes.Models.Screens = {
|
178
178
|
all: new ScreenSet
|
179
179
|
displaying: new ScreenViewSet([],{ single_active_only: true })
|
180
180
|
groups: new MenuGroupSet
|
@@ -0,0 +1,86 @@
|
|
1
|
+
|
2
|
+
# a simple reimplentation
|
3
|
+
# to use traffic cop
|
4
|
+
methodMap = {
|
5
|
+
'create': 'POST',
|
6
|
+
'update': 'PUT',
|
7
|
+
'patch': 'PATCH',
|
8
|
+
'delete': 'DELETE',
|
9
|
+
'read': 'GET'
|
10
|
+
}
|
11
|
+
|
12
|
+
getValue = (object, prop)->
|
13
|
+
if !(object && object[prop])
|
14
|
+
return null;
|
15
|
+
return if _.isFunction(object[prop]) then object[prop]() else object[prop];
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
paramsMap = {
|
21
|
+
fields : 'f'
|
22
|
+
with : 'w'
|
23
|
+
query : 'q'
|
24
|
+
include : 'i'
|
25
|
+
order : 'o'
|
26
|
+
limit : 'l'
|
27
|
+
start : 's'
|
28
|
+
format : 'df'
|
29
|
+
}
|
30
|
+
|
31
|
+
Lanes.Models.Sync = {
|
32
|
+
urlError: ->
|
33
|
+
throw new Error('A "url" property or function must be specified')
|
34
|
+
|
35
|
+
copyServerReply: (record, reply)->
|
36
|
+
record.errors = reply?.errors
|
37
|
+
record.lastServerMessage = reply?.message
|
38
|
+
{ record: record, reply: reply }
|
39
|
+
|
40
|
+
# Wraps a sync request's error and success functions
|
41
|
+
# Copies any errors onto the model and sets it's data on success
|
42
|
+
wrapRequest: (record, options)->
|
43
|
+
error = options.error
|
44
|
+
success = options.success
|
45
|
+
options.promise = new _.Promise( (resolve,reject)->
|
46
|
+
options.resolvePromise = resolve
|
47
|
+
options.rejectPromise = reject
|
48
|
+
)
|
49
|
+
options.error = (reply, resp, req)->
|
50
|
+
options.rejectPromise( this.copyServerResp(record,resp.responseJSON || {error: resp.responseText}) )
|
51
|
+
error?.apply(options.scope, arguments)
|
52
|
+
|
53
|
+
options.success = (reply,resp,req)->
|
54
|
+
record.setFromServer( reply.data, options ) if reply?.data?
|
55
|
+
options.resolvePromise( Lanes.Models.Sync.copyServerReply(record,reply) )
|
56
|
+
success?.apply(options.scope, arguments)
|
57
|
+
options
|
58
|
+
|
59
|
+
perform: (method, model, options={})->
|
60
|
+
query = {}
|
61
|
+
for key, value of options
|
62
|
+
query[ paramsMap[key] ] = value if paramsMap[key]
|
63
|
+
|
64
|
+
# Default JSON-request options.
|
65
|
+
params = {
|
66
|
+
type: methodMap[method]
|
67
|
+
dataType: "json"
|
68
|
+
data: query
|
69
|
+
}
|
70
|
+
|
71
|
+
# Ensure that we have a URL.
|
72
|
+
params.url = _.result(model, "url") or Lanes.Models.Sync.urlError() unless options.url
|
73
|
+
params.url += '.json'
|
74
|
+
params.headers = {
|
75
|
+
X_CSRF_TOKEN: Lanes.Models.Config.csrf_token
|
76
|
+
}
|
77
|
+
params.contentType = "application/json"
|
78
|
+
if options.data || _.contains(['create','update','patch'], method)
|
79
|
+
params.data = JSON.stringify( options.data || model.dataForSave(options) )
|
80
|
+
delete options.data
|
81
|
+
|
82
|
+
# Make the request, allowing the user to override any Ajax options.
|
83
|
+
xhr = options.xhr = Lanes.$.ajax(_.extend(params, options))
|
84
|
+
model.trigger "request", model, xhr, options
|
85
|
+
xhr
|
86
|
+
}
|
@@ -1,17 +1,17 @@
|
|
1
|
-
unless Lanes.
|
1
|
+
unless Lanes.Models.Roles
|
2
2
|
|
3
|
-
class Lanes.
|
3
|
+
class Lanes.Models.Role extends Lanes.Models.BasicModel
|
4
4
|
props:
|
5
5
|
id: 'string'
|
6
6
|
name: 'string'
|
7
7
|
member: { type: 'boolean', default: false }
|
8
8
|
|
9
|
-
class Lanes.
|
10
|
-
model: Lanes.
|
9
|
+
class Lanes.Models.Roles extends Lanes.Models.BasicCollection
|
10
|
+
model: Lanes.Models.Role
|
11
11
|
|
12
12
|
|
13
|
-
unless Lanes.
|
14
|
-
class Lanes.
|
13
|
+
unless Lanes.Models.User
|
14
|
+
class Lanes.Models.User extends Lanes.Models.Base
|
15
15
|
|
16
16
|
constructor: (attributes,access)->
|
17
17
|
super
|
@@ -24,7 +24,7 @@ unless Lanes.Data.User
|
|
24
24
|
isLoggedIn:
|
25
25
|
fn: -> false
|
26
26
|
allRoles:
|
27
|
-
fn: -> new Lanes.
|
27
|
+
fn: -> new Lanes.Models.Roles
|
28
28
|
|
29
29
|
session:
|
30
30
|
access_data: 'object'
|
@@ -43,4 +43,4 @@ unless Lanes.Data.User
|
|
43
43
|
canDelete: (model) -> true
|
44
44
|
|
45
45
|
unless Lanes.current_user
|
46
|
-
Lanes.current_user = new Lanes.
|
46
|
+
Lanes.current_user = new Lanes.Models.User
|
@@ -1,9 +1,9 @@
|
|
1
|
-
Lanes.
|
1
|
+
Lanes.Models.Mixins.HasCodeField = {
|
2
2
|
|
3
3
|
INVALID: /[^A-Z0-9a-z]/
|
4
4
|
|
5
5
|
included: ->
|
6
|
-
this.prototype.INVALID_CODE_CLanes.RS ||= Lanes.
|
6
|
+
this.prototype.INVALID_CODE_CLanes.RS ||= Lanes.Models.mixins.Lanes.sCodeField.INVALID
|
7
7
|
|
8
8
|
initialize: ->
|
9
9
|
this.on('change:code', this.upcaseCode )
|
@@ -17,7 +17,7 @@ class ScreenBase
|
|
17
17
|
reset: Lanes.emptyFn
|
18
18
|
|
19
19
|
template: ->
|
20
|
-
this.
|
20
|
+
this.FILE.extension.toLowerCase() + "/screens/" + _.underscore( this.FILE.file ) + "/layout";
|
21
21
|
|
22
22
|
render: ->
|
23
23
|
previouslyRendered = this.rendered
|
@@ -11,7 +11,7 @@ Lanes.Screens.ChangeListener = {
|
|
11
11
|
|
12
12
|
derived:
|
13
13
|
changes: deps:[], fn: ->
|
14
|
-
new Lanes.
|
14
|
+
new Lanes.Models.ChangeSetCollection([],{ parent: this })
|
15
15
|
changes_visible: { deps: ['change_count'], fn:-> @change_count > 0 }
|
16
16
|
|
17
17
|
bindings:
|
@@ -6,7 +6,7 @@ class Lanes.Screens.Instance
|
|
6
6
|
|
7
7
|
constructor: (selector, options)->
|
8
8
|
this.viewport = new Lanes.Views.Viewport({ selector: selector, instance: this });
|
9
|
-
Lanes.
|
9
|
+
Lanes.Models.Bootstrap.initialize(options);
|
10
10
|
Lanes.$(document).ready => @boot(options)
|
11
11
|
|
12
12
|
boot: (options)->
|
@@ -25,13 +25,13 @@ class Lanes.Screens.Instance
|
|
25
25
|
title: => @getAttribute('data-tooltip-message')
|
26
26
|
});
|
27
27
|
Lanes.Views.Keys.initialize();
|
28
|
-
Lanes.
|
28
|
+
Lanes.Models.PubSub.initialize() if options.pub_sub;
|
29
29
|
|
30
30
|
view = Lanes.getPath(options.root_view);
|
31
31
|
if view
|
32
32
|
this.displayInitialView(view);
|
33
33
|
else
|
34
|
-
definition=Lanes.
|
34
|
+
definition=Lanes.Models.Screens.all.findWhere({view: options.root_view});
|
35
35
|
if definition
|
36
36
|
definition.getScreen().then( (screen)=>
|
37
37
|
# break out of the promise so an errors during render get thrown properly
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<% Lanes::Screens::Group.each(self) do | spec | %>
|
2
|
-
Lanes.
|
2
|
+
Lanes.Models.Screens.groups.add( <%= spec.to_json %> );
|
3
3
|
<% end %>
|
4
4
|
|
5
5
|
<% Lanes::Screens::Definition.each(self) do | spec | %>
|
6
|
-
Lanes.
|
6
|
+
Lanes.Models.Screens.register( <%= spec.to_json %> );
|
7
7
|
<% end %>
|
@@ -42,7 +42,7 @@ class ViewBase
|
|
42
42
|
rendered:
|
43
43
|
deps: ["el"], fn: -> !!@el
|
44
44
|
|
45
|
-
|
45
|
+
hasModels:
|
46
46
|
deps: ["model"], fn: -> !!@model
|
47
47
|
|
48
48
|
viewport:
|
@@ -147,8 +147,8 @@ class ViewBase
|
|
147
147
|
renderWithTemplate: (templateArg)->
|
148
148
|
template = templateArg || this.resultsFor('template')
|
149
149
|
throw new Error('Template string or function needed.') unless template
|
150
|
-
template_fn = Lanes.Templates.find(template, this.
|
151
|
-
newDom = if template_fn then template_fn( _.result(this,'
|
150
|
+
template_fn = Lanes.Templates.find(template, this.FILE.extension)
|
151
|
+
newDom = if template_fn then template_fn( _.result(this,'templateModels')) else template
|
152
152
|
newDom = Lanes.Vendor.domify(newDom) if _.isString(newDom);
|
153
153
|
parent = this.el && this.el.parentNode;
|
154
154
|
parent.replaceChild(newDom, this.el) if parent
|
@@ -159,18 +159,18 @@ class ViewBase
|
|
159
159
|
this.el = newDom;
|
160
160
|
return this;
|
161
161
|
|
162
|
-
templateName: -> _.underscore( this.
|
162
|
+
templateName: -> _.underscore( this.FILE.file )
|
163
163
|
|
164
164
|
template: ->
|
165
|
-
this.
|
165
|
+
this.FILE.extension.toLowerCase() + "/views/" + _.result(this,'templateName')
|
166
166
|
|
167
|
-
|
167
|
+
FILE: FILE
|
168
168
|
|
169
|
-
|
169
|
+
templateModels: ->
|
170
170
|
{ model: this.model, collection: this.collection }
|
171
171
|
|
172
172
|
renderTemplate:(name,data={})->
|
173
|
-
template = Lanes.Templates.find(name, this.
|
173
|
+
template = Lanes.Templates.find(name, this.FILE.name)
|
174
174
|
if template
|
175
175
|
template(data)
|
176
176
|
else
|
@@ -179,7 +179,7 @@ class ViewBase
|
|
179
179
|
|
180
180
|
renderTemplateMethod: (method)->
|
181
181
|
return null unless name = _.result(this, method)
|
182
|
-
this.renderTemplate(name, _.result(this, "#{method}
|
182
|
+
this.renderTemplate(name, _.result(this, "#{method}Models") || @model)
|
183
183
|
|
184
184
|
|
185
185
|
# Remove this view by taking the element out of the DOM, and removing any
|
@@ -302,7 +302,7 @@ class ViewBase
|
|
302
302
|
Lanes.getPath(subview.component, Lanes.Components)
|
303
303
|
else if subview.view
|
304
304
|
if _.isString(subview.view)
|
305
|
-
Lanes.getPath(subview.view, this.
|
305
|
+
Lanes.getPath(subview.view, this.FILE.namespace['Views'] )
|
306
306
|
else
|
307
307
|
subview.view
|
308
308
|
Lanes.warn( "Unable to obtain view for %o", subview) if ! klass
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Responsible for adding and removing a view's model(s) from
|
1
|
+
# Responsible for adding and removing a view's model(s) from Models.PubSub
|
2
2
|
class Lanes.Views.PubSub extends Lanes.Views.ModelObserver
|
3
3
|
|
4
4
|
model_events:
|
@@ -17,13 +17,13 @@ class Lanes.Views.PubSub extends Lanes.Views.ModelObserver
|
|
17
17
|
this.showUpdate(field) if field = @view.query("[name=#{field}]")
|
18
18
|
|
19
19
|
bindModel: (model)->
|
20
|
-
Lanes.
|
20
|
+
Lanes.Models.PubSub.add(model)
|
21
21
|
super
|
22
22
|
|
23
23
|
unBindModel: (model)->
|
24
|
-
Lanes.
|
24
|
+
Lanes.Models.PubSub.remove(model)
|
25
25
|
super
|
26
26
|
|
27
27
|
teardown: ->
|
28
28
|
super
|
29
|
-
Lanes.
|
29
|
+
Lanes.Models.PubSub.remove(model) if model = this.getModel()
|
@@ -51,7 +51,7 @@ class Lanes.Workspace.ActiveScreenSwitcher extends Lanes.Views.Base
|
|
51
51
|
constructor: ->
|
52
52
|
super
|
53
53
|
_.bindAll(this, 'resetShownControls')
|
54
|
-
@collection = Lanes.
|
54
|
+
@collection = Lanes.Models.Screens.displaying
|
55
55
|
this.listenTo( @collection, "change:active", this.onActiveChange )
|
56
56
|
this.listenTo( this.viewport, "change:width", this.resetShownControls )
|
57
57
|
this.listenTo( Lanes.current_user, "change:isLoggedIn", this.closeScreens)
|
@@ -17,8 +17,8 @@ class Lanes.Workspace.Pages extends Lanes.Views.Base
|
|
17
17
|
screens_menu_container: '.screens-menu-container'
|
18
18
|
|
19
19
|
initialize: (options)->
|
20
|
-
this.listenTo( Lanes.
|
21
|
-
this.listenTo( Lanes.
|
20
|
+
this.listenTo( Lanes.Models.Screens.displaying, "change:active", this.onActiveChange )
|
21
|
+
this.listenTo( Lanes.Models.Screens.displaying, "remove", this.onRemove )
|
22
22
|
this.listenTo( @model,'change:screen_menu_position', this.moveScreensMenu )
|
23
23
|
super
|
24
24
|
|
@@ -71,7 +71,7 @@ class Lanes.Workspace.ScreensMenu extends Lanes.Views.Base
|
|
71
71
|
initialize: ->
|
72
72
|
super
|
73
73
|
this.listenTo(Lanes.current_user, "change:isLoggedIn", this.resetGroups)
|
74
|
-
@groups = Lanes.
|
74
|
+
@groups = Lanes.Models.Screens.groups.available()
|
75
75
|
this
|
76
76
|
|
77
77
|
resetGroups: ->
|
data/lanes.gemspec
CHANGED
@@ -13,7 +13,8 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.summary = %q{Lanes is a framework for easily writing single page web applications}
|
14
14
|
spec.description = %q{Lanes is a framework for writing single page web applications. It's a full stack framework that contains both server and client.}
|
15
15
|
|
16
|
-
spec.homepage = "http://
|
16
|
+
spec.homepage = "http://lanesframework.org/"
|
17
|
+
|
17
18
|
spec.license = "MIT"
|
18
19
|
|
19
20
|
spec.files = `git ls-files`.split($/)
|
@@ -7,8 +7,7 @@ module Lanes
|
|
7
7
|
RESERVED_YAML_KEYWORDS = %w(y yes n no true false on off null)
|
8
8
|
OPTIONS ||= {
|
9
9
|
timestamps: true,
|
10
|
-
parent: "Lanes::Model"
|
11
|
-
client_collection_parent: "Lanes.Data.Collection"
|
10
|
+
parent: "Lanes::Model"
|
12
11
|
}
|
13
12
|
|
14
13
|
class_options OPTIONS
|
@@ -42,10 +41,10 @@ module Lanes
|
|
42
41
|
|
43
42
|
def create_client
|
44
43
|
self.fields.unshift ModelAttribute.parse("id:integer")
|
45
|
-
template "client/
|
46
|
-
"#{client_dir}/
|
47
|
-
template "spec/client/
|
48
|
-
"#{spec_dir}/
|
44
|
+
template "client/models/Model.coffee", \
|
45
|
+
"#{client_dir}/models/#{class_name}.coffee"
|
46
|
+
template "spec/client/models/ModelSpec.coffee", \
|
47
|
+
"#{spec_dir}/models/#{class_name}Spec.coffee"
|
49
48
|
end
|
50
49
|
|
51
50
|
def add_route
|
@@ -86,7 +85,7 @@ module Lanes
|
|
86
85
|
|
87
86
|
def client_parent
|
88
87
|
if options[:parent] == 'Lanes::Model'
|
89
|
-
"Lanes.
|
88
|
+
"Lanes.Models.Base"
|
90
89
|
else
|
91
90
|
"Lanes.#{namespace.camelize}.#{options[:parent]}"
|
92
91
|
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
class <%= namespace.camelize %>.
|
1
|
+
class <%= namespace.camelize %>.Models.<%= class_name %> extends <%= client_parent %>
|
2
2
|
|
3
3
|
api_path: '<%= name.downcase.pluralize.underscore.dasherize %>'
|
4
|
-
|
4
|
+
FILE: FILE
|
5
5
|
|
6
6
|
props:
|
7
7
|
<% fields.each do |field| -%>
|
@@ -15,10 +15,6 @@ class <%= namespace.camelize %>.Data.<%= class_name %> extends <%= client_parent
|
|
15
15
|
|
16
16
|
associations:
|
17
17
|
<% reference_fields.each do |field| -%>
|
18
|
-
<%= sprintf("%-#{max_field_length}s ",field.name) %>: { <%= field.belongs_to? ? 'model' : 'collection' -%>: "
|
18
|
+
<%= sprintf("%-#{max_field_length}s ",field.name) %>: { <%= field.belongs_to? ? 'model' : 'collection' -%>: "<%= namespace.camelize %>.<%= field.name.camelize %>" }
|
19
19
|
<% end -%>
|
20
20
|
<% end -%>
|
21
|
-
|
22
|
-
class <%= namespace.camelize %>.Data.<%= class_name %>Collection extends <%= options[:client_collection_parent] %>
|
23
|
-
|
24
|
-
model: <%= namespace.camelize %>.Data.<%= class_name %>
|
@@ -3,22 +3,15 @@ require_relative 'model_attribute'
|
|
3
3
|
module Lanes
|
4
4
|
module Command
|
5
5
|
|
6
|
-
class UpdateModel <
|
6
|
+
class UpdateModel < NamedCommand
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
argument :name
|
11
|
-
attr_reader :namespace, :class_name, :namespaced_name
|
12
|
-
|
13
|
-
def self.source_root
|
14
|
-
Pathname.new(__FILE__).dirname.join("templates")
|
15
|
-
end
|
8
|
+
attr_reader :namespaced_name
|
16
9
|
|
17
10
|
def read_class
|
18
11
|
if name=~/::/
|
19
12
|
(@namespace,@name) = name.split("::")
|
20
13
|
else
|
21
|
-
ext = Command.load_current_extension
|
14
|
+
ext = Command.load_current_extension(raise_on_fail:true)
|
22
15
|
@namespace = ext.identifier
|
23
16
|
end
|
24
17
|
class_name = name.camelize
|
@@ -27,7 +20,7 @@ module Lanes
|
|
27
20
|
if !@klass
|
28
21
|
raise Thor::Error.new("#{namespaced_name} was not found")
|
29
22
|
end
|
30
|
-
@file = Pathname.new("
|
23
|
+
@file = Pathname.new(client_dir).join("models/#{class_name}.coffee")
|
31
24
|
unless @file.exist?
|
32
25
|
raise Thor::Error.new("Model #{@file} doesn't exist")
|
33
26
|
end
|
data/lib/lanes/command.rb
CHANGED
@@ -25,8 +25,9 @@ module Lanes
|
|
25
25
|
if ext
|
26
26
|
begin
|
27
27
|
require(ext)
|
28
|
-
rescue
|
29
|
-
|
28
|
+
rescue =>e
|
29
|
+
stack = e.backtrace[0..4].join("\n")
|
30
|
+
raise Thor::Error.new("Loading ./lib/*/extension.rb failed with: #{e}\n#{stack}")
|
30
31
|
end
|
31
32
|
all = Extensions.all
|
32
33
|
if all.any?
|
@@ -39,7 +40,7 @@ module Lanes
|
|
39
40
|
end
|
40
41
|
|
41
42
|
def _maybe_fail(should_raise)
|
42
|
-
raise Thor::Error.new("Unable to locate Lanes environment") if should_raise
|
43
|
+
raise Thor::Error.new("Unable to locate Lanes environment.\nDoes ./lib/*/extension.rb exist?") if should_raise
|
43
44
|
return nil
|
44
45
|
end
|
45
46
|
end
|
data/lib/lanes/version.rb
CHANGED
@@ -11,7 +11,7 @@ Lanes.Vendor.MessageBus = {
|
|
11
11
|
start: Lanes.emptyFn
|
12
12
|
}
|
13
13
|
|
14
|
-
class Lanes.Testing.Model extends Lanes.
|
14
|
+
class Lanes.Testing.Model extends Lanes.Models.Base
|
15
15
|
api_path: "test"
|
16
16
|
props:
|
17
17
|
id: 'number',
|
@@ -29,7 +29,7 @@ class Lanes.Testing.Model extends Lanes.Data.Model
|
|
29
29
|
deps: ['something', 'fireDanger', 'active'],
|
30
30
|
fn: -> this.something + this.active;
|
31
31
|
|
32
|
-
class Lanes.Testing.Collection extends Lanes.
|
32
|
+
class Lanes.Testing.Collection extends Lanes.Models.Collection
|
33
33
|
model: Lanes.Testing.Model
|
34
34
|
|
35
35
|
syncResponse = (method,model,options)->
|
@@ -37,6 +37,7 @@ syncResponse = (method,model,options)->
|
|
37
37
|
options.success(model, syncReply, {})
|
38
38
|
if options.failure && !syncReply.success
|
39
39
|
options.failure(model, syncReply, {})
|
40
|
+
_.Promise.resolve(model,options)
|
40
41
|
|
41
42
|
syncReply = {}
|
42
43
|
|
@@ -55,7 +56,7 @@ beforeEach ->
|
|
55
56
|
Lanes.Testing.syncSpy = jasmine.createSpy('sync').and.callFake(syncResponse)
|
56
57
|
Lanes.Testing.syncSpy.lastOptions = ->
|
57
58
|
this.calls.mostRecent().args[2]
|
58
|
-
Lanes.
|
59
|
-
Lanes.
|
59
|
+
Lanes.Models.Base::sync = Lanes.Testing.syncSpy
|
60
|
+
Lanes.Models.Collection::sync = Lanes.Testing.syncSpy
|
60
61
|
|
61
62
|
|