blocks 3.0.1 → 4.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +5 -5
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +61 -17
  4. data/CHANGELOG.rdoc +27 -0
  5. data/Gemfile +11 -10
  6. data/Guardfile +1 -0
  7. data/README.md +2 -0
  8. data/bin/deploy_docs +1 -1
  9. data/blocks.gemspec +3 -1
  10. data/docs/_includes/configuration.md +3 -6
  11. data/docs/_includes/defining.md +7 -7
  12. data/docs/_includes/{introduction.md → features.md} +2 -2
  13. data/docs/_includes/helper-blocks.md +5 -0
  14. data/docs/_includes/helper-blocks/content_tag.md +44 -0
  15. data/docs/_includes/installation.md +16 -2
  16. data/docs/_includes/overview.md +21 -0
  17. data/docs/_includes/templating.md +1 -1
  18. data/docs/_includes/templating/bootstrap_4_cards.md +9 -9
  19. data/docs/_layouts/slate.html +11 -9
  20. data/docs/index.md +3 -1
  21. data/gemfiles/Gemfile.rails-3-0-stable +1 -0
  22. data/gemfiles/Gemfile.rails-3-1-stable +1 -0
  23. data/gemfiles/Gemfile.rails-3-2-stable +1 -0
  24. data/gemfiles/Gemfile.rails-4-0-stable +2 -1
  25. data/gemfiles/Gemfile.rails-4-1-stable +2 -1
  26. data/gemfiles/Gemfile.rails-4-2-stable +2 -1
  27. data/gemfiles/Gemfile.rails-5-0-stable +4 -3
  28. data/gemfiles/Gemfile.rails-5-1-stable +4 -3
  29. data/gemfiles/Gemfile.rails-5-2-stable +13 -0
  30. data/lib/blocks.rb +37 -29
  31. data/lib/blocks/builders/block_definition.rb +45 -43
  32. data/lib/blocks/builders/builder.rb +96 -60
  33. data/lib/blocks/builders/hook_definition.rb +19 -4
  34. data/lib/blocks/engine.rb +14 -0
  35. data/lib/blocks/helpers/controller_extensions.rb +13 -0
  36. data/lib/blocks/helpers/haml_capture.rb +44 -0
  37. data/lib/blocks/{action_view_extensions → helpers}/view_extensions.rb +10 -4
  38. data/lib/blocks/renderers/adjacent_blocks_renderer.rb +9 -7
  39. data/lib/blocks/renderers/block_placeholder.rb +2 -0
  40. data/lib/blocks/renderers/block_renderer.rb +26 -5
  41. data/lib/blocks/renderers/block_with_hooks_renderer.rb +29 -19
  42. data/lib/blocks/renderers/collection_renderer.rb +18 -6
  43. data/lib/blocks/renderers/nesting_blocks_renderer.rb +9 -11
  44. data/lib/blocks/renderers/partial_renderer.rb +16 -14
  45. data/lib/blocks/renderers/renderer.rb +9 -24
  46. data/lib/blocks/renderers/runtime_context.rb +175 -147
  47. data/lib/blocks/renderers/wrapper_renderer.rb +21 -10
  48. data/lib/blocks/utilities/configurator.rb +30 -6
  49. data/lib/blocks/utilities/hash_with_caller.rb +36 -32
  50. data/lib/blocks/utilities/hash_with_render_strategy.rb +67 -19
  51. data/lib/blocks/utilities/options_set.rb +38 -63
  52. data/lib/blocks/version.rb +3 -1
  53. metadata +22 -21
  54. data/docs/_includes/wip.md +0 -34
  55. data/lib/blocks/experimental/builder_permissions.rb +0 -52
  56. data/lib/blocks/experimental/invalid_permissions_handler.rb +0 -27
  57. data/lib/blocks/renderers/abstract_renderer.rb +0 -69
  58. data/lib/blocks/utilities/dynamic_configuration.rb +0 -71
