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.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +0 -1
  3. data/client/lanes/{screens/Instance.coffee → Boot.coffee} +5 -5
  4. data/client/lanes/Config.coffee +2 -0
  5. data/client/lanes/components/multi-select/MultiSelect.coffee +20 -6
  6. data/client/lanes/components/popover/PopOver.coffee +5 -2
  7. data/client/lanes/components/record-finder/RecordFinder.coffee +12 -7
  8. data/client/lanes/components/record-finder/config.json +1 -1
  9. data/client/lanes/components/select-field/SelectField.coffee +8 -8
  10. data/client/lanes/index.js +1 -0
  11. data/client/lanes/index.scss.erb +1 -1
  12. data/client/lanes/lib/MakeBaseClass.coffee +12 -0
  13. data/client/lanes/lib/loader.coffee +3 -1
  14. data/client/lanes/lib/namespace.coffee +1 -1
  15. data/client/lanes/lib/utilFunctions.coffee +13 -1
  16. data/client/lanes/models/{ModelAssociations.coffee → AssociationMap.coffee} +12 -9
  17. data/client/lanes/models/Base.coffee +40 -14
  18. data/client/lanes/models/Collection.coffee +6 -2
  19. data/client/lanes/models/EnumMap.coffee +25 -0
  20. data/client/lanes/models/PubSub.coffee +2 -2
  21. data/client/lanes/models/Query.coffee +1 -1
  22. data/client/lanes/models/ServerCache.coffee +63 -0
  23. data/client/lanes/models/Sync.coffee +11 -13
  24. data/client/lanes/models/index.js +3 -1
  25. data/client/lanes/screens/Base.coffee +1 -1
  26. data/client/lanes/screens/Definitions.coffee +1 -1
  27. data/client/lanes/screens/index.js +1 -1
  28. data/client/lanes/screens/mixins/Editing.coffee +38 -0
  29. data/client/lanes/screens/mixins/index.js +1 -0
  30. data/client/lanes/styles/plugins/overlay.scss +7 -0
  31. data/client/lanes/testing/BeforeEach.coffee +62 -0
  32. data/client/lanes/testing/ModelSaver.coffee +5 -6
  33. data/client/lanes/testing/TestModels.coffee +23 -0
  34. data/client/lanes/testing/index.js +3 -1
  35. data/client/lanes/vendor/packaged.js +5860 -26
  36. data/client/lanes/views/Base.coffee +20 -20
  37. data/client/lanes/views/FormBindings.coffee +4 -2
  38. data/client/lanes/views/RenderContext.coffee +2 -2
  39. data/client/lanes/workspace/Layout.coffee +6 -2
  40. data/client/lanes/workspace/Navbar.coffee +1 -1
  41. data/client/lanes/workspace/Pages.coffee +1 -1
  42. data/client/lanes/workspace/navbar.html +3 -1
  43. data/client/lanes/workspace/styles/header.scss +3 -1
  44. data/lib/lanes/access/authentication_provider.rb +2 -2
  45. data/lib/lanes/access/config/routes.rb +1 -1
  46. data/lib/lanes/access/extension.rb +1 -4
  47. data/lib/lanes/access/role.rb +20 -15
  48. data/lib/lanes/access/test_fixture_extensions.rb +20 -0
  49. data/lib/lanes/access.rb +3 -3
  50. data/lib/lanes/api/request_wrapper.rb +3 -2
  51. data/lib/lanes/api/sprockets_extension.rb +1 -1
  52. data/lib/lanes/api/test_specs.rb +1 -1
  53. data/lib/lanes/capistrano.rb +18 -6
  54. data/lib/lanes/command/app.rb +1 -1
  55. data/lib/lanes/command/generate_model.rb +6 -0
  56. data/lib/lanes/command/generate_view.rb +7 -6
  57. data/lib/lanes/command/named_command.rb +1 -1
  58. data/lib/lanes/concerns/all.rb +1 -0
  59. data/lib/lanes/concerns/code_identifier.rb +43 -0
  60. data/lib/lanes/concerns/set_attribute_data.rb +0 -8
  61. data/lib/lanes/configuration.rb +1 -1
  62. data/lib/lanes/db.rb +11 -9
  63. data/lib/lanes/extension.rb +1 -0
  64. data/lib/lanes/guard_tasks.rb +1 -1
  65. data/lib/lanes/model.rb +1 -0
  66. data/lib/lanes/rake_tasks.rb +0 -2
  67. data/lib/lanes/screen.rb +1 -4
  68. data/lib/lanes/spec_helper.rb +5 -2
  69. data/lib/lanes/version.rb +1 -1
  70. data/npm-build/package.json +1 -0
  71. data/npm-build/template.js +1 -0
  72. data/spec/command-reference-files/initial/Gemfile +4 -1
  73. data/spec/command-reference-files/initial/client/appy-app/Extension.coffee +11 -1
  74. data/spec/command-reference-files/initial/config/lanes.rb +4 -1
  75. data/spec/command-reference-files/initial/lib/appy-app/extension.rb +12 -1
  76. data/spec/command-reference-files/initial/lib/appy-app.rb +0 -1
  77. data/spec/command-reference-files/model/lib/appy-app/model.rb +12 -0
  78. data/spec/command-reference-files/model/lib/appy-app.rb +11 -0
  79. data/spec/command-reference-files/view/client/appy-app/views/BigView.coffee +1 -0
  80. data/spec/lanes/helpers/lanes-helpers.coffee +0 -79
  81. data/spec/lanes/models/{ModelAssociationsSpec.coffee → AssociationMapSpec.coffee} +0 -0
  82. data/spec/lanes/models/BaseSpec.coffee +25 -12
  83. data/spec/lanes/models/CollectionSpec.coffee +20 -0
  84. data/spec/lanes/models/EnumMapSpec.coffee +26 -0
  85. data/spec/server/command_spec.rb +1 -1
  86. data/templates/Gemfile +4 -1
  87. data/templates/client/Extension.coffee +11 -1
  88. data/templates/client/views/View.coffee +2 -1
  89. data/templates/config/lanes.rb +4 -1
  90. data/templates/lib/namespace/extension.rb +12 -1
  91. data/templates/lib/namespace.rb +0 -1
  92. data/templates/spec/client/views/ViewSpec.coffee +1 -1
  93. metadata +16 -6
  94. 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: (attrs={})->
