modular 0.2.1 → 0.2.2

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 (76) hide show
  1. data/.gitignore +1 -0
  2. data/Gemfile +1 -0
  3. data/lib/modular.rb +3 -14
  4. data/lib/modular/action_controller_extension.rb +16 -7
  5. data/lib/modular/components.rb +7 -4
  6. data/lib/modular/components/base.rb +75 -5
  7. data/lib/modular/components/container.rb +37 -11
  8. data/lib/modular/configuration.rb +8 -0
  9. data/lib/modular/creation.rb +20 -13
  10. data/lib/{generators → modular/generators}/component/USAGE +0 -0
  11. data/lib/modular/generators/component/component_generator.rb +18 -0
  12. data/lib/{generators → modular/generators}/component/templates/component.rb.erb +0 -0
  13. data/lib/{generators → modular/generators}/component/templates/template.erb +0 -0
  14. data/lib/modular/mst_rendering.rb +10 -0
  15. data/lib/modular/railtie.rb +4 -0
  16. data/lib/modular/rendering.rb +1 -42
  17. data/lib/modular/version.rb +1 -1
  18. data/spec/components/{base.rb → base_spec.rb} +12 -6
  19. data/spec/components/container_spec.rb +27 -0
  20. data/spec/components/{hello_world.rb → hello_world_spec.rb} +0 -0
  21. data/spec/components/{helpers_example.rb → helpers_example_spec.rb} +0 -0
  22. data/spec/components/spec/internal/log/test.log +0 -0
  23. data/spec/controllers/callback_layout_controller_spec.rb +4 -0
  24. data/spec/controllers/rendering_spec.rb +33 -0
  25. data/spec/internal/app/components/mustache_container.rb +5 -0
  26. data/spec/internal/app/components/mustached.rb +5 -0
  27. data/spec/internal/app/controllers/callback_layout_controller.rb +5 -5
  28. data/spec/internal/app/controllers/example_controller.rb +9 -1
  29. data/spec/internal/app/views/components/mustache_container.mst +3 -0
  30. data/spec/internal/app/views/components/mustached.mst +1 -0
  31. data/spec/internal/app/views/example/mustache.html.erb +1 -0
  32. data/spec/internal/app/views/example/mustache_nested.html.erb +1 -0
  33. data/spec/internal/config/initializers/modular.rb +11 -6
  34. data/spec/modular/configuration_spec.rb +6 -6
  35. data/spec/modular/creation_spec.rb +36 -5
  36. data/spec/modular/validation_spec.rb +115 -0
  37. data/templates/components/container.html.erb +7 -0
  38. data/templates/layout.erb +1 -3
  39. metadata +23 -47
  40. data/lib/generators/component/component_generator.rb +0 -16
  41. data/lib/modular/helpers.rb +0 -74
  42. data/modular-app/Gemfile +0 -20
  43. data/modular-app/Rakefile +0 -7
  44. data/modular-app/config.ru +0 -4
  45. data/modular-app/config/application.rb +0 -42
  46. data/modular-app/config/boot.rb +0 -6
  47. data/modular-app/config/database.yml +0 -22
  48. data/modular-app/config/environment.rb +0 -5
  49. data/modular-app/config/environments/development.rb +0 -26
  50. data/modular-app/config/environments/production.rb +0 -49
  51. data/modular-app/config/environments/test.rb +0 -35
  52. data/modular-app/config/initializers/backtrace_silencers.rb +0 -7
  53. data/modular-app/config/initializers/inflections.rb +0 -10
  54. data/modular-app/config/initializers/mime_types.rb +0 -5
  55. data/modular-app/config/initializers/secret_token.rb +0 -7
  56. data/modular-app/config/initializers/session_store.rb +0 -8
  57. data/modular-app/config/locales/en.yml +0 -5
  58. data/modular-app/config/routes.rb +0 -7
  59. data/modular-app/db/migrate/20110721090602_create_simple_models.rb +0 -12
  60. data/modular-app/db/schema.rb +0 -20
  61. data/modular-app/db/seeds.rb +0 -7
  62. data/modular-app/script/rails +0 -6
  63. data/modular-app/spec/spec_helper.rb +0 -27
  64. data/spec/components/container.rb +0 -34
  65. data/spec/components/validated.rb +0 -15
  66. data/spec/controllers/example_controller_spec.rb +0 -12
  67. data/spec/controllers/indirect_render_controller_spec.rb +0 -13
  68. data/spec/internal/app/components/heavy_task.rb +0 -8
  69. data/spec/internal/app/controllers/indirect_render_controller.rb +0 -7
  70. data/spec/internal/app/views/components/container.html.erb +0 -7
  71. data/spec/internal/app/views/components/heavy_task.html.erb +0 -1
  72. data/spec/internal/tmp/modular/cached_for_time.html.erb +0 -14
  73. data/spec/internal/tmp/modular/cached_forever.html.erb +0 -12
  74. data/spec/internal/tmp/modular/heavy.html.erb +0 -19
  75. data/spec/internal/tmp/modular/nested.html.erb +0 -28
  76. data/spec/views/indirect_render/index.html.erb_spec.rb +0 -4