@@ -1,18 +1,29 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Blocks
2
- class WrapperRenderer < AbstractRenderer
3
- def render(wrapper, runtime_context)
4
- content_block = Proc.new { with_output_buffer { yield } }
4
+ class WrapperRenderer
5
+ def self.render(wrapper, wrapper_type, runtime_context)
6
+ output_buffer = runtime_context.output_buffer
7
+
5
8
  if wrapper.nil?
6
9
  yield
10
+
7
11
  elsif wrapper.is_a?(Proc)
8
- output_buffer << capture(content_block, *(runtime_context.runtime_args), runtime_context, &wrapper)
9
- elsif block_definition = block_for(wrapper)
10
- runtime_context = runtime_context.extend_to_block_definition(block_definition)
11
- block_renderer.render(content_block, runtime_context)
12
- elsif builder.respond_to?(wrapper)
13
- output_buffer << builder.send(wrapper, runtime_context, &content_block)
12
+ output_buffer << runtime_context.capture(
13
+ Proc.new { runtime_context.with_output_buffer { yield } },
14
+ *(runtime_context.runtime_args),
15
+ runtime_context.to_hash.merge(wrapper_type: wrapper_type),
16
+ &wrapper
17
+ )
18
+
14
19
  else
15
- yield
20
+ wrapper_runtime_context = runtime_context.extend_from_definition(
21
+ wrapper,
22
+ wrapper_type: wrapper_type
23
+ ) do
24
+ runtime_context.with_output_buffer { yield }
25
+ end
26
+ output_buffer << BlockWithHooksRenderer.render(wrapper_runtime_context)
16
27
  end
17
28
  end
18
29
  end
@@ -1,14 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Blocks
2
4
  module Configurator
3
5
  extend ActiveSupport::Concern
4
6
 
5
7
  included do
6
- include DynamicConfiguration
8
+ mattr_accessor :builder_class
9
+ mattr_accessor :renderer_class
10
+ mattr_accessor :global_options
11
+ mattr_accessor :lookup_caller_location
12
+ mattr_accessor :track_caller
13
+ # TODO: add default_defintions option
14
+ # TODO: add submodules / extensions option
15
+ # TODO: add option to specify render order for nesting hooks
16
+
17
+ # Specifies whether the default options specified for a render call will take priority over ones specified as block default options
18
+ # Legacy versions of Blocks had default render options always take precedence over block-level default options
19
+ mattr_accessor :default_render_options_take_precedence_over_block_defaults
20
+
21
+ # Specifies whether a block defined with a proc will receive a collection item as its first argument when rendering collections
22
+ # Legacy versions of Blocks assumed that the collection item would be the first argument
23
+ mattr_accessor :collection_item_passed_to_block_as_first_arg
7
24
 
8
- add_config :builder_class
9
- add_config :renderer_class
10
- add_config :global_options_set
11
- add_config :lookup_caller_location, instance_predicate: true
12
25
  reset_config
13
26
  end
14
27
 
@@ -18,7 +31,18 @@ module Blocks
18
31
  config.builder_class = Builder
19
32
  config.renderer_class = Renderer
20
33
  config.lookup_caller_location = false
21
- config.global_options_set = OptionsSet.new("Global Options")
34
+ config.track_caller = false
35
+ config.global_options = nil
36
+ config.default_render_options_take_precedence_over_block_defaults = false
37
+ config.collection_item_passed_to_block_as_first_arg = false
38
+ end
39
+ end
40
+
41
+ def configure
42
+ yield self
43
+ self.track_caller = true if lookup_caller_location
44
+ if track_caller
45
+ HashWithRenderStrategy.send(:prepend, HashWithCaller)
22
46
  end
23
47
  end
24
48
  end
@@ -1,41 +1,49 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Blocks
2
- class HashWithCaller < HashWithIndifferentAccess
4
+ module HashWithCaller
3
5
  attr_accessor :callers
