modular 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data/Gemfile +4 -0
  2. data/README +0 -0
  3. data/Rakefile +2 -0
  4. data/TODO +2 -0
  5. data/autotest/discover.rb +12 -0
  6. data/lib/generators/component/USAGE +9 -0
  7. data/lib/generators/component/component_generator.rb +16 -0
  8. data/lib/generators/component/templates/component.rb.erb +6 -0
  9. data/lib/generators/component/templates/template.erb +2 -0
  10. data/lib/modular/abstract_model.rb +74 -0
  11. data/lib/modular/caching.rb +62 -0
  12. data/lib/modular/components/base.rb +29 -0
  13. data/lib/modular/components/container.rb +39 -0
  14. data/lib/modular/components/main_content.rb +9 -0
  15. data/lib/modular/configuration.rb +31 -0
  16. data/lib/modular/layout_generator.rb +66 -0
  17. data/lib/modular/rails.rb +16 -0
  18. data/lib/modular/rendering.rb +72 -0
  19. data/lib/modular/version.rb +3 -0
  20. data/lib/modular.rb +57 -0
  21. data/modular-app/Gemfile +20 -0
  22. data/modular-app/Rakefile +7 -0
  23. data/modular-app/app/components/cached_for_time.rb +10 -0
  24. data/modular-app/app/components/cached_forever.rb +10 -0
  25. data/modular-app/app/components/fake_news_feed.rb +9 -0
  26. data/modular-app/app/components/foobar.rb +7 -0
  27. data/modular-app/app/components/heavy_task.rb +5 -0
  28. data/modular-app/app/components/validated.rb +10 -0
  29. data/modular-app/app/components/vertical.rb +4 -0
  30. data/modular-app/app/controllers/application_controller.rb +3 -0
  31. data/modular-app/app/controllers/cached_for_time_controller.rb +7 -0
  32. data/modular-app/app/controllers/cached_forever_controller.rb +6 -0
  33. data/modular-app/app/controllers/callback_layout_controller.rb +11 -0
  34. data/modular-app/app/controllers/example_controller.rb +5 -0
  35. data/modular-app/app/controllers/indirect_render_controller.rb +7 -0
  36. data/modular-app/app/controllers/layout_test_controller.rb +6 -0
  37. data/modular-app/app/helpers/application_helper.rb +2 -0
  38. data/modular-app/app/helpers/callback_layout_helper.rb +2 -0
  39. data/modular-app/app/helpers/example_helper.rb +2 -0
  40. data/modular-app/app/helpers/indirect_render_helper.rb +2 -0
  41. data/modular-app/app/models/simple_model.rb +14 -0
  42. data/modular-app/app/views/cached_for_time/index.html.erb +2 -0
  43. data/modular-app/app/views/cached_forever/index.html.erb +0 -0
  44. data/modular-app/app/views/callback_layout/index.html.erb +2 -0
  45. data/modular-app/app/views/components/cached_for_time.html.erb +2 -0
  46. data/modular-app/app/views/components/cached_forever.html.erb +2 -0
  47. data/modular-app/app/views/components/container.html.erb +7 -0
  48. data/modular-app/app/views/components/fake_news_feed.html.erb +1 -0
  49. data/modular-app/app/views/components/foobar.html.erb +4 -0
  50. data/modular-app/app/views/components/heavy_task.html.erb +1 -0
  51. data/modular-app/app/views/components/validated.html.erb +2 -0
  52. data/modular-app/app/views/components/vertical.html.erb +2 -0
  53. data/modular-app/app/views/example/index.html.erb +2 -0
  54. data/modular-app/app/views/indirect_render/index.html.erb +2 -0
  55. data/modular-app/app/views/layout_test/index.html.erb +1 -0
  56. data/modular-app/app/views/layouts/application.html.erb +16 -0
  57. data/modular-app/config/application.rb +42 -0
  58. data/modular-app/config/boot.rb +6 -0
  59. data/modular-app/config/database.yml +22 -0
  60. data/modular-app/config/environment.rb +5 -0
  61. data/modular-app/config/environments/development.rb +26 -0
  62. data/modular-app/config/environments/production.rb +49 -0
  63. data/modular-app/config/environments/test.rb +35 -0
  64. data/modular-app/config/initializers/backtrace_silencers.rb +7 -0
  65. data/modular-app/config/initializers/inflections.rb +10 -0
  66. data/modular-app/config/initializers/mime_types.rb +5 -0
  67. data/modular-app/config/initializers/modular.rb +20 -0
  68. data/modular-app/config/initializers/secret_token.rb +7 -0
  69. data/modular-app/config/initializers/session_store.rb +8 -0
  70. data/modular-app/config/locales/en.yml +5 -0
  71. data/modular-app/config/routes.rb +7 -0
  72. data/modular-app/config.ru +4 -0
  73. data/modular-app/db/migrate/20110721090602_create_simple_models.rb +12 -0
  74. data/modular-app/db/schema.rb +20 -0
  75. data/modular-app/db/seeds.rb +7 -0
  76. data/modular-app/script/rails +6 -0
  77. data/modular-app/spec/components/base.rb +33 -0
  78. data/modular-app/spec/components/container.rb +34 -0
  79. data/modular-app/spec/components/validated.rb +15 -0
  80. data/modular-app/spec/controllers/cached_for_time_controller_spec.rb +20 -0
  81. data/modular-app/spec/controllers/cached_forever_controller_spec.rb +17 -0
  82. data/modular-app/spec/controllers/callback_layout_controller_spec.rb +12 -0
  83. data/modular-app/spec/controllers/example_controller_spec.rb +12 -0
  84. data/modular-app/spec/controllers/indirect_render_controller_spec.rb +13 -0
  85. data/modular-app/spec/controllers/layout_test_controller_spec.rb +38 -0
  86. data/modular-app/spec/helpers/indirect_render_helper_spec.rb +14 -0
  87. data/modular-app/spec/spec_helper.rb +27 -0
  88. data/modular-app/spec/views/indirect_render/index.html.erb_spec.rb +4 -0
  89. data/modular.gemspec +25 -0
  90. data/spec/base.rb +37 -0
  91. data/spec/configuration.rb +74 -0
  92. data/spec/spec_helper.rb +7 -0
  93. data/templates/layout.erb +17 -0
  94. metadata +202 -0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in modular.gemspec
