modular 0.2.1 → 0.2.2

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