4
6
 
5
7
  def initialize(*args)
6
- self.callers = HashWithIndifferentAccess.new
7
- options = args.extract_options!
8
- add_options(args.first, options)
9
- super &nil
8
+ self.callers = {}
9
+ super
10
10
  end
11
11
 
12
- def to_s
13
- description = []
14
-
15
- description << "{"
16
- description << map do |key, value|
17
- value_display = case value
18
- when Symbol
19
- ":#{value}"
20
- when String
21
- "\"#{value}\""
22
- when Proc
23
- "Proc"
24
- else
25
- value
26
- end
27
- "\"#{key}\" => #{value_display}, # [#{callers[key]}]"
28
- end.join(",\n")
29
- description << "}"
30
- description.join("\n")
12
+ def initialize_copy(original)
13
+ super
14
+ self.callers = original.callers.clone
31
15
  end
32
16
 
33
- def add_options(*args)
17
+ # TODO: implement inspect
18
+
19
+ # TODO: fix and test this implementation
20
+ # def to_s
21
+ # description = []
22
+ #
23
+ # description << "{"
24
+ # description << map do |key, value|
25
+ # value_display = case value
26
+ # when Symbol
27
+ # ":#{value}"
28
+ # when String
29
+ # "\"#{value}\""
30
+ # when Proc
31
+ # "Proc"
32
+ # else
33
+ # value
34
+ # end
35
+ # "\"#{key}\" => #{value_display}, # [#{callers[key]}]"
36
+ # end.join(",\n")
37
+ # description << "}"
38
+ # description.join("\n")
39
+ # end
40
+
41
+ def reverse_merge!(*args)
34
42
  options = args.extract_options!
35
43
 
36
44
  caller_id = args.first.to_s.presence || ""
37
45
 
38
- if !options.is_a?(HashWithCaller) && Blocks.lookup_caller_location?
46
+ if !options.is_a?(HashWithCaller) && Blocks.lookup_caller_location
39
47
  caller_location = caller.detect do |c|
40
48
  !c.include?("/lib/blocks") &&
41
49
  !c.include?("/lib/ruby") &&
@@ -55,19 +63,15 @@ module Blocks
55
63
  end
56
64
 
57
65
  if !self.key?(key)
58
- self[key] = value
59
66
  callers[key] = setter
60
67
 
61
68
  elsif current_value.is_a?(Hash) && value.is_a?(Hash)
62
- self[key] = value.deep_merge(current_value)
69
+ # self[key] = value.deep_merge(current_value)
63
70
  callers[key] = "#{callers[key]}, #{setter}"
64
- # TODO: handle attribute merges here
65
71
  end
66
72
  end
67
- end
68
73
 
69
- def nested_under_indifferent_access
70
- self
74
+ super options
71
75
  end
72
76
  end
73
77
  end
@@ -1,36 +1,35 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Blocks
2
- class HashWithRenderStrategy < HashWithCaller
4
+ class HashWithRenderStrategy < Hash
3
5
  attr_accessor :render_strategy
4
6
 
5
7
  RENDER_WITH_PROXY = :with
6
8
  RENDER_WITH_BLOCK = :block
7
9
  RENDER_WITH_PARTIAL = :partial
8
10
 
9
- RENDERING_STRATEGIES = [RENDER_WITH_PROXY, RENDER_WITH_BLOCK, RENDER_WITH_PARTIAL]
11
+ RENDERING_STRATEGIES = [RENDER_WITH_PROXY, RENDER_WITH_PARTIAL, RENDER_WITH_BLOCK]
10
12
 
11
- def initialize_copy(original)
12
- super
13
- self.callers = original.callers.clone
14
- self.render_strategy = nil
15
- RENDERING_STRATEGIES.each do |rs|
16
- self.delete(rs)
17
- end
13
+ def initialize(*args, &block)
14
+ super &nil
15
+ options = args.extract_options!
16
+ reverse_merge!(args.first, options, &block)
18
17
  end