4
+ gemspec
data/README ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/TODO ADDED
@@ -0,0 +1,2 @@
1
+ * Fix autotest discovery to use one autotest, not two separate
2
+ * Use custom context
@@ -0,0 +1,12 @@
1
+ Autotest.add_discovery { "rspec2" }
2
+
3
+ Autotest.add_hook :initialize do |at|
4
+ at.add_mapping(%r%^spec/.*\.rb$%) { |filename, _|
5
+
6
+ filename
7
+ }
8
+
9
+ %w{.git .svn .hg .DS_Store ._* spec/helpers spec/testdata}.each do |exception|
10
+ at.add_exception(exception)
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ Description:
2
+ Creates modular component.
3
+
4
+ Example:
5
+ rails generate component Thing
6
+
7
+ This will create:
8
+ Component: app/components/thing.rb
9
+ View: app/views/components/thing.html.erb
@@ -0,0 +1,16 @@
1
+ class ComponentGenerator < Rails::Generators::NamedBase
2
+ source_root File.expand_path('../templates', __FILE__)
3
+
4
+ def generate_template
5
+ template "component.rb.erb", "app/components/#{filename}.rb"
6
+ end
7
+
8
+ def generate_controller
9
+ template "template.erb", "app/views/components/#{filename}.html.erb"
10
+ end
11
+
12
+ private
13
+ def filename
14
+ name.underscore
15
+ end
16
+ end
@@ -0,0 +1,6 @@
1
+ class Modular::Components::<%=filename.camelize%> < Modular::Components::Base
2
+ def execute
3
+ end
4
+ end
5
+
6
+ <%=filename.camelize%> = Modular::Components::<%=filename.camelize%>
@@ -0,0 +1,2 @@
1
+ <h3>Template for <%=filename.camelize%></h3>
2
+
@@ -0,0 +1,74 @@
1
+ require 'active_model'
2
+
3
+ module Modular
4
+ module Helpers
5
+ class AbstractModel
6
+ include ActiveModel::Validations
7
+ include ActiveModel::Conversion
8
+ extend ActiveModel::Naming
9
+
10
+ def initialize(attributes = {})
11
+ @attributes ||= ActiveSupport::HashWithIndifferentAccess.new
12
+
13
+ attributes.each do |name, value|
14
+ @attributes[name.to_s] = value
15
+ end
16
+ end
17
+
18
+ def persisted?
19
+ false
20
+ end
21
+
22
+ def to_json
23
+ ActiveSupport::JSON.encode @attributes.merge({:type => type})
24
+ end
25
+
26
+ def self.attr_reader(*fields)
27
+ fields.each do |field|
28
+ class_eval <<EOF
29
+ def #{field}
30
+ @attributes['#{field}']
31
+ end
32
+ EOF
33
+ end
34
+ end
35
+
36
+ def self.attr_writer(*fields)
37
+ fields.each do |field|
38
+ class_eval <<EOF
39
+ def #{field}=(value)
40
+ @attributes['#{field}']=value
41
+ end
42
+ EOF
43
+ end
44
+ end
45
+
46
+ def self.attr_accessor(*fields)
47
+ fields.each do |field|
48
+ attr_writer field
49
+ attr_reader field
50
+ end
51
+ end
52
+
53
+ def self.attr_accessor_with_default(sym, default = Proc.new)
54
+ define_method(sym, block_given? ? default : Proc.new { default })
55
+ module_eval(<<-EVAL, __FILE__, __LINE__ + 1)
56
+ def #{sym}=(value) # def age=(value)
57
+ class << self; attr_accessor :#{sym} end # class << self; attr_accessor :age end
58
+ @attributes['#{sym}']=value # @attributes['age'] = value
59
+ end # end
60
+ EVAL
61
+ end
62
+
63
+ def self.attr_reader_with_default(sym, default = Proc.new)
64
+ define_method(sym, block_given? ? default : Proc.new { default })
65
+ module_eval(<<-EVAL, __FILE__, __LINE__ + 1)
66
+ def #{sym}=(value) # def age=(value)
67
+ class << self; attr_reader :#{sym} end # class << self; attr_accessor :age end
68
+ @attributes['#{sym}']=value # @attributes['age'] = value
69
+ end # end
70
+ EVAL
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,62 @@
1
+ module Modular
2
+ module Components
3
+ module Caching
4
+ def self.included(base)
5
+ base.cattr_accessor :cache_options
6
+
7
+ base.class_eval do
8
+ def self.cache(*args, &block)
9
+ self.cache_options = args.extract_options!
10
+ self.cache_options[:cache_key] = block if block_given?
11
+ end
12
+ end
13
+ end
14
+
15
+ def render
16
+ if cache_options.nil?
17
+ super
18
+ elsif cached?
19
+ get_cached
20
+ else
21
+ data = super
22
+ do_caching data
23
+ data
24
+ end
25
+ end
26
+
27
+ def cache_store
28
+ ::ActionController::Base.cache_store
29
+ end
30
+
31
+ def cache_options
32
+ self.class.cache_options
33
+ end
34
+
35
+ def clear_cache
36
+ cache_store.delete cache_key
37
+ end
38
+
39
+ protected
40
+ def cache_key
41
+ key = cache_options[:cache_key]
42
+ key = key.call(self) if key.is_a? Proc
43
+ key = self.to_json if key.nil?
44
+
45
+ ::ActiveSupport::Cache.expand_cache_key key, :modular
46
+ end
47
+
48
+ def cached?
49
+ cache_store.exist? cache_key
50
+ end
51
+
52
+ def get_cached
53
+ cache_store.read cache_key
54
+ end
55
+
56
+ def do_caching(data)
57
+ cache_store.write cache_key, data, cache_options
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,29 @@
1
+ require 'abstract_controller'
2
+ require "modular/abstract_model"
3
+ require "modular/rendering"
4
+ require "modular/caching"
5
+
6
+ module Modular
7
+ module Components
8
+ class Base < Modular::Helpers::AbstractModel
9
+ #rendering
10
+ include AbstractController::Rendering
11
+ include Modular::Components::DirectRender
12
+
13
+ #slug
14
+ def self.type
15
+ self.name.rpartition("::").last
16
+ end
17
+
18
+ def type
19
+ self.class.type
20
+ end
21
+
22
+ #params for element itself
23
+ attr_reader_with_default :width, 300
24
+ attr_reader :title
25
+
26
+ validates :title, :length => {:maximum => 64}
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,39 @@
1
+ module Modular
2
+ module Components
3
+ class Container < Base
4
+ include Modular::Components::IndirectRender
5
+
6
+ attr_accessor :components
7
+
8
+ def initialize(attributes = {})
9
+ @attributes = ActiveSupport::HashWithIndifferentAccess.new(:components => [])
10
+ attributes = attributes.with_indifferent_access
11
+ attributes["components"] ||= []
12
+
13
+ attributes["components"].each do |value|
14
+ if value.is_a? Modular::Components::Base
15
+ @attributes[:components].push value
16
+ else
17
+ @attributes[:components].push(Modular.from_json(value)) rescue ''
18
+ end
19
+ end
20
+
21
+ super(attributes.except("components"))
22
+ end
23
+
24
+ def add(type, args = {}, &block)
25
+ cont = Modular.create(type, args)
26
+ cont.instance_eval &block if block_given?
27
+ components.push cont
28
+ end
29
+
30
+ # def render_child(component, render_type)
31
+ # if component.is_a?(Modular::Components::IndirectRender)&&(render_type == :indirect)
32
+ # component.indirect_render.html_safe
33
+ # else
34
+ # ("<%= Modular.from_json('" + component.to_json.html_safe + "').render %>").html_safe
35
+ # end
36
+ # end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,9 @@
1
+ class Modular::Components::MainContent < Modular::Components::Base
2
+ include Modular::Components::IndirectRender
3
+
4
+ def indirect_render(args = {})
5
+ '<%=yield%>'.html_safe
6
+ end
7
+ end
8
+
9
+ MainContent = Modular::Components::MainContent
@@ -0,0 +1,31 @@
1
+ module Modular
2
+ class Configuration
3
+ attr_accessor_with_default :columns, 12
4
+ attr_accessor_with_default :column_width, 68
5
+ attr_accessor_with_default :padding_width, 15
6
+ attr_reader :layouts
7
+
8
+ def self.config
9
+ @@config ||= new
10
+ end
11
+
12
+ def self.configure(&block)
13
+ @@config = new
14
+ @@config.instance_eval &block if block_given?
15
+ @@config
16
+ end
17
+
18
+ def register_layout(layout, mod = :Container, params = {}, &block)
19
+ @layouts ||= {}.with_indifferent_access
20
+
21
+ if mod.is_a? Components::Base
22
+ @layouts[layout.to_s] = mod
23
+ else
24
+ root_layout = Modular.create mod, params
25
+ root_layout.instance_eval &block if block_given?
26
+ @layouts[layout.to_s] = root_layout
27
+ end
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,66 @@
1
+ require 'erb'
2
+
3
+ module Modular
4
+ class LayoutGenerator
5
+ class ERBContext
6
+ def initialize(hash)
7
+ hash.each_pair do |key, value|
8
+ instance_variable_set('@' + key.to_s, value)
9
+ end
10
+ end
11
+
12
+ def get_binding
13
+ binding
14
+ end
15
+ end
16
+
17
+ def self.generate(id, params = {})
18
+ new(id, params).generate
19
+ end
20
+
21
+ def generate
22
+ write_layout unless layout_exists?
23
+ filename.to_s
24
+ end
25
+
26
+ def initialize(id, params)
27
+ @id = id
28
+ @params = params
29
+ end
30
+
31
+ protected
32
+ def foldername
33
+ 'tmp/modular/'
34
+ end
35
+
36
+ def filename
37
+ foldername + (@id.to_s + (@params[:cache_key].to_s) + '.html.erb')
38
+ end
39
+
40
+ def layout_exists?
41
+ if (defined? Rails) && (Rails.configuration.action_controller.perform_caching)
42
+ File.exists?(filename)
43
+ else
44
+ false
45
+ end
46
+ end
47
+
48
+ def write_layout
49
+ folder = self.foldername
50
+ filename = self.filename
51
+
52
+ Dir.mkdir(folder) unless File.exists? folder
53
+
54
+ template = ERB.new File.new(Gem.loaded_specs['modular'].full_gem_path + '/templates/layout.erb').read
55
+ output = template.result(ERBContext.new(template_variables).get_binding)
56
+
57
+ File.open(filename, 'w') do |f|
58
+ f.write(output)
59
+ end
60
+ end
61
+
62
+ def template_variables
63
+ @params.merge :layout_id => @id
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,16 @@
1
+ require 'action_controller'
2
+
3
+ class ActionController::Base
4
+ def render_modular_layout(name)
5
+ layout = Modular.layout name
6
+ render :text => layout.render
7
+ end
8
+
9
+ def self.modular_layout(name, params = {})
10
+ proc = Proc.new do |controller|
11
+ '../../../' + Modular.generate_rails_layout(name.is_a?(Symbol) ? controller.__send__(name) : name, params)
12
+ end
13
+
14
+ layout proc
15
+ end
16
+ end
@@ -0,0 +1,72 @@
1
+ module Modular
2
+ module Components
3
+ module DirectRender
4
+ extend ActiveSupport::Concern
5
+
6
+ module InstanceMethods
7
+
8
+ def controller_path
9
+ 'components'
10
+ end
11
+
12
+ def action_name
13
+ type.underscore
14
+ end
15
+
16
+ def execute
17
+ end
18
+
19
+ def render
20
+ execute
21
+ modular_render :render_type => :direct
22
+ end
23
+
24
+ def initialize(attributes = {})
25
+ append_view_path File.join('app', 'views')
26
+ super
27
+ end
28
+
29
+ protected
30
+ def modular_render(args = {})
31
+ render_to_string :file => 'components/' + action_name, :locals => args
32
+ end
33
+ end
34
+
35
+
36
+ module ClassMethods
37
+ def view_context_class
38
+ context = super
39
+
40
+ context.send :define_method, :render_component do |component|
41
+ if component.is_a?(Modular::Components::IndirectRender)
42
+ component.indirect_render
43
+ else
44
+ a = "<%= Modular.from_json('"+ component.to_json + "').render %>"
45
+ a.html_safe
46
+ end
47
+ end
48
+ context
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ module IndirectRender
55
+ def execute
56
+ end
57
+
58
+ def indirect_render
59
+ execute
60
+ modular_render :render_type => :indirect
61
+ end
62
+
63
+ def render(args = {})
64
+ throw "Direct render unavailible for this component"
65
+ end
66
+
67
+ def self.included(base)
68
+ thow "Unable to use indirect render without direct render" unless base.ancestors.include? Modular::Components::DirectRender
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,3 @@
1
+ module Modular
2
+ VERSION = "0.1"
3
+ end
data/lib/modular.rb ADDED
@@ -0,0 +1,57 @@
1
+ require "active_support/all"
2
+
3
+ module Modular
4
+ extend ActiveSupport::Autoload
5
+
6
+ eager_autoload do
7
+ autoload :Configuration
8
+ autoload :LayoutGenerator
9
+ end
10
+
11
+ def create(typ, params = {})
12
+ return typ if typ.is_a? Components::Base
13
+
14
+ begin
15
+ begin
16
+ component = typ.to_s.camelize.constantize.new params
17
+ rescue NameError
18
+ component = (Components.name + '::' + typ.to_s.camelize).constantize.new params
19
+ end
20
+ rescue Exception => e
21
+ raise "Unable to create element " + typ.to_s
22
+ end
23
+
24
+ raise "Component has errors: " + component.errors.to_s unless component.valid?
25
+
26
+ component
27
+ end
28
+
29
+ def from_json(text)
30
+ obj = ActiveSupport::JSON.decode text
31
+ raise "Type expected in json string" unless obj['type']
32
+ create(obj['type'], obj.except('type'))
33
+ end
34
+
35
+ delegate :config, :configure, :to => Configuration
36
+
37
+ def layout(id)
38
+ Configuration.config.layouts[id]
39
+ end
40
+
41
+ def layouts
42
+ Configuration.config.layouts.keys
43
+ end
44
+
45
+ def generate_rails_layout(id, params = {})
46
+ LayoutGenerator.generate(id, params)
47
+ end
48
+
49
+ extend self
50
+ end
51
+
52
+ require "modular/components/base"
53
+ require "modular/components/container"
54
+ require "modular/components/main_content"
55
+ require "modular/version"
56
+
57
+ require "modular/rails" if defined? Rails
@@ -0,0 +1,20 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'rails'
4
+ # gem 'rails', :git => 'git://github.com/rails/rails.git'
5
+
6
+ gem 'sqlite3'
7
+ gem 'mongrel'
8
+
9
+ gem "modular", :path => ".."
10
+
11
+ group :development, :test do
12
+ gem 'autotest-standalone'
13
+ gem 'autotest-rails-pure'
14
+
15
+ gem 'rspec-rails', '~> 2.5.0'
16
+ gem 'ruby-debug'
17
+ gem 'webrat'
18
+
19
+ gem 'autotest-growl', :require => false
20
+ end
@@ -0,0 +1,7 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+ require 'rake'
6
+
7
+ ModularApp::Application.load_tasks
@@ -0,0 +1,10 @@
1
+ class Modular::Components::CachedForTime < Modular::Components::Base
2
+ include Modular::Components::Caching
3
+ cache :expires_in => 2.seconds
4
+
5
+ def execute
6
+ SimpleModel.called_by_cached_for_time
7
+ end
8
+ end
9
+
10
+ CachedForTime = Modular::Components::CachedForTime
@@ -0,0 +1,10 @@
1
+ class Modular::Components::CachedForever < Modular::Components::Base
2
+ include Modular::Components::Caching
3
+ cache
4
+
5
+ def execute
6
+ SimpleModel.called_by_cached_forever
7
+ end
8
+ end
9
+
10
+ CachedForever = Modular::Components::CachedForever
@@ -0,0 +1,9 @@
1
+ module Modular
2
+ module Components
3
+ class FakeNewsFeed < Modular::Components::Base
4
+ attr_reader :news_count
5
+ end
6
+ end
7
+ end
8
+
9
+ FakeNewsFeed = Modular::Components::FakeNewsFeed
@@ -0,0 +1,7 @@
1
+ class Foobar < Modular::Components::Base
2
+ attr_reader :text
3
+
4
+ def execute
5
+ SimpleModel.foobar_method
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ class Modular::Components::HeavyTask < Modular::Components::Base
2
+ include Modular::Components::IndirectRender
3
+ end
4
+
5
+ HeavyTask = Modular::Components::HeavyTask
@@ -0,0 +1,10 @@
1
+ class Modular::Components::Validated < Modular::Components::Base
2
+ attr_reader :non_existant_property
3
+
4
+ validates_presence_of :non_existant_property
5
+
6
+ def execute
7
+ end
8
+ end
9
+
10
+ Validated = Modular::Components::Validated
@@ -0,0 +1,4 @@
1
+ class Modular::Components::Vertical < Modular::Components::Base
2
+ end
3
+
4
+ Vertical = Modular::Components::Vertical
@@ -0,0 +1,3 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery
3
+ end
@@ -0,0 +1,7 @@
1
+ class CachedForTimeController < ApplicationController
2
+ modular_layout 'cached_for_time'
3
+
4
+ def index
5
+ end
6
+
7
+ end
@@ -0,0 +1,6 @@
1
+ class CachedForeverController < ApplicationController
2
+ modular_layout 'cached_forever'
3
+
4
+ def index
5
+ end
6
+ end
@@ -0,0 +1,11 @@
1
+ class CallbackLayoutController < ApplicationController
2
+ modular_layout :method_name
3
+
4
+ def method_name
5
+ 'heavy'
6
+ end
7
+
8
+ def index
9
+ end
10
+
11
+ end
@@ -0,0 +1,5 @@
1
+ class ExampleController < ApplicationController
2
+ def index
3
+ render_modular_layout :simple
4
+ end
5
+ end