data/.gitignore CHANGED
@@ -2,3 +2,4 @@
2
2
  /spec/internal/db/combustion_test.sqlite
3
3
  /pkg/
4
4
  Gemfile.lock
5
+ /spec/internal/tmp
data/Gemfile CHANGED
@@ -16,3 +16,4 @@ gem 'memcache-client'
16
16
  gem 'pry'
17
17
  gem 'pry-nav'
18
18
  gem 'webrat'
19
+ gem 'mustache'
data/lib/modular.rb CHANGED
@@ -6,24 +6,14 @@ module Modular
6
6
  eager_autoload do
7
7
  autoload :Creation
8
8
  autoload :Configuration
9
+ autoload :Components
9
10
  autoload :LayoutGenerator
10
- autoload :Helpers
11
+ autoload :MstRendering
11
12
  end
12
13
 
13
14
  delegate :create, :from_json, :to => Creation
14
15
  delegate :config, :configure, :to => Configuration
15
-
16
- def layout(id)
17
- if Configuration.config.layouts.has_key?(id)
18
- Configuration.config.layouts[id]
19
- else
20
- raise "Layout '#{id}' not found"
21
- end
22
- end
23
-
24
- def layouts
25
- Configuration.config.layouts
26
- end
16
+ delegate :layout, :layouts, :to => :config
27
17
 
28
18
  def generate_rails_layout(id, params = {})
29
19
  LayoutGenerator.generate(id, params)
@@ -32,6 +22,5 @@ module Modular
32
22
  extend self
33
23
  end
34
24
 
35
- require "modular/components"
36
25
  require "modular/version"
37
26
  require 'modular/railtie'
@@ -1,17 +1,26 @@
1
1
  module Modular::ActionControllerExtension
2
2
  extend ActiveSupport::Concern
3
3
 
4
- def render_modular_layout(name)
5
- layout = Modular.layout name
6
- render :text => layout.render
4
+ def modular_layout(name)
5
+ render :layout => get_layout_path(name)
6
+ end
7
+
8
+ def get_layout_path(name)
9
+ if name.is_a?(Symbol)
10
+
11
+ name = self.__send__(name)
12
+ end
13
+
14
+ path = '../../../' + Modular.generate_rails_layout(name)
15
+ #cutting off '.html.erb'
16
+ path[0, path.length-9]
7
17
  end
8
18
 
9
19
  module ClassMethods
10
- def modular_layout(name, params = {})
20
+ def modular_layout(name)
11
21
  proc = Proc.new do |controller|
12
- path = '../../../' + Modular.generate_rails_layout(name.is_a?(Symbol) ? controller.__send__(name) : name, params)
13
- #cutting off '.html.erb'
14
- path[0, path.length-9]
22
+
23
+ controller.send(:get_layout_path, name)
15
24
  end
16
25
 
17
26
  layout proc
@@ -1,6 +1,9 @@
1
1
  module Modular::Components
2
- end
2
+ extend ActiveSupport::Autoload
3
3
 
4
- require "modular/components/base"
5
- require "modular/components/container"
6
- require "modular/components/main_content"
4
+ eager_autoload do
5
+ autoload :Base
6
+ autoload :Container
7
+ autoload :MainContent
8
+ end
9
+ end
@@ -1,32 +1,102 @@
1
1
  require 'abstract_controller'
2
2
  require "modular/rendering"
3
3
  require "modular/caching"
4
+ require 'active_model'
4
5
 
5
6
  module Modular
6
7
  module Components
7
- class Base < Modular::Helpers::AbstractModel
8
+ class Base < AbstractController::Base
8
9
  #rendering
9
10
  include AbstractController::Rendering
10
11
  include AbstractController::Helpers
11
12
  include Modular::Rendering
12
13
 
13
- def self.abstract?
14
- true
15
- end
14
+ abstract!
16
15
 
17
16
  #slug
18
17
  def self.type
19
- self.name.rpartition("::").last
18
+ self.name.demodulize.underscore
20
19
  end
21
20
 
22
21
  def type
23
22
  self.class.type
24
23
  end
25
24
 