19
18
 
20
- alias_method :dup, :clone
19
+ def to_hash
20
+ {}.update(self)
21
+ end
21
22
 
22
- def reverse_merge(options)
23
- self.clone.tap {|cloned| cloned.add_options(options) }
23
+ def slice(*keys)
24
+ self.class.new(super)
24
25
  end
25
26
 
26
- # TODO: need to implement either merge or update to update
27
- # both the hash and the callers hash
27
+ def except(*keys)
28
+ slice(*self.keys - keys)
29
+ end
28
30
 
29
- def add_options(*args, &block)
31
+ def reverse_merge!(*args, &block)
30
32
  options = args.extract_options!
31
- if !options.is_a?(HashWithIndifferentAccess)
32
- options = options.with_indifferent_access
33
- end
34
33
  options[:block] = block if block
35
34
  if render_strategy.nil?
36
35
  self.render_strategy = if options.is_a?(HashWithRenderStrategy)
@@ -40,11 +39,60 @@ module Blocks
40
39
  end
41
40
  end
42
41
 
43
- super(*args, options)
42
+ options.each do |key, value|
43
+ current_value = self[key]
44
+
45
+ if !self.key?(key)
46
+ self[key] = value
47
+ elsif current_value.is_a?(Hash) && value.is_a?(Hash)
48
+ # TODO: handle attribute merges here
49
+ self[key] = value.deep_merge(current_value)
50
+ end
51
+ end
44
52
  end
45
53
 
46
54
  def render_strategy_and_item
47
55
  [render_strategy, self[render_strategy]] if render_strategy
48
56
  end
57
+
58
+ def render_strategy_item
59
+ self[render_strategy] if render_strategy
60
+ end
61
+
62
+ def renders_with_proxy?
63
+ render_strategy == RENDER_WITH_PROXY
64
+ end
65
+
66
+ def nested_under_indifferent_access
67
+ self
68
+ end
69
+
70
+ # Returns +true+ so that <tt>Array#extract_options!</tt> finds members of
71
+ # this class.
72
+ def extractable_options?
73
+ true
74
+ end
75
+
76
+ def to_s
77
+ description = []
78
+
79
+ description << "{"
80
+ description << map do |key, value|
81
+ value_display = case value
82
+ when Symbol
83
+ ":#{value}"
84
+ when String
85
+ "\"#{value}\""
86
+ when Proc
87
+ "Proc"
88
+ else
89
+ value
90
+ end
91
+ # "\"#{key}\" => #{value_display}, # [#{callers[key]}]"
92
+ "\"#{key}\" => #{value_display}"
93
+ end.join(",\n")
94
+ description << "}"
95
+ description.join("\n")
96
+ end
49
97
  end
50
98
  end
@@ -1,95 +1,70 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Blocks
2
- class OptionsSet < HashWithIndifferentAccess
4
+ class OptionsSet < HashWithRenderStrategy
3
5
  attr_accessor :name
4
-
5
- attr_accessor :runtime_options
6
- attr_accessor :standard_options
7
6
  attr_accessor :default_options
8
7
 
9
8
  def initialize(*args, &block)
10
- options = args.extract_options!
11
- self.name = args.first
12
- reset
13
- add_options options, &block
14
- super(&nil)
15
- end
16
-
17
- def initialize_copy(original)
18
9
  super
19
- control_fields = (
20
- RuntimeContext::CONTROL_VARIABLES.keys +
21
- RuntimeContext::CONTROL_VARIABLES.values
22
- ).flatten.compact
23
- self.runtime_options = original.runtime_options.clone.except(*control_fields)
24
- self.default_options = original.default_options.clone.except(*control_fields)
25
- self.standard_options = original.standard_options.clone.except(*control_fields)
26
- end
27
-
28
- def to_s
29
- description = []
30
- description << "Block Name: #{name}"
31
- description << "------------------------------"
32
- description << "Runtime Options:"
33
- description << runtime_options.to_s
34
- description << "------------------------------"
35
- description << "Standard Options:"
36
- description << standard_options.to_s
37
- description << "------------------------------"
38
- description << "Default Options:"
39
- description << default_options.to_s
40
- description.join("\n")
10
+ self.name = args.first
41
11
  end
