joosy 0.1.0.RC1

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 (98) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +14 -0
  3. data/Gemfile.lock +159 -0
  4. data/Guardfile +30 -0
  5. data/MIT-LICENSE +21 -0
  6. data/README.rdoc +3 -0
  7. data/Rakefile +14 -0
  8. data/app/assets/javascripts/joosy.js.coffee +7 -0
  9. data/app/assets/javascripts/joosy/core/application.js.coffee +28 -0
  10. data/app/assets/javascripts/joosy/core/form.js.coffee +87 -0
  11. data/app/assets/javascripts/joosy/core/helpers.js.coffee +6 -0
  12. data/app/assets/javascripts/joosy/core/joosy.js.coffee +65 -0
  13. data/app/assets/javascripts/joosy/core/layout.js.coffee +47 -0
  14. data/app/assets/javascripts/joosy/core/modules/container.js.coffee +59 -0
  15. data/app/assets/javascripts/joosy/core/modules/events.js.coffee +35 -0
  16. data/app/assets/javascripts/joosy/core/modules/filters.js.coffee +39 -0
  17. data/app/assets/javascripts/joosy/core/modules/log.js.coffee +15 -0
  18. data/app/assets/javascripts/joosy/core/modules/module.js.coffee +43 -0
  19. data/app/assets/javascripts/joosy/core/modules/renderer.js.coffee +116 -0
  20. data/app/assets/javascripts/joosy/core/modules/time_manager.js.coffee +25 -0
  21. data/app/assets/javascripts/joosy/core/modules/widgets_manager.js.coffee +58 -0
  22. data/app/assets/javascripts/joosy/core/page.js.coffee +156 -0
  23. data/app/assets/javascripts/joosy/core/preloader.js.coffee +5 -0
  24. data/app/assets/javascripts/joosy/core/resource/generic.js.coffee +61 -0
  25. data/app/assets/javascripts/joosy/core/resource/rest.js.coffee +76 -0
  26. data/app/assets/javascripts/joosy/core/resource/rest_collection.js.coffee +48 -0
  27. data/app/assets/javascripts/joosy/core/router.js.coffee +89 -0
  28. data/app/assets/javascripts/joosy/core/templaters/rails_jst.js.coffee +20 -0
  29. data/app/assets/javascripts/joosy/core/widget.js.coffee +41 -0
  30. data/app/assets/javascripts/joosy/preloaders/caching.js.coffee +94 -0
  31. data/app/assets/javascripts/joosy/preloaders/inline.js.coffee +55 -0
  32. data/app/helpers/joosy/sprockets_helper.rb +23 -0
  33. data/app/views/layouts/json_wrapper.json.erb +1 -0
  34. data/joosy.gemspec +25 -0
  35. data/lib/joosy.rb +9 -0
  36. data/lib/joosy/forms.rb +47 -0
  37. data/lib/joosy/rails/engine.rb +17 -0
  38. data/lib/joosy/rails/version.rb +5 -0
  39. data/lib/rails/generators/joosy/application_generator.rb +41 -0
  40. data/lib/rails/generators/joosy/joosy_base.rb +30 -0
  41. data/lib/rails/generators/joosy/layout_generator.rb +32 -0
  42. data/lib/rails/generators/joosy/page_generator.rb +44 -0
  43. data/lib/rails/generators/joosy/preloader_generator.rb +32 -0
  44. data/lib/rails/generators/joosy/resource_generator.rb +29 -0
  45. data/lib/rails/generators/joosy/templates/app.js.coffee +10 -0
  46. data/lib/rails/generators/joosy/templates/app/helpers/application.js.coffee +4 -0
  47. data/lib/rails/generators/joosy/templates/app/layouts/application.js.coffee +2 -0
  48. data/lib/rails/generators/joosy/templates/app/layouts/template.js.coffee +2 -0
  49. data/lib/rails/generators/joosy/templates/app/pages/application.js.coffee +1 -0
  50. data/lib/rails/generators/joosy/templates/app/pages/template.js.coffee +5 -0
  51. data/lib/rails/generators/joosy/templates/app/pages/welcome/index.js.coffee +22 -0
  52. data/lib/rails/generators/joosy/templates/app/resources/template.js.coffee +2 -0
  53. data/lib/rails/generators/joosy/templates/app/routes.js.coffee +8 -0
  54. data/lib/rails/generators/joosy/templates/app/templates/layouts/application.jst.hamlc +2 -0
  55. data/lib/rails/generators/joosy/templates/app/templates/pages/welcome/index.jst.hamlc +7 -0
  56. data/lib/rails/generators/joosy/templates/app/widgets/template.js.coffee +2 -0
  57. data/lib/rails/generators/joosy/templates/app_controller.rb +9 -0
  58. data/lib/rails/generators/joosy/templates/app_preloader.js.coffee.erb +13 -0
  59. data/lib/rails/generators/joosy/templates/preload.html.erb +26 -0
  60. data/lib/rails/generators/joosy/templates/preload.html.haml +19 -0
  61. data/lib/rails/generators/joosy/widget_generator.rb +32 -0
  62. data/spec/javascripts/helpers/spec_helper.js.coffee +44 -0
  63. data/spec/javascripts/joosy/core/application_spec.js.coffee +40 -0
  64. data/spec/javascripts/joosy/core/form_spec.js.coffee +141 -0
  65. data/spec/javascripts/joosy/core/joosy_spec.js.coffee +72 -0
  66. data/spec/javascripts/joosy/core/layout_spec.js.coffee +50 -0
  67. data/spec/javascripts/joosy/core/modules/container_spec.js.coffee +92 -0
  68. data/spec/javascripts/joosy/core/modules/events_spec.js.coffee +53 -0
  69. data/spec/javascripts/joosy/core/modules/filters_spec.js.coffee +71 -0
  70. data/spec/javascripts/joosy/core/modules/log_spec.js.coffee +15 -0
  71. data/spec/javascripts/joosy/core/modules/module_spec.js.coffee +47 -0
  72. data/spec/javascripts/joosy/core/modules/renderer_spec.js.coffee +149 -0
  73. data/spec/javascripts/joosy/core/modules/time_manager_spec.js.coffee +25 -0
  74. data/spec/javascripts/joosy/core/modules/widget_manager_spec.js.coffee +75 -0
  75. data/spec/javascripts/joosy/core/page_spec.js.coffee +175 -0
  76. data/spec/javascripts/joosy/core/resource/generic_spec.js.coffee +35 -0
  77. data/spec/javascripts/joosy/core/resource/rest_collection_spec.js.coffee +65 -0
  78. data/spec/javascripts/joosy/core/resource/rest_spec.js.coffee +108 -0
  79. data/spec/javascripts/joosy/core/router_spec.js.coffee +123 -0
  80. data/spec/javascripts/joosy/core/templaters/rails_jst_spec.js.coffee +25 -0
  81. data/spec/javascripts/joosy/core/widget_spec.js.coffee +51 -0
  82. data/spec/javascripts/joosy/preloaders/caching_spec.js.coffee +36 -0
  83. data/spec/javascripts/joosy/preloaders/inline_spec.js.coffee +16 -0
  84. data/spec/javascripts/support/assets/coolface.jpg +0 -0
  85. data/spec/javascripts/support/assets/okay.jpg +0 -0
  86. data/spec/javascripts/support/assets/test.js +1 -0
  87. data/spec/javascripts/support/jasmine.yml +74 -0
  88. data/spec/javascripts/support/jasmine_config.rb +23 -0
  89. data/spec/javascripts/support/jasmine_runner.rb +32 -0
  90. data/spec/javascripts/support/sinon-1.3.1.js +3469 -0
  91. data/spec/javascripts/support/sinon-ie-1.3.1.js +82 -0
  92. data/vendor/assets/javascripts/base64.js +135 -0
  93. data/vendor/assets/javascripts/inflection.js +656 -0
  94. data/vendor/assets/javascripts/jquery.form.js +980 -0
  95. data/vendor/assets/javascripts/jquery.hashchange.js +390 -0
  96. data/vendor/assets/javascripts/metamorph.js +409 -0
  97. data/vendor/assets/javascripts/sugar.js +6040 -0
  98. metadata +232 -0