25
+ def self.use_mustached_template!
26
+ require 'mustache'
27
+ self.class_eval do
28
+ include Modular::MstRendering
29
+ end
30
+ end
31
+
32
+ include ActiveModel::Validations
33
+ include ActiveModel::Conversion
34
+ extend ActiveModel::Naming
35
+
36
+ def self.attr_reader(*fields)
37
+ fields.each do |field|
38
+ class_eval <<EOF
39
+ def #{field}
40
+ @attributes['#{field}']
41
+ end
42
+ EOF
43
+ end
44
+ end
45
+
46
+ def self.attr_writer(*fields)
47
+ fields.each do |field|
48
+ class_eval <<EOF
49
+ def #{field}=(value)
50
+ @attributes['#{field}']=value
51
+ end
52
+ EOF
53
+ end
54
+ end
55
+
56
+ def self.attr_accessor(*fields)
57
+ fields.each do |field|
58
+ attr_writer field
59
+ attr_reader field
60
+ end
61
+ end
62
+
26
63
  #params for element itself
27
64
  attr_accessor :title
65
+ attr_accessor :uniqid
66
+ attr_accessor :width
28
67
 
29
68
  validates :title, :length => {:maximum => 64}
69
+
70
+ def initialize(attributes = {})
71
+ append_view_path(Rails.root.join('app', 'views'))
72
+ append_view_path(Gem.loaded_specs['modular'].full_gem_path + '/templates')
73
+
74
+ @attributes ||= ActiveSupport::HashWithIndifferentAccess.new
75
+
76
+ @attributes[:uniqid] = ''
77
+ @attributes[:width] = 0
78
+
79
+ attributes.each do |name, value|
80
+ @attributes[name.to_s] = value
81
+ end
82
+ end
83
+
84
+ def persisted?
85
+ false
86
+ end
87
+
88
+ def to_hash
89
+ @attributes.merge({:type => type})
90
+ end
91
+
92
+ def to_json
93
+ ActiveSupport::JSON.encode to_hash
94
+ end
95
+
96
+ def all_errors
97
+ valid? #this call is used to make validation calls
98
+ { uniqid => errors.to_a }
99
+ end
30
100
  end
31
101
  end
32
102
  end
@@ -1,30 +1,56 @@
1
1
  module Modular
2
2
  module Components
3
3
  class Container < Base
4
- attr_accessor :components
4
+ attr_accessor :children
5
5
 
6
6
  def initialize(attributes = {})
7
- @attributes = ActiveSupport::HashWithIndifferentAccess.new(:components => [])
7
+ @attributes = ActiveSupport::HashWithIndifferentAccess.new(:children => [])
8
8
  attributes = attributes.with_indifferent_access
9
- attributes["components"] ||= []
9
+ attributes["children"] ||= []
10
10
 
11
- attributes["components"].each do |value|
12
- if value.is_a? Modular::Components::Base
13
- @attributes[:components].push value
14
- else
15
- @attributes[:components].push(Modular.from_json(value)) rescue ''
16
- end
11
+ attributes["children"].each do |value|
12
+ @attributes[:children].push value if value.is_a? Modular::Components::Base
17
13
  end
18
14
 
19
- super(attributes.except("components"))
15
+ super(attributes.except("children"))
20
16
  end
21
17
 
22
18
  def add(type, args = {}, &block)
23
19
  cont = Modular.create(type, args)
24
20
  cont.instance_eval &block if block_given?
25
- components.push cont
21
+ children.push cont
22
+ end
23
+
24
+ def valid_with_children?(context = nil)
25
+ children.each do |child|
26
+ return false if child.invalid?
27
+ end
28
+
29
+ valid_with_no_children?
26
30
  end
27
31
 
32
+ alias_method :valid_with_no_children?, :valid?
33
+ alias_method :valid?, :valid_with_children?
34
+
35
+ def all_errors
36
+ if valid_with_no_children?
37
+ errs = {}
38
+ else
39
+ errs = super
40
+ end
41
+
42
+ children.each do |child|
43
+ e = child.all_errors
44
+ e.each do |key, value|
45
+ unless value.empty?
46
+ errs[key] ||= []
47
+ errs[key] += value
48
+ end
49
+ end
50
+ end
51
+
52
+ errs
53
+ end
28
54
  end
29
55
  end
30
56
  end
@@ -15,6 +15,14 @@ module Modular
15
15
  instance.instance_eval &block if block_given?
16
16
  instance
17
17
  end
18
+
19
+ def layout(id)
20
+ if layouts.has_key?(id)
21
+ layouts[id]
22
+ else
23
+ raise "Layout '#{id}' not found"
24
+ end
25
+ end
18
26
 