52
+ constructor: (options={})->
54
53
 
55
54
  this.cid = _.uniqueId('view');
56
- attrs || (attrs = {});
57
- parent = attrs.parent;
58
- delete attrs.parent;
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, attrs, {init: false, parent: parent})
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 attrs.el && !this.autoRender
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 || @useFormBindings || @parent?.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( @subviewId, @model )
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
- Lanes.u.getPath(subview.view, this.subviewPrefix() )
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
- # ## subviewPrefix
301
- # returns the namespace that the views should be in
302
- # is needed so views can be specified by only thier name, rather than complete path
303
- subviewPrefix: ->
304
- Lanes.u.objectPath(this.FILE)
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:el", this.rebindForm, this )
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; @view.model.setFromView(name, val); delete el[0].binding_is_setting
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
@@ -8,8 +8,8 @@ Lanes.Views.RenderContext = {
8
8
  start: (@parent, model=@parent.model)->
9
9
  @stack = [[@parent,model]]
10
10
 
11
- push: (identifier, model)->
12
- @stack.push([identifier,model])
11
+ push: (view, model)->
12
+ @stack.push([view,model])
13
13
  @_grants = null
14
14
 
15
15
  model: ->
@@ -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)
@@ -12,7 +12,7 @@ class Lanes.Workspace.Navbar extends Lanes.Views.Base
12
12
  subviews:
13
13
  screens:
14
14
  hook: 'screens-container'
15
- view: 'ActiveScreenSwitcher'
15
+ view: 'Lanes.Workspace.ActiveScreenSwitcher'
16
16
  model: 'model'
17
17
 
18
18
  bindings:
@@ -12,7 +12,7 @@ class Lanes.Workspace.Pages extends Lanes.Views.Base
12
12
 
13
13
  subviews:
14
14
  menu:
15
- view: 'ScreensMenu'
15
+ view: 'Lanes.Workspace.ScreensMenu'
16
16
 
17
17
  ui:
18
18
  screen: '.screen'
@@ -1,6 +1,8 @@
1
1
  <div class="header-top">
2
2
  <div class="navbar-header">
3
- <a class="navbar-brand logo" href="#"></a>
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
- background: url(asset_path('images/lanes/logo-sm.png')) no-repeat;
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 "Unauthorized access attempted to #{req}"
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
  }))
@@ -2,7 +2,7 @@ module Lanes
2
2
  API.routes.draw do
3
3
 
4
4
  post "/user-session.json" do
5
- wrap_json_reply do
5
+ wrap_reply do
6
6
  user = User.where(login: data['login']).first
7
7
  if user && user.authenticate(data['password'])
8
8
  session[:user_id] = user.id
@@ -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)
@@ -2,28 +2,33 @@ module Lanes
2
2
  module Access
3
3
 
4
4
  class Role
5
- class_attribute :read, :write, :delete
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
- read.include?(model)
12
+ read_types.include?(model)
13
13
  end
14
14
 
15
15
  def can_write?(model)
16
- write.include?(model)
16
+ write_types.include?(model)
17
17
  end
18
18
 
19
19
  def can_delete?(model)
20
- delete.include?(model)
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=[:read,:write,:delete], *klass)
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.read = []; subklass.write = []; subklass.delete = []
40
+ subklass.read_types = []; subklass.write_types = []; subklass.delete_types = []
36
41
  end
37
42
 
38
43
  def grant( *klasses )