42
12
 
13
+ # def to_s
14
+ # description = []
15
+ # description << "Block Name: #{name}"
16
+ # description << "------------------------------"
17
+ # description << "Standard Options:"
18
+ # description << standard_options.to_s
19
+ # description << "------------------------------"
20
+ # description << "Default Options:"
21
+ # description << default_options.to_s
22
+ # description.join("\n")
23
+ # end
24
+ #
43
25
  def inspect
44
- hash = standard_options.to_hash
45
- hash[:defaults] = default_options if default_options.present?
46
- hash[:runtime] = runtime_options if runtime_options.present?
26
+ hash = to_hash
27
+ hash[:defaults] = default_options.to_hash if default_options.present?
47
28
  hash
48
29
  end
49
30
 
50
- def add_options(*args, &block)
31
+ def reverse_merge!(*args, &block)
51
32
  options = args.extract_options!
52
33
  caller_id = args.first
53
34
 
54
- runtime, defaults, standard = if options.is_a?(OptionsSet)
35
+ defaults, standard = if options.is_a?(OptionsSet)
55
36
  caller_id ||= options.name
56
- [options.runtime_options, options.default_options, options.standard_options]
37
+ [options.default_options, options]
57
38
  else
58
- if !options.is_a?(HashWithIndifferentAccess)
59
- options = options.with_indifferent_access
60
- end
61
- [options.delete(:runtime), options.delete(:defaults), options]
39
+ [options.delete(:defaults), options]
62
40
  end
63
41
 
64
42
  caller_id ||= self.name
65
43
 
66
- runtime_options.add_options caller_id, runtime
67
- standard_options.add_options caller_id, standard, &block
68
- default_options.add_options caller_id, defaults
44
+ if standard.present? || block
45
+ super caller_id, standard, &block
46
+ end
69
47
 
70
- self
71
- end
48
+ if defaults.present?
49
+ if !default_options
50
+ self.default_options = HashWithRenderStrategy.new "#{name} Default Options"
51
+ end
52
+ default_options.reverse_merge! caller_id, defaults
53
+ end
72
54
 
73
- def reset
74
- self.runtime_options = HashWithRenderStrategy.new "#{name} Runtime Options"
75
- self.standard_options = HashWithRenderStrategy.new "#{name} Standard Options"
76
- self.default_options = HashWithRenderStrategy.new "#{name} Default Options"
55
+ self
77
56
  end
78
57
 
79
- def current_render_strategy_and_item
80
- render_strategies_and_items.compact.first
58
+ def renders_with_proxy?
59
+ render_strategy == HashWithRenderStrategy::RENDER_WITH_PROXY
81
60
  end
82
61
 
83
- def render_strategies_and_items
84
- [
85
- runtime_options.render_strategy_and_item,
86
- standard_options.render_strategy_and_item,
87
- default_options.render_strategy_and_item
88
- ]
62
+ def render_strategy
63
+ super || default_options.try(:render_strategy)
89
64
  end
90
65
 
91
- def nested_under_indifferent_access
92
- self
66
+ def render_strategy_item
67
+ super || default_options.try(:render_strategy_item)
93
68
  end
94
69
  end
95
70
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Blocks
2
- VERSION = "3.0.1"
4
+ VERSION = "4.0.0.rc2"
3
5
  end