19
27
  def register_layout(layout, mod = :container, params = {}, &block)
20
28
  @layouts ||= Hash.new.with_indifferent_access
@@ -4,25 +4,32 @@ module Modular
4
4
  return typ if typ.is_a? Modular::Components::Base
5
5
 
6
6
  begin
7
- begin
8
- component = typ.to_s.camelize.constantize.new params
9
- rescue NameError
10
- component = (Components.name + '::' + typ.to_s.camelize).constantize.new params
11
- end
12
- rescue Exception => e
13
- raise "Unable to create element " + typ.to_s
7
+ component = typ.to_s.camelize.constantize.new params
8
+ rescue NameError
9
+ component = (Components.name + '::' + typ.to_s.camelize).constantize.new params
14
10
  end
15
-
16
- raise "Component has errors: " + component.errors.to_s if component.invalid?
17
11
 
18
12
  component
19
13
  end
20
14
 
21
- def from_json(text)
22
- obj = ActiveSupport::JSON.decode text
15
+ def from_json(obj)
16
+ obj = ActiveSupport::JSON.decode obj if obj.is_a? String
17
+ obj = obj.with_indifferent_access
18
+
23
19
  raise "Type expected in json string" unless obj['type']
24
- create(obj['type'], obj.except('type'))
25
- end
20
+ component = create(obj['type'], obj.except('type').except("children"))
21
+
22
+ if obj.has_key?('children') && component.is_a?(Modular::Components::Container)
23
+ obj['children'].each do |child|
24
+ if child.is_a? Hash
25
+ child_component = from_json(child)
26
+ component.add(child_component)
27
+ end
28
+ end
29
+ end
30
+
31
+ component
32
+ end
26
33
 
27
34
  extend self
28
35
  end
@@ -0,0 +1,18 @@
1
+ module Modular
2
+ class ComponentGenerator < Rails::Generators::NamedBase
3
+ source_root File.expand_path('../templates', __FILE__)
4
+
5
+ def generate_template
6
+ template "component.rb.erb", "app/components/#{filename}.rb"
7
+ end
8
+
9
+ def generate_controller
10
+ template "template.erb", "app/views/components/#{filename}.html.erb"
11
+ end
12
+
13
+ private
14
+ def filename
15
+ name.underscore
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ module Modular
2
+ module MstRendering
3
+ def render
4
+ path = Rails.root + "app/views/components/#{type}.mst"
5
+ template = File.open(path, "rb").read
6
+
7
+ Mustache.render(template, @attributes).html_safe
8
+ end
9
+ end
10
+ end
@@ -7,5 +7,9 @@ module TaggableCache
7
7
  ::ActionController::Base.__send__ :include, Modular::ActionControllerExtension
8
8
  end
9
9
  end
10
+
11
+ generators do
12
+ require "modular/generators/component/component_generator"
13
+ end
10
14
  end
11
15
  end
@@ -1,59 +1,18 @@
1
1
  module Modular::Rendering
2
2
  extend ActiveSupport::Concern
3
3
 
4
- def controller_path
5
- 'components'
6
- end
7
-
8
4
  def action_name
9
5
  type.underscore
10
6
  end
11
-
12
- # def config
13
- # ActionController::Base.config
14
- # end
15
7
 
16
8
  def execute
17
9
  end
18
-
10
+
19
11
  def render
20
12
  execute
21
13
  modular_render :render_type => :indirect
22
14
  end
23
15
 
24
- # configure the different paths correctly
25
- def initialize(*args)
26
- super()
27
- lookup_context.view_paths = Rails.root.join('app', 'views')
28
- config.javascripts_dir = Rails.root.join('public', 'javascripts')
29
- config.stylesheets_dir = Rails.root.join('public', 'stylesheets')
30
- config.assets_dir = Rails.root.join('public')
31
- end
32
-
33
- # we are not in a browser, no need for this
34
- def protect_against_forgery?
35
- false
36
- end
37
-
38
- # so that your flash calls still work
39
- def flash
40
- {}
41
- end
42
-
43
- def params
44
- {}
45
- end
46
-
47
- # # same asset host as the controllers
48
- # self.asset_host = ActionController::Base.asset_host
49
-
50
- def initialize(attributes = {})
51
- append_view_path(Rails.root.join('app', 'views'))
52
- append_view_path(Gem.loaded_specs['modular'].full_gem_path + '/templates')
53
-
54
- super
55
- end
56
-
57
16
  protected
58
17
  def modular_render(args = {})
59
18
  render_to_string :file => 'components/' + action_name, :locals => args