lanes 0.1.8 → 0.1.9
Sign up to get free protection for your applications and to get access to all the features.
- 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?
|