metadata CHANGED
@@ -1,45 +1,45 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blocks
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.1
4
+ version: 4.0.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Hunter
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-10-17 00:00:00.000000000 Z
11
+ date: 2020-06-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: call_with_params
14
+ name: rails
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: 3.0.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: 3.0.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: rails
28
+ name: simplecov
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 3.0.0
34
- type: :runtime
33
+ version: '0'
34
+ type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 3.0.0
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: simplecov
42
+ name: memory_profiler
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -82,10 +82,13 @@ files:
82
82
  - docs/_includes/custom-builders.md
83
83
  - docs/_includes/defining.md
84
84
  - docs/_includes/demos/hooks-and-wrappers-output.html
85
+ - docs/_includes/features.md
86
+ - docs/_includes/helper-blocks.md
87
+ - docs/_includes/helper-blocks/content_tag.md
85
88
  - docs/_includes/hooks.md
86
89
  - docs/_includes/installation.md
87
- - docs/_includes/introduction.md
88
90
  - docs/_includes/option-merging.md
91
+ - docs/_includes/overview.md
89
92
  - docs/_includes/rendering.md
90
93
  - docs/_includes/reserved-keywords.md
91
94
  - docs/_includes/skipping.md
@@ -94,7 +97,6 @@ files:
94
97
  - docs/_includes/templating.md
95
98
  - docs/_includes/templating/bootstrap_4_cards.md
96
99
  - docs/_includes/use-cases.md
97
- - docs/_includes/wip.md
98
100
  - docs/_includes/wrappers.md
99
101
  - docs/_layouts/slate.html
100
102
  - docs/_plugins/gem_version.rb
@@ -147,14 +149,15 @@ files:
147
149
  - gemfiles/Gemfile.rails-4-2-stable
148
150
  - gemfiles/Gemfile.rails-5-0-stable
149
151
  - gemfiles/Gemfile.rails-5-1-stable
152
+ - gemfiles/Gemfile.rails-5-2-stable
150
153
  - lib/blocks.rb
151
- - lib/blocks/action_view_extensions/view_extensions.rb
152
154
  - lib/blocks/builders/block_definition.rb
153
155
  - lib/blocks/builders/builder.rb
154
156
  - lib/blocks/builders/hook_definition.rb
155
- - lib/blocks/experimental/builder_permissions.rb
156
- - lib/blocks/experimental/invalid_permissions_handler.rb
157
- - lib/blocks/renderers/abstract_renderer.rb
157
+ - lib/blocks/engine.rb
158
+ - lib/blocks/helpers/controller_extensions.rb
159
+ - lib/blocks/helpers/haml_capture.rb
160
+ - lib/blocks/helpers/view_extensions.rb
158
161
  - lib/blocks/renderers/adjacent_blocks_renderer.rb
159
162
  - lib/blocks/renderers/block_placeholder.rb
160
163
  - lib/blocks/renderers/block_renderer.rb
@@ -166,7 +169,6 @@ files:
166
169
  - lib/blocks/renderers/runtime_context.rb
167
170
  - lib/blocks/renderers/wrapper_renderer.rb
168
171
  - lib/blocks/utilities/configurator.rb
169
- - lib/blocks/utilities/dynamic_configuration.rb
170
172
  - lib/blocks/utilities/hash_with_caller.rb
171
173
  - lib/blocks/utilities/hash_with_render_strategy.rb
172
174
  - lib/blocks/utilities/options_set.rb
@@ -187,12 +189,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
187
189
  version: '0'
188
190
  required_rubygems_version: !ruby/object:Gem::Requirement
189
191
  requirements:
190
- - - ">="
192
+ - - ">"
191
193
  - !ruby/object:Gem::Version
192
- version: '0'
194
+ version: 1.3.1
193
195
  requirements: []
194
- rubyforge_project:
195
- rubygems_version: 2.6.13
196
+ rubygems_version: 3.1.2
196
197
  signing_key:
197
198
  specification_version: 4
198
199
  summary: Blocks gives you total control over how your blocks of code render.