39
- self.read.push( *klasses )
40
- write.push( *klasses )
41
- delete.push( *klasses )
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
- self.read.push( *klasses )
50
+ read_types.push(*klasses)
46
51
  end
47
52
 
48
53
  def write( *klasses )
49
- self.write.push( *klasses )
54
+ write_types.push(*klasses)
50
55
  end
51
56
 
52
- def delete( *klasses )
53
- self.delete.push( *klasses )
57
+ def delete(*klasses )
58
+ delete_types.push(*klasses)
54
59
  end
55
60
 
56
61
  def lock(klass, attribute)
57
- LockedFields.lock( klass, attribute, self)
62
+ LockedFields.lock(klass, attribute, self)
58
63
  end
59
64
 
60
65
  def lock_writes(klass, attribute)
61
- LockedFields.lock( klass, attribute, self, :write)
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.read.map{ |klass| type_to_client(klass) },
23
- write: role.write.map{ |klass| type_to_client(klass) },
24
- delete: role.delete.map{ |klass| type_to_client(klass) }
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
- response = yield
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']
@@ -22,7 +22,7 @@ module Lanes
22
22
  end
23
23
  Screen.each do | screen |
24
24
  assets = screen.assets
25
- manifest.compile( assets ) unless assets.empty?
25
+ manifest.compile(assets) unless assets.empty?
26
26
  end
27
27
  end
28
28
 
@@ -18,9 +18,9 @@ module Lanes
18
18
  end
19
19
 
20
20
  def js_files
21
- [ '/assets/lanes/testing' ] +
22
21
  urlpath(Jasmine::Core.js_files) +
23
22
  urlpath(Jasmine::Core.boot_files) +
23
+ [ '/assets/lanes/testing' ] +
24
24
  urlpath(spec_files(extension.identifier))
25
25
  end
26
26
 
@@ -1,10 +1,10 @@
1
- set :linked_dirs, %w{config}
1
+ set :linked_files, %w{config/database.yml}
2
2
 
3
- namespace :deploy do
3
+ namespace :db do
4
4
 
5
- desc 'Runs bundle exec lanes db migrate'
6
- task :migrate => [:set_rails_env] do
7
- on primary fetch(:migration_role) do
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
- after 'deploy:updated', 'deploy:migrate'
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
@@ -28,7 +28,7 @@ module Lanes
28
28
  template "config/routes.rb"
29
29
  template "config/lanes.rb"
30
30
  template "gitignore",".gitignore"
31
- create_file "lib/#{identifier}/models/empty.rb",""
31
+
32
32
  create_file "log/.gitkeep",""
33
33
  create_file "tmp/.gitkeep",""
34
34
  create_file "db/.gitkeep", ""
@@ -51,6 +51,12 @@ module Lanes
51
51
  end
52
52
  end
53
53
 
54
+ def add_autoload
55
+ insert_into_file "lib/#{identifier}/model.rb", before: /^end\n/ do
56
+ " autoload :#{class_name}, \"#{identifier}/models/#{file_name}\"\n"
57
+ end
58
+ end
59
+
54
60
  private
55
61
 
56
62
  def fields_with_index
@@ -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
- @client_dir << "/screens/#{options[:screen].underscore.dasherize}"
20
- @spec_dir << "/screens/#{options[:screen].underscore.dasherize}"
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
- "#{spec_dir}/#{class_name}Spec.coffee"
31
+ "#{spec_dir}/#{class_name}Spec.coffee"
31
32
  end
32
33
 
33
34
 
@@ -18,7 +18,7 @@ module Lanes
18
18
  end
19
19
 
20
20
  def set_variables
21
- @class_name = name.underscore.classify
21
+ @class_name = name.underscore.camelize
22
22
  @spec_dir = "spec/#{identifier}"
23
23
  @client_dir = "client/#{identifier}"
24
24
  end
@@ -7,5 +7,6 @@ require_relative "export_methods"
7
7
  require_relative "export_scope"
8
8
  require_relative "set_attribute_data"
9
9
  require_relative "pub_sub"
10
+ require_relative "code_identifier"
10
11
  require_relative "queries"
11
12
  require_relative "sanitize_fields"
@@ -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!
@@ -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( env = ENV['RAILS_ENV'] || 'development')
8
+ def establish_connection(env=Lanes.config.environment)
9
9
  if ENV['DATABASE_URL']
10
- ::ActiveRecord::Base.establish_connection( ENV['DATABASE_URL'] )
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( ::ActiveRecord::Base.configurations[ env ] )
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
- Lanes::DB.establish_connection( env )
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
- ActiveRecord::Tasks::DatabaseTasks.env = 'test'
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( :config => ActiveRecord::Base.configurations[ env ] )
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(&block)
48
+ def silence_activerecord
47
49
  old_logger = ::ActiveRecord::Base.logger
48
50
  ::ActiveRecord::Base.logger = nil
49
51
  yield if block_given?