@@ -0,0 +1,41 @@
1
+ #= require joosy/core/joosy
2
+ #= require joosy/core/modules/module
3
+ #= require joosy/core/modules/log
4
+ #= require joosy/core/modules/events
5
+ #= require joosy/core/modules/container
6
+ #= require joosy/core/modules/renderer
7
+ #= require joosy/core/modules/filters
8
+
9
+ class Joosy.Widget extends Joosy.Module
10
+ @include Joosy.Modules.Log
11
+ @include Joosy.Modules.Events
12
+ @include Joosy.Modules.Container
13
+ @include Joosy.Modules.Renderer
14
+ @include Joosy.Modules.Filters
15
+
16
+ __renderer: false
17
+
18
+ setInterval: (args...) ->
19
+ @parent.setInterval(args...)
20
+
21
+ setTimeout: (args...) ->
22
+ @parent.setTimeout(args...)
23
+
24
+ navigate: (args...) ->
25
+ Joosy.Router.navigate(args...)
26
+
27
+ __renderSection: ->
28
+ 'widgets'
29
+
30
+ __load: (@parent, @container) ->
31
+ if @__renderer
32
+ @container.html @__renderer()
33
+ @refreshElements()
34
+ @__delegateEvents()
35
+ @__runAfterLoads()
36
+
37
+ this
38
+
39
+ __unload: ->
40
+ @__removeMetamorphs()
41
+ @__runAfterUnloads()
@@ -0,0 +1,94 @@
1
+ #= require base64
2
+
3
+ window.globalEval = (src) ->
4
+ if window.execScript
5
+ window.execScript src
6
+ else
7
+ fn = ->
8
+ window.eval.call window,src
9
+ fn()
10
+
11
+ @Preloader = @CachingPreloader =
12
+ force: false
13
+ prefix: "cache:"
14
+
15
+ libraries: []
16
+ counter: 0
17
+
18
+ complete: false
19
+
20
+ ajax: (url, size, callback) ->
21
+ if window.XMLHttpRequest
22
+ x = new XMLHttpRequest
23
+ else
24
+ x = new ActiveXObject 'Microsoft.XMLHTTP'
25
+
26
+ x.open 'GET', url, 1
27
+
28
+ x.onreadystatechange = () =>
29
+ if x.readyState > 3
30
+ clearInterval(@interval)
31
+ callback?(x)
32
+
33
+ if @progress
34
+ poller = =>
35
+ try
36
+ @progress.call window, Math.round((x.responseText.length / size) * (@counter / @libraries.length) * 100)
37
+ catch e
38
+ # ... IE?
39
+
40
+ @interval = setInterval poller, 100
41
+
42
+ x.send()
43
+
44
+ restore: ->
45
+ for name, i in @libraries
46
+ code = window.localStorage.getItem(name)
47
+ window.globalEval if window.navigator.appName == "Microsoft Internet Explorer" then Base64.decode(code) else code
48
+ @complete?.call window, true
49
+
50
+ download: (libraries) ->
51
+ if libraries.length > 0
52
+ @counter += 1
53
+
54
+ lib = libraries.shift()
55
+ url = lib[0]
56
+ size = lib[1]
57
+
58
+ @ajax url, size, (xhr) =>
59
+ code = xhr.responseText
60
+ window.localStorage.setItem @prefix+url, (if window.navigator.appName == "Microsoft Internet Explorer" then Base64.encode(code) else code)
61
+ window.globalEval xhr.responseText
62
+ @download libraries
63
+ else
64
+ @clean()
65
+ @complete?.call window
66
+
67
+ load: (libraries, options={}) ->
68
+ @[key] = val for key, val of options
69
+ @libraries = libraries.slice()
70
+
71
+ for lib, i in @libraries
72
+ @libraries[i] = @prefix+lib[0]
73
+
74
+ if !@force && @check()
75
+ @restore()
76
+ else
77
+ @start?.call window
78
+ @download libraries
79
+
80
+ check: ->
81
+ flag = true
82
+ for name, i in @libraries
83
+ flag &&= window.localStorage.getItem(name)?
84
+ flag
85
+
86
+ clean: ->
87
+ removed = 0
88
+
89
+ for element, i in window.localStorage
90
+ key = window.localStorage.key(i-removed)
91
+
92
+ if key.indexOf(@prefix) == 0 && @libraries.indexOf(key) < 0
93
+ window.localStorage.removeItem key
94
+ removed += 1
@@ -0,0 +1,55 @@
1
+ #
2
+ # Preloader for libraries using <script src> without any caching magic
3
+ #
4
+ # Example:
5
+ # libraries = [['/test1.js'], ['/test2.js']]
6
+ # InlinePreloader.load libraries,
7
+ # start: -> console.log 'preloading started'
8
+ # complete: -> console.log 'preloading finished'
9
+ #
10
+ # @class InlinePreloader
11
+ #
12
+ @Preloader = @InlinePreloader =
13
+
14
+ #
15
+ # Loads one script by adding <script src> to DOM head
16
+ #
17
+ # @param [String] url to load script from
18
+ # @param [Function] `() -> null` to call after script was loaded and executed
19
+ #
20
+ receive: (url, callback) ->
21
+ head = document.getElementsByTagName("head")[0]
22
+ script = document.createElement("script")
23
+ script.src = url
24
+
25
+ done = false
26
+
27
+ proceed = ->
28
+ if ( !done && (!this.readyState ||
29
+ this.readyState == "loaded" || this.readyState == "complete") )
30
+
31
+ done = true and callback() if callback
32
+ script.onload = script.onreadystatechange = null
33
+
34
+ script.onload = script.onreadystatechange = proceed
35
+
36
+ head.appendChild(script)
37
+ return undefined
38
+
39
+ #
40
+ # Loads set of libraries by adding <script src> to DOM head
41
+ # See class description for example of usage
42
+ #
43
+ # @param [Array] 2-levels array of libraries URLs i.e. [['/test1.js'],['/test2.js']]
44
+ # @param [Hash] Available options:
45
+ # * start: `() -> null` to call before load starts:
46
+ # * complete: `() -> null` to call after load completes
47
+ #
48
+ load: (libraries, options) ->
49
+ @[key] = val for key, val of options
50
+ @start?.call window
51
+
52
+ if libraries.length > 0
53
+ @receive libraries.shift()[0], => @load(libraries)
54
+ else
55
+ @complete?.call window
@@ -0,0 +1,23 @@
1
+ module Joosy::SprocketsHelper
2
+ def extract_sources_and_sizes_from_include_tag(name)
3
+ code = javascript_include_tag name
4
+ resources = code.scan(/(?:href|src)=['"]([^'"]+)['"]/).flatten
5
+
6
+ resources.map do |resource|
7
+ path = ::Rails.root.to_s + "/public" + resource.split('?')[0]
8
+ size = File.size(path) rescue false
9
+ [resource, size]
10
+ end.to_json.html_safe
11
+ end
12
+
13
+ def require_joosy_preloader_for(app_asset, options={})
14
+ preloader_asset = "joosy/preloaders/#{options[:preloader] || 'caching'}"
15
+ force_preloader = options[:force] || false
16
+
17
+ if force_preloader
18
+ require_asset preloader_asset
19
+ else
20
+ require_asset Rails.env == 'production' ? preloader_asset : app_asset
21
+ end
22
+ end
23
+ end
@@ -0,0 +1 @@
1
+ <textarea><%= yield %></textarea>
data/joosy.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ require File.expand_path("../lib/joosy/rails/version", __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "joosy"
5
+ s.version = Joosy::Rails::VERSION
6
+ s.platform = Gem::Platform::RUBY
7
+ s.summary = "Joosy Framework support for Ruby on Rails"
8
+ s.email = "boris@roundlake.ru"
9
+ s.homepage = "http://github.com/roundlake/joosy"
10
+ s.description = "A gem wrapper to include Joosy via the asset pipeline."
11
+ s.authors = ['Boris Staal', 'Andrew Shaydurov', 'Peter Zotov', 'Alexander Pavlenko']
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.require_paths = ["lib"]
15
+
16
+ s.add_dependency 'rails', ">= 3.1.0"
17
+ s.add_dependency 'coffee-rails'
18
+ s.add_dependency 'jquery-rails'
19
+ s.add_dependency 'haml_coffee_assets'
20
+
21
+ s.add_development_dependency 'guard'
22
+ s.add_development_dependency 'guard-coffeescript'
23
+ s.add_development_dependency 'guard-sprockets'
24
+ s.add_development_dependency 'jasmine'
25
+ end
data/lib/joosy.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'haml_coffee_assets'
2
+ require 'jquery-rails'
3
+ require 'coffee-rails'
4
+
5
+ require 'joosy/rails/engine'
6
+ require 'joosy/rails/version'
7
+ require 'joosy/forms'
8
+
9
+ ActionController::Base.send :include, Joosy::Forms
@@ -0,0 +1,47 @@
1
+ module Joosy
2
+ module Forms
3
+ def self.included base
4
+ base.send(:include, InstanceMethods)
5
+ end
6
+
7
+ module InstanceMethods
8
+ def joosy_store(entity, data=nil, &block)
9
+ if entity.save
10
+ joosy_succeed(data, entity, &block)
11
+ else
12
+ joosy_fail(entity.errors.messages, entity.class.name)
13
+ end
14
+ end
15
+
16
+ def joosy_fail(errors, entity=false)
17
+ errors = Hash[*errors.map {|x| [x, nil]}.flatten] if errors.is_a?(Array)
18
+
19
+ if !entity
20
+ notifications = errors
21
+ else
22
+ notifications = {}
23
+ errors.each do |k, v|
24
+ notifications["#{entity.underscore}[#{k}]"] = v
25
+ end
26
+ end
27
+
28
+ joosy_respond notifications, :unprocessable_entity
29
+ end
30
+
31
+ def joosy_succeed(data, entity=nil, &block)
32
+ block.call(entity) if block_given?
33
+ joosy_respond (data.is_a?(Proc) ? data.call(entity) : (data || entity))
34
+ end
35
+
36
+ def joosy_respond(data, status=200)
37
+ unless request.xhr?
38
+ @data = { :status => status, :json => data }
39
+ self.class.layout 'json_wrapper'
40
+ render :text => result.to_json, :status => status
41
+ else
42
+ render :json => data, :status => status
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,17 @@
1
+ require 'rails/engine'
2
+
3
+ module Joosy
4
+ module Rails
5
+ class Engine < ::Rails::Engine
6
+
7
+ initializer 'joosy.extend.sprockets' do |app|
8
+ ActiveSupport.on_load(:action_view) do
9
+ app.assets.context_class.instance_eval do
10
+ include ::Joosy::SprocketsHelper
11
+ end
12
+ end
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ module Joosy
2
+ module Rails
3
+ VERSION = "0.1.0.RC1"
4
+ end
5
+ end
@@ -0,0 +1,41 @@
1
+ require 'rails/generators/joosy/joosy_base'
2
+
3
+ module Joosy
4
+ module Generators
5
+ class ApplicationGenerator < ::Rails::Generators::JoosyBase
6
+ source_root File.join(File.dirname(__FILE__), 'templates')
7
+
8
+ def create_files
9
+ super
10
+
11
+ template "app.js.coffee", "#{file_path}.js.coffee"
12
+
13
+ empty_directory file_path
14
+
15
+ template "app/routes.js.coffee", "#{file_path}/routes.js.coffee"
16
+
17
+ empty_directory "#{file_path}/helpers"
18
+ template "app/helpers/application.js.coffee", "#{file_path}/helpers/application.js.coffee"
19
+
20
+ empty_directory "#{file_path}/layouts"
21
+ template "app/layouts/application.js.coffee", "#{file_path}/layouts/application.js.coffee"
22
+
23
+ empty_directory "#{file_path}/pages/welcome"
24
+ template "app/pages/application.js.coffee", "#{file_path}/pages/application.js.coffee"
25
+ template "app/pages/welcome/index.js.coffee", "#{file_path}/pages/welcome/index.js.coffee"
26
+
27
+ empty_directory "#{file_path}/templates/layouts"
28
+ template "app/templates/layouts/application.jst.hamlc", "#{file_path}/templates/layouts/application.jst.hamlc"
29
+
30
+ empty_directory "#{file_path}/templates/pages/welcome"
31
+ template "app/templates/pages/welcome/index.jst.hamlc", "#{file_path}/templates/pages/welcome/index.jst.hamlc"
32
+
33
+ empty_directory_with_gitkeep "#{file_path}/widgets"
34
+ empty_directory_with_gitkeep "#{file_path}/resources"
35
+
36
+ empty_directory_with_gitkeep "#{file_path}/templates/layouts"
37
+ empty_directory_with_gitkeep "#{file_path}/templates/widgets"
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,30 @@
1
+ require 'rails/generators/named_base'
2
+
3
+ module Rails
4
+ module Generators
5
+ class JoosyBase < ::Rails::Generators::NamedBase
6
+ class_option :template_kind, :type => :string, :aliases => "-T", :default => 'hamlc',
7
+ :desc => "Generate templates with specified extension (default: .hamlc)"
8
+
9
+ class_option :skip_git, :type => :boolean, :aliases => "-G", :default => false,
10
+ :desc => "Skip Git keeps"
11
+
12
+
13
+ def create_files
14
+ self.destination_root = "app/assets/javascripts"
15
+ end
16
+
17
+ protected
18
+
19
+ # From https://github.com/rails/rails/blob/master/railties/lib/rails/generators/app_base.rb
20
+ def empty_directory_with_gitkeep(destination, config = {})
21
+ empty_directory(destination, config)
22
+ git_keep(destination)
23
+ end
24
+
25
+ def git_keep(destination)
26
+ create_file("#{destination}/.gitkeep") unless options[:skip_git]
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,32 @@
1
+ require 'rails/generators/joosy/joosy_base'
2
+
3
+ module Joosy
4
+ module Generators
5
+ class LayoutGenerator < ::Rails::Generators::JoosyBase
6
+ source_root File.join(File.dirname(__FILE__), 'templates')
7
+
8
+ def create_files
9
+ super
10
+
11
+ empty_directory "#{app_path}/layouts"
12
+ template "app/layouts/template.js.coffee", "#{app_path}/layouts/#{file_name}.js.coffee"
13
+
14
+ empty_directory "#{app_path}/templates/layouts"
15
+ create_file("#{app_path}/templates/layouts/#{file_name}.jst.#{options[:template_kind]}")
16
+ end
17
+
18
+ protected
19
+
20
+ def app_path
21
+ unless class_path.size == 1
22
+ puts <<HELP
23
+ Usage: rails generate joosy:layout joosy_app_name/layout_name
24
+ Tip: do not add Layout suffix to layout_name
25
+ HELP
26
+ exit 1
27
+ end
28
+ class_path[0]
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,44 @@
1
+ require 'rails/generators/joosy/joosy_base'
2
+
3
+ module Joosy
4
+ module Generators
5
+ class PageGenerator < ::Rails::Generators::JoosyBase
6
+ source_root File.join(File.dirname(__FILE__), 'templates')
7
+
8
+ def create_files
9
+ super
10
+
11
+ empty_directory "#{app_path}/pages/#{namespace_path}"
12
+ template "app/pages/template.js.coffee", "#{app_path}/pages/#{namespace_path}/#{file_name}.js.coffee"
13
+
14
+ empty_directory "#{app_path}/templates/pages/#{namespace_path}"
15
+ create_file "#{app_path}/templates/pages/#{namespace_path}/#{file_name}.jst.#{options[:template_kind]}"
16
+ end
17
+
18
+ protected
19
+
20
+ def app_path
21
+ if class_path.size < 2
22
+ puts <<HELP
23
+ Usage: rails generate joosy:page joosy_app_name/page_namespace/page_name
24
+ Tip: do not add Page suffix to page_name
25
+ HELP
26
+ exit 1
27
+ end
28
+ class_path[0]
29
+ end
30
+
31
+ def namespace_path
32
+ File.join class_path[1..-1]
33
+ end
34
+
35
+ def namespace_name
36
+ class_path[1..-1].map(&:camelize).join '.'
37
+ end
38
+
39
+ def layout_name
40
+ class_path[1]
41
+ end
42
+ end
43
+ end
44
+ end