lanes 0.1.8 → 0.1.9

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