lanes 0.1.8 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +0 -1
- data/client/lanes/{screens/Instance.coffee → Boot.coffee} +5 -5
- data/client/lanes/Config.coffee +2 -0
- data/client/lanes/components/multi-select/MultiSelect.coffee +20 -6
- data/client/lanes/components/popover/PopOver.coffee +5 -2
- data/client/lanes/components/record-finder/RecordFinder.coffee +12 -7
- data/client/lanes/components/record-finder/config.json +1 -1
- data/client/lanes/components/select-field/SelectField.coffee +8 -8
- data/client/lanes/index.js +1 -0
- data/client/lanes/index.scss.erb +1 -1
- data/client/lanes/lib/MakeBaseClass.coffee +12 -0
- data/client/lanes/lib/loader.coffee +3 -1
- data/client/lanes/lib/namespace.coffee +1 -1
- data/client/lanes/lib/utilFunctions.coffee +13 -1
- data/client/lanes/models/{ModelAssociations.coffee → AssociationMap.coffee} +12 -9
- data/client/lanes/models/Base.coffee +40 -14
- data/client/lanes/models/Collection.coffee +6 -2
- data/client/lanes/models/EnumMap.coffee +25 -0
- data/client/lanes/models/PubSub.coffee +2 -2
- data/client/lanes/models/Query.coffee +1 -1
- data/client/lanes/models/ServerCache.coffee +63 -0
- data/client/lanes/models/Sync.coffee +11 -13
- data/client/lanes/models/index.js +3 -1
- data/client/lanes/screens/Base.coffee +1 -1
- data/client/lanes/screens/Definitions.coffee +1 -1
- data/client/lanes/screens/index.js +1 -1
- data/client/lanes/screens/mixins/Editing.coffee +38 -0
- data/client/lanes/screens/mixins/index.js +1 -0
- data/client/lanes/styles/plugins/overlay.scss +7 -0
- data/client/lanes/testing/BeforeEach.coffee +62 -0
- data/client/lanes/testing/ModelSaver.coffee +5 -6
- data/client/lanes/testing/TestModels.coffee +23 -0
- data/client/lanes/testing/index.js +3 -1
- data/client/lanes/vendor/packaged.js +5860 -26
- data/client/lanes/views/Base.coffee +20 -20
- data/client/lanes/views/FormBindings.coffee +4 -2
- data/client/lanes/views/RenderContext.coffee +2 -2
- data/client/lanes/workspace/Layout.coffee +6 -2
- data/client/lanes/workspace/Navbar.coffee +1 -1
- data/client/lanes/workspace/Pages.coffee +1 -1
- data/client/lanes/workspace/navbar.html +3 -1
- data/client/lanes/workspace/styles/header.scss +3 -1
- data/lib/lanes/access/authentication_provider.rb +2 -2
- data/lib/lanes/access/config/routes.rb +1 -1
- data/lib/lanes/access/extension.rb +1 -4
- data/lib/lanes/access/role.rb +20 -15
- data/lib/lanes/access/test_fixture_extensions.rb +20 -0
- data/lib/lanes/access.rb +3 -3
- data/lib/lanes/api/request_wrapper.rb +3 -2
- data/lib/lanes/api/sprockets_extension.rb +1 -1
- data/lib/lanes/api/test_specs.rb +1 -1
- data/lib/lanes/capistrano.rb +18 -6
- data/lib/lanes/command/app.rb +1 -1
- data/lib/lanes/command/generate_model.rb +6 -0
- data/lib/lanes/command/generate_view.rb +7 -6
- data/lib/lanes/command/named_command.rb +1 -1
- data/lib/lanes/concerns/all.rb +1 -0
- data/lib/lanes/concerns/code_identifier.rb +43 -0
- data/lib/lanes/concerns/set_attribute_data.rb +0 -8
- data/lib/lanes/configuration.rb +1 -1
- data/lib/lanes/db.rb +11 -9
- data/lib/lanes/extension.rb +1 -0
- data/lib/lanes/guard_tasks.rb +1 -1
- data/lib/lanes/model.rb +1 -0
- data/lib/lanes/rake_tasks.rb +0 -2
- data/lib/lanes/screen.rb +1 -4
- data/lib/lanes/spec_helper.rb +5 -2
- data/lib/lanes/version.rb +1 -1
- data/npm-build/package.json +1 -0
- data/npm-build/template.js +1 -0
- data/spec/command-reference-files/initial/Gemfile +4 -1
- data/spec/command-reference-files/initial/client/appy-app/Extension.coffee +11 -1
- data/spec/command-reference-files/initial/config/lanes.rb +4 -1
- data/spec/command-reference-files/initial/lib/appy-app/extension.rb +12 -1
- data/spec/command-reference-files/initial/lib/appy-app.rb +0 -1
- data/spec/command-reference-files/model/lib/appy-app/model.rb +12 -0
- data/spec/command-reference-files/model/lib/appy-app.rb +11 -0
- data/spec/command-reference-files/view/client/appy-app/views/BigView.coffee +1 -0
- data/spec/lanes/helpers/lanes-helpers.coffee +0 -79
- data/spec/lanes/models/{ModelAssociationsSpec.coffee → AssociationMapSpec.coffee} +0 -0
- data/spec/lanes/models/BaseSpec.coffee +25 -12
- data/spec/lanes/models/CollectionSpec.coffee +20 -0
- data/spec/lanes/models/EnumMapSpec.coffee +26 -0
- data/spec/server/command_spec.rb +1 -1
- data/templates/Gemfile +4 -1
- data/templates/client/Extension.coffee +11 -1
- data/templates/client/views/View.coffee +2 -1
- data/templates/config/lanes.rb +4 -1
- data/templates/lib/namespace/extension.rb +12 -1
- data/templates/lib/namespace.rb +0 -1
- data/templates/spec/client/views/ViewSpec.coffee +1 -1
- metadata +16 -6
- data/spec/command-reference-files/initial/lib/appy-app/models/empty.rb +0 -0
@@ -25,7 +25,6 @@ class ViewBase
|
|
25
25
|
pubSub : "boolean"
|
26
26
|
parent : "object"
|
27
27
|
subviewId : { type: "string", setOnce: true }
|
28
|
-
formBindings: { type: 'any', default: false }
|
29
28
|
|
30
29
|
derived:
|
31
30
|
'$el':
|
@@ -50,16 +49,16 @@ class ViewBase
|
|
50
49
|
this.root_view?.viewport
|
51
50
|
|
52
51
|
|
53
|
-
constructor: (
|
52
|
+
constructor: (options={})->
|
54
53
|
|
55
54
|
this.cid = _.uniqueId('view');
|
56
|
-
|
57
|
-
parent =
|
58
|
-
delete
|
55
|
+
options || (options = {});
|
56
|
+
parent = options.parent;
|
57
|
+
delete options.parent;
|
59
58
|
|
60
59
|
this._substituteEventUI()
|
61
60
|
|
62
|
-
Lanes.Vendor.Ampersand.State.call(this,
|
61
|
+
Lanes.Vendor.Ampersand.State.call(this, options, {init: false, parent: parent})
|
63
62
|
|
64
63
|
this.on('change:$el', this._onElementChange, this)
|
65
64
|
this.on('change:model', this._onModelChange, this)
|
@@ -68,21 +67,18 @@ class ViewBase
|
|
68
67
|
this._onCollectionChange() if @collection
|
69
68
|
this._parsedBindings = Lanes.Vendor.Ampersand.Bindings(this.bindings, this)
|
70
69
|
this._initializeBindings();
|
71
|
-
if
|
70
|
+
if options.el && !this.autoRender
|
72
71
|
this._onElementChange();
|
73
72
|
|
74
73
|
this._initializeSubviews();
|
75
|
-
this.initialize.apply(this, arguments);
|
76
|
-
|
77
|
-
this.set(_.pick(attrs, 'model', 'collection', 'el'))
|
78
74
|
|
79
75
|
this.render() if this.autoRender && this.template
|
80
76
|
|
81
77
|
if !this.pubSub? # if it's unset, not true/false; default to parent or true
|
82
78
|
this.pubSub = if this.parent?.pubSub? then this.parent.pubSub else true
|
83
79
|
|
84
|
-
if @formBindings ||
|
85
|
-
@formBindings = new Lanes.Views.FormBindings(this, @formBindings)
|
80
|
+
if @formBindings || options.formBindings || @parent?.formBindings
|
81
|
+
@formBindings = new Lanes.Views.FormBindings(this, @formBindings||options.formBindings)
|
86
82
|
|
87
83
|
if @keyBindings
|
88
84
|
Lanes.Views.Keys.add(this, @keyBindings, @keyScope)
|
@@ -90,6 +86,8 @@ class ViewBase
|
|
90
86
|
if @pubSub
|
91
87
|
this._pubSub = new Lanes.Views.PubSub(this)
|
92
88
|
|
89
|
+
# all done, call initialize ourselves since we told state not to via 'init:false'
|
90
|
+
this.initialize.apply(this, arguments);
|
93
91
|
|
94
92
|
_normalizeUIString: (uiString, ui)->
|
95
93
|
uiString.replace(/@ui\.[a-zA-Z_$0-9]*/g, (r)->
|
@@ -114,7 +112,7 @@ class ViewBase
|
|
114
112
|
# **render** is the core function that your view can override, its job is
|
115
113
|
# to populate its element (`this.el`), with the appropriate HTML.
|
116
114
|
render: ->
|
117
|
-
Lanes.Views.RenderContext.push(
|
115
|
+
Lanes.Views.RenderContext.push( this, @model )
|
118
116
|
this.renderContextFree()
|
119
117
|
Lanes.Views.RenderContext.pop()
|
120
118
|
this
|
@@ -291,17 +289,19 @@ class ViewBase
|
|
291
289
|
Lanes.u.findObject(subview.component, 'Components', this.FILE)
|
292
290
|
else if subview.view
|
293
291
|
if _.isString(subview.view)
|
294
|
-
|
292
|
+
this.findSubView(subview.view)
|
295
293
|
else
|
296
294
|
subview.view
|
297
295
|
Lanes.warn( "Unable to obtain view for %o", subview) if ! klass
|
298
296
|
klass
|
299
297
|
|
300
|
-
# ##
|
301
|
-
#
|
302
|
-
#
|
303
|
-
|
304
|
-
Lanes.u.
|
298
|
+
# ## findSubView
|
299
|
+
# searches for the named subview in the appropriate location
|
300
|
+
# normal view will search the Views namespace, screens under the screen
|
301
|
+
findSubView: (name)->
|
302
|
+
Lanes.u.findRelative(name, this.FILE) ||
|
303
|
+
@FILE.namespace['Views']?[name] ||
|
304
|
+
Lanes.u.getPath(name)
|
305
305
|
|
306
306
|
# ## _parseSubview
|
307
307
|
# helper for parsing out the subview declaration and registering
|
@@ -370,7 +370,7 @@ class ViewBase
|
|
370
370
|
return if prev == @model
|
371
371
|
this._unbindFromObject(prev, @modelEvents) if prev
|
372
372
|
this._bindToObject(@model, @modelEvents) if @model
|
373
|
-
this.onModelChange?()
|
373
|
+
this.onModelChange?(prev)
|
374
374
|
true
|
375
375
|
|
376
376
|
_onCollectionChange: ->
|
@@ -3,7 +3,7 @@ class Lanes.Views.FormBindings
|
|
3
3
|
constructor: (@view, config={})->
|
4
4
|
_.bindAll(this,'onFieldChange')
|
5
5
|
@selector = if config.selector then "#{config.selector} " else ""
|
6
|
-
@view.on( "change
|
6
|
+
@view.on( "change:$el", this.rebindForm, this )
|
7
7
|
@view.on( "change:model", this.rebindModel, this )
|
8
8
|
@view.on( "remove", this.teardown, this )
|
9
9
|
this.rebindModel( @view, @view.model )
|
@@ -14,7 +14,9 @@ class Lanes.Views.FormBindings
|
|
14
14
|
return unless @view.model?.hasAttribute(name)
|
15
15
|
val = el.val()
|
16
16
|
unless false == this.view.trigger("update:#{val}", val)
|
17
|
-
el[0].binding_is_setting=true
|
17
|
+
el[0].binding_is_setting=true
|
18
|
+
@view.model.setFromView(name, val)
|
19
|
+
delete el[0].binding_is_setting
|
18
20
|
msg = @view.model.checkValid(name,val)
|
19
21
|
this.setError( el, msg )
|
20
22
|
return true
|
@@ -9,10 +9,10 @@ class Lanes.Workspace.Layout extends Lanes.Views.Base
|
|
9
9
|
subviews:
|
10
10
|
navbar:
|
11
11
|
hook: 'navbar-container'
|
12
|
-
view: 'Navbar'
|
12
|
+
view: 'Lanes.Workspace.Navbar'
|
13
13
|
pages:
|
14
14
|
hook: 'page-container'
|
15
|
-
view: 'Pages'
|
15
|
+
view: 'Lanes.Workspace.Pages'
|
16
16
|
|
17
17
|
session:
|
18
18
|
ui_state: 'state'
|
@@ -23,3 +23,7 @@ class Lanes.Workspace.Layout extends Lanes.Views.Base
|
|
23
23
|
constructor: (options={})->
|
24
24
|
options.ui_state = new Lanes.Workspace.UIState( model: options.model, layout: this )
|
25
25
|
super
|
26
|
+
|
27
|
+
onRender: ->
|
28
|
+
if Lanes.config.initial_workspace_screen_id
|
29
|
+
Lanes.Screens.display_id(Lanes.config.initial_workspace_screen_id)
|
@@ -1,6 +1,8 @@
|
|
1
1
|
<div class="header-top">
|
2
2
|
<div class="navbar-header">
|
3
|
-
<a class="navbar-brand logo" href="#"
|
3
|
+
<a class="navbar-brand logo" href="#">
|
4
|
+
<%= _.titleize(Lanes.Extensions.controlling().identifier) %>
|
5
|
+
</a>
|
4
6
|
|
5
7
|
<button class="screens-menu-toggle" type="button">
|
6
8
|
<span class="sr-only">Toggle navbar</span>
|
@@ -22,7 +22,9 @@
|
|
22
22
|
height: 48px;
|
23
23
|
width: 150px;
|
24
24
|
margin: 2px;
|
25
|
-
|
25
|
+
color: rgb(205, 208, 212);
|
26
|
+
font-size: 30px;
|
27
|
+
text-shadow: rgb(143, 112, 112) 2px 2px 4px;
|
26
28
|
}
|
27
29
|
|
28
30
|
.navbar-toggle, .screens-menu-toggle {
|
@@ -46,14 +46,14 @@ module Lanes
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
|
50
49
|
def wrap_reply(model, req)
|
51
50
|
if allowed_access_to?(model)
|
52
51
|
::Lanes::User.scoped_to(current_user) do | user |
|
53
52
|
yield
|
54
53
|
end
|
55
54
|
else
|
56
|
-
Lanes.logger.warn
|
55
|
+
Lanes.logger.warn request.env['HTTP_X_TESTING_USER']
|
56
|
+
Lanes.logger.warn "Unauthorized access attempted to #{req.url}"
|
57
57
|
req.halt( 401, Oj.dump({
|
58
58
|
success:false, errors: {user: "Access Denied"}, message: "Access Denied"
|
59
59
|
}))
|
@@ -27,10 +27,7 @@ module Lanes
|
|
27
27
|
end
|
28
28
|
def roles_for_client
|
29
29
|
Lanes::Access::Role.all_available.map do |role|
|
30
|
-
{
|
31
|
-
id: role.to_s.demodulize.underscore,
|
32
|
-
name: role.to_s.demodulize
|
33
|
-
}
|
30
|
+
{ id: role.to_s.demodulize.underscore, name: role.to_s.demodulize }
|
34
31
|
end
|
35
32
|
end
|
36
33
|
def client_bootstrap_data(view)
|
data/lib/lanes/access/role.rb
CHANGED
@@ -2,28 +2,33 @@ module Lanes
|
|
2
2
|
module Access
|
3
3
|
|
4
4
|
class Role
|
5
|
-
class_attribute :
|
5
|
+
class_attribute :read_types, :write_types, :delete_types
|
6
6
|
|
7
7
|
def initialize(user)
|
8
8
|
@user = user
|
9
9
|
end
|
10
10
|
|
11
11
|
def can_read?(model)
|
12
|
-
|
12
|
+
read_types.include?(model)
|
13
13
|
end
|
14
14
|
|
15
15
|
def can_write?(model)
|
16
|
-
|
16
|
+
write_types.include?(model)
|
17
17
|
end
|
18
18
|
|
19
19
|
def can_delete?(model)
|
20
|
-
|
20
|
+
delete_types.include?(model)
|
21
21
|
end
|
22
22
|
|
23
23
|
class << self
|
24
24
|
ALL=Array.new
|
25
25
|
|
26
|
-
def grant_global_access(types
|
26
|
+
def grant_global_access(types=:all, *klass)
|
27
|
+
unless types.is_a?(Symbol)
|
28
|
+
klass.unshift(types)
|
29
|
+
types=:all
|
30
|
+
end
|
31
|
+
types = [:read,:write,:delete] if :all == types
|
27
32
|
types = [*types]
|
28
33
|
ALL.each do | child |
|
29
34
|
types.each{ |type| child.send(type).concat(klass) }
|
@@ -32,33 +37,33 @@ module Lanes
|
|
32
37
|
|
33
38
|
def inherited(subklass)
|
34
39
|
ALL << subklass
|
35
|
-
subklass.
|
40
|
+
subklass.read_types = []; subklass.write_types = []; subklass.delete_types = []
|
36
41
|
end
|
37
42
|
|
38
43
|
def grant( *klasses )
|
39
|
-
|
40
|
-
|
41
|
-
|
44
|
+
read_types.push(*klasses)
|
45
|
+
write_types.push(*klasses)
|
46
|
+
delete_types.push(*klasses)
|
42
47
|
end
|
43
48
|
|
44
49
|
def read( *klasses )
|
45
|
-
|
50
|
+
read_types.push(*klasses)
|
46
51
|
end
|
47
52
|
|
48
53
|
def write( *klasses )
|
49
|
-
|
54
|
+
write_types.push(*klasses)
|
50
55
|
end
|
51
56
|
|
52
|
-
def delete(
|
53
|
-
|
57
|
+
def delete(*klasses )
|
58
|
+
delete_types.push(*klasses)
|
54
59
|
end
|
55
60
|
|
56
61
|
def lock(klass, attribute)
|
57
|
-
LockedFields.lock(
|
62
|
+
LockedFields.lock(klass, attribute, self)
|
58
63
|
end
|
59
64
|
|
60
65
|
def lock_writes(klass, attribute)
|
61
|
-
LockedFields.lock(
|
66
|
+
LockedFields.lock(klass, attribute, self, :write)
|
62
67
|
end
|
63
68
|
|
64
69
|
def all_available
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module AccessFixtureTestPatches
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
alias_method_chain :table_rows, :custom_autoset_user_fields
|
6
|
+
end
|
7
|
+
|
8
|
+
def table_rows_with_custom_autoset_user_fields
|
9
|
+
results = table_rows_without_custom_autoset_user_fields
|
10
|
+
if model_class && model_class < ActiveRecord::Base && model_class.record_modifications
|
11
|
+
results[ table_name ].each do | row |
|
12
|
+
row['created_by_id'] = 593363170 if model_class.column_names.include?('created_by_id')
|
13
|
+
row['updated_by_id'] = 593363170 if model_class.column_names.include?('updated_by_id')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
results
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
ActiveRecord::FixtureSet.send :include, AccessFixtureTestPatches
|
data/lib/lanes/access.rb
CHANGED
@@ -19,9 +19,9 @@ module Lanes
|
|
19
19
|
:roles => user.roles.map{ | role |
|
20
20
|
{
|
21
21
|
type: type_to_client_id(role),
|
22
|
-
read: role.
|
23
|
-
write: role.
|
24
|
-
delete: role.
|
22
|
+
read: role.read_types.map{ |klass| type_to_client(klass) },
|
23
|
+
write: role.write_types.map{ |klass| type_to_client(klass) },
|
24
|
+
delete: role.delete_types.map{ |klass| type_to_client(klass) }
|
25
25
|
}
|
26
26
|
},
|
27
27
|
:locked_fields => LockedFields.definitions.map{ | klass, locks |
|
@@ -31,7 +31,7 @@ module Lanes
|
|
31
31
|
def make_handler(model, controller, parent_attribute)
|
32
32
|
lambda do
|
33
33
|
authentication = Lanes::API::AuthenticationProvider.new(request)
|
34
|
-
authentication.wrap_reply(model,self) do
|
34
|
+
authentication.wrap_reply(model, self) do
|
35
35
|
if parent_attribute
|
36
36
|
params[:nested_attribute] = Hash[ parent_attribute,
|
37
37
|
params[parent_attribute] ]
|
@@ -46,6 +46,7 @@ module Lanes
|
|
46
46
|
|
47
47
|
def log_request
|
48
48
|
Lanes.logger.info "UserID: #{session['user_id']}, Params: #{request.params}"
|
49
|
+
Lanes.logger.debug JSON.pretty_generate(data) unless Lanes.env.production?
|
49
50
|
end
|
50
51
|
|
51
52
|
def wrap_reply(with_transaction=true)
|
@@ -53,7 +54,7 @@ module Lanes
|
|
53
54
|
log_request
|
54
55
|
if with_transaction
|
55
56
|
Lanes::Model.transaction do
|
56
|
-
|
57
|
+
response = yield
|
57
58
|
# This is quite possibly a horrible idea.
|
58
59
|
# It enables test specs to reset the db state after a request
|
59
60
|
if Lanes.env.test? && request.env['HTTP_X_ROLLBACK_AFTER_REQUEST']
|
data/lib/lanes/api/test_specs.rb
CHANGED
data/lib/lanes/capistrano.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
set :
|
1
|
+
set :linked_files, %w{config/database.yml}
|
2
2
|
|
3
|
-
namespace :
|
3
|
+
namespace :db do
|
4
4
|
|
5
|
-
desc '
|
6
|
-
task :migrate => [:set_rails_env] do
|
7
|
-
on
|
5
|
+
desc 'Migrates the database by running: bundle exec lanes db migrate'
|
6
|
+
task :migrate => ["deploy:set_rails_env"] do
|
7
|
+
on roles(:db) do
|
8
8
|
info '[deploy:migrate] Run `lanes db migrate`'
|
9
9
|
within release_path do
|
10
10
|
with rails_env: fetch(:rails_env) do
|
@@ -14,5 +14,17 @@ namespace :deploy do
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
|
17
|
+
desc 'Seeds the database by running: bundle exec lanes db seed'
|
18
|
+
task :seed => ["deploy:set_rails_env"] do
|
19
|
+
on roles(:db) do
|
20
|
+
info '[deploy:seed] Run `lanes db seed`'
|
21
|
+
within release_path do
|
22
|
+
with rails_env: fetch(:rails_env) do
|
23
|
+
execute :bundle, "exec lanes db seed"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
after 'deploy:updated', 'db:migrate'
|
18
30
|
end
|
data/lib/lanes/command/app.rb
CHANGED
@@ -28,7 +28,7 @@ module Lanes
|
|
28
28
|
template "config/routes.rb"
|
29
29
|
template "config/lanes.rb"
|
30
30
|
template "gitignore",".gitignore"
|
31
|
-
|
31
|
+
|
32
32
|
create_file "log/.gitkeep",""
|
33
33
|
create_file "tmp/.gitkeep",""
|
34
34
|
create_file "db/.gitkeep", ""
|
@@ -9,25 +9,26 @@ module Lanes
|
|
9
9
|
screen: 'global'
|
10
10
|
}
|
11
11
|
class_options( OPTIONS )
|
12
|
+
attr_reader :view_class
|
12
13
|
|
13
14
|
def set_variables
|
14
15
|
super
|
15
16
|
if options[:screen] == 'global'
|
16
17
|
@client_dir << "/views"
|
17
18
|
@spec_dir << "/views"
|
19
|
+
@view_class = "#{namespace}.Views.#{class_name}"
|
18
20
|
else
|
19
|
-
|
20
|
-
@
|
21
|
+
screen_directory = options[:screen].underscore.dasherize
|
22
|
+
@client_dir << "/screens/#{screen_directory}"
|
23
|
+
@spec_dir << "/screens/#{screen_directory}"
|
24
|
+
@view_class = "#{namespace}.Screens.#{options[:screen]}.#{class_name}"
|
21
25
|
end
|
22
26
|
end
|
23
27
|
|
24
|
-
# desc "foo bar"
|
25
|
-
# option :from, :required => true
|
26
|
-
|
27
28
|
def create_screen
|
28
29
|
template "client/views/View.coffee", "#{client_dir}/#{class_name}.coffee"
|
29
30
|
template "spec/client/views/ViewSpec.coffee", \
|
30
|
-
|
31
|
+
"#{spec_dir}/#{class_name}Spec.coffee"
|
31
32
|
end
|
32
33
|
|
33
34
|
|
data/lib/lanes/concerns/all.rb
CHANGED
@@ -0,0 +1,43 @@
|
|
1
|
+
module Lanes
|
2
|
+
module Concerns
|
3
|
+
|
4
|
+
# @see ClassMethods
|
5
|
+
module CodeIdentifier
|
6
|
+
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
# ### Code Identifier Concern
|
10
|
+
# This adds the {#has_code_identifier} class method
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
# A 2-10 character string that identifies an entity, such as a Customer, Vendor, or SKU.
|
14
|
+
# The code is often assigned by the user, but may also
|
15
|
+
# be auto-generated by {Skr::Strings.code_identifier}
|
16
|
+
#
|
17
|
+
# @param max_length [Integer] how long the code is allowed to be
|
18
|
+
# @param from [Symbol], method to call for a string to base the code upon
|
19
|
+
def has_code_identifier( from: nil, max_length: 10 )
|
20
|
+
|
21
|
+
validates :code, :length=>2..max_length, :presence=>true, :uniqueness=>true
|
22
|
+
|
23
|
+
alias_attribute :record_identifier, :code
|
24
|
+
|
25
|
+
if from
|
26
|
+
before_validation(:on=>:create) do
|
27
|
+
source = self[from]
|
28
|
+
unless source.blank?
|
29
|
+
self.code ||= Lanes::Strings.code_identifier( source, length:max_length )
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
before_validation do
|
35
|
+
self.code = self.code.upcase unless self.code.blank?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -32,14 +32,6 @@ module Lanes::Concerns
|
|
32
32
|
|
33
33
|
module ClassMethods
|
34
34
|
|
35
|
-
# # An attribute accessor that allows access from the API
|
36
|
-
# def api_attr_accessor( *names )
|
37
|
-
# names.each do | attr |
|
38
|
-
# attr_accessor attr
|
39
|
-
# whitelist_attributes attr
|
40
|
-
# end
|
41
|
-
# end
|
42
|
-
|
43
35
|
# @param attributes [Array of symbols] attributes that are safe for the API to set
|
44
36
|
def whitelist_attributes( *attributes )
|
45
37
|
options = attributes.extract_options!
|
data/lib/lanes/configuration.rb
CHANGED
@@ -52,7 +52,7 @@ module Lanes
|
|
52
52
|
config_option :table_prefix, ''
|
53
53
|
|
54
54
|
# The configuration environment to use, test, development, production
|
55
|
-
config_option :environment, (ENV['RACK_ENV'] || 'development').to_sym
|
55
|
+
config_option :environment, (ENV['LANES_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development').to_sym
|
56
56
|
|
57
57
|
# The secret key to use for session cookies.
|
58
58
|
config_option :session_secret_key_base, '1234', silent: true
|
data/lib/lanes/db.rb
CHANGED
@@ -5,14 +5,14 @@ module Lanes
|
|
5
5
|
|
6
6
|
attr_accessor(:config_file)
|
7
7
|
|
8
|
-
def establish_connection(
|
8
|
+
def establish_connection(env=Lanes.config.environment)
|
9
9
|
if ENV['DATABASE_URL']
|
10
|
-
::ActiveRecord::Base.establish_connection(
|
10
|
+
::ActiveRecord::Base.establish_connection(ENV['DATABASE_URL'])
|
11
11
|
else
|
12
12
|
file = config_file || Extensions.controlling.root_path.join("config","database.yml")
|
13
13
|
config = YAML::load( IO.read(file) )
|
14
14
|
::ActiveRecord::Base.configurations = config
|
15
|
-
::ActiveRecord::Base.establish_connection(
|
15
|
+
::ActiveRecord::Base.establish_connection(::ActiveRecord::Base.configurations[env.to_s])
|
16
16
|
end
|
17
17
|
ActiveRecord::Base.logger = Lanes.logger
|
18
18
|
end
|
@@ -25,25 +25,27 @@ module Lanes
|
|
25
25
|
def configure_rake_environment
|
26
26
|
ActiveRecord::Tasks::DatabaseTasks.seed_loader = Lanes::DB
|
27
27
|
default_schema = Extensions.controlling.root_path.join("db","schema.sql")
|
28
|
-
env = ENV['RAILS_ENV'] || 'development'
|
29
28
|
ENV['SCHEMA'] ||= default_schema.to_s
|
30
29
|
ENV['DB_STRUCTURE'] ||= default_schema.to_s
|
31
30
|
ActiveRecord::Base.schema_format = :sql
|
32
|
-
|
31
|
+
ActiveRecord::Base.dump_schema_after_migration = !Lanes.env.production?
|
32
|
+
Lanes::DB.establish_connection
|
33
33
|
ActiveRecord::Tasks::DatabaseTasks.database_configuration = ActiveRecord::Base.configurations
|
34
|
-
|
34
|
+
env=Lanes.config.environment.to_s
|
35
|
+
ActiveRecord::Tasks::DatabaseTasks.env = env
|
35
36
|
ActiveRecord::Tasks::DatabaseTasks.migrations_paths = 'db/migrate'
|
36
|
-
ActiveRecord::Tasks::DatabaseTasks.current_config(
|
37
|
+
ActiveRecord::Tasks::DatabaseTasks.current_config(
|
38
|
+
config: ActiveRecord::Base.configurations[env]
|
39
|
+
)
|
37
40
|
end
|
38
41
|
|
39
|
-
|
40
42
|
private
|
41
43
|
|
42
44
|
def migrations_dir
|
43
45
|
::ActiveRecord::Migrator.migrations_paths.first
|
44
46
|
end
|
45
47
|
|
46
|
-
def silence_activerecord
|
48
|
+
def silence_activerecord
|
47
49
|
old_logger = ::ActiveRecord::Base.logger
|
48
50
|
::ActiveRecord::Base.logger = nil
|
49
51
|
yield if block_given?
|