Class: Curlybars::RenderingSupport
- Inherits:
-
Object
- Object
- Curlybars::RenderingSupport
- Defined in:
- lib/curlybars/rendering_support.rb
Instance Method Summary collapse
- #cached_call(meth) ⇒ Object
- #call(helper, helper_path, helper_position, arguments, options, &block) ⇒ Object
- #check_context_is_hash_or_enum_of_presenters(collection, path, position) ⇒ Object
- #check_context_is_presenter(context, path, position) ⇒ Object
- #check_timeout! ⇒ Object
- #coerce_to_hash!(collection, path, position) ⇒ Object
-
#initialize(timeout, contexts, variables, file_name, global_helpers_providers = [], cache = ->(key, &block) { block.call }) ⇒ RenderingSupport
constructor
A new instance of RenderingSupport.
- #optional_presenter_cache(presenter, template_cache_key, buffer) ⇒ Object
- #path(path, position) ⇒ Object
- #position(line_number, line_offset) ⇒ Object
- #presenter?(context) ⇒ Boolean
- #presenter_collection?(collection) ⇒ Boolean
- #to_bool(condition) ⇒ Object
- #variable(variable_path, position) ⇒ Object
Constructor Details
#initialize(timeout, contexts, variables, file_name, global_helpers_providers = [], cache = ->(key, &block) { block.call }) ⇒ RenderingSupport
Returns a new instance of RenderingSupport.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/curlybars/rendering_support.rb', line 3 def initialize(timeout, contexts, variables, file_name, global_helpers_providers = [], cache = ->(key, &block) { block.call }) @timeout = timeout @start_time = Time.now @contexts = contexts @variables = variables @file_name = file_name @cached_calls = {} @cache = cache @global_helpers = {} global_helpers_providers.each do |provider| provider.allowed_methods.each do |global_helper_name| symbol = global_helper_name.to_sym @global_helpers[symbol] = provider.method(symbol) end end end |
Instance Method Details
#cached_call(meth) ⇒ Object
106 107 108 109 110 |
# File 'lib/curlybars/rendering_support.rb', line 106 def cached_call(meth) return cached_calls[meth] if cached_calls.key? meth instrument(meth) { cached_calls[meth] = meth.call(*arguments_for_signature(meth, [], {})) } end |
#call(helper, helper_path, helper_position, arguments, options, &block) ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/curlybars/rendering_support.rb', line 112 def call(helper, helper_path, helper_position, arguments, , &block) parameters = helper.parameters parameter_types = parameters.map(&:first) # parameters has value [[:rest]] when the presenter is using method_missing to catch all calls has_invalid_parameters = parameter_types.map { |type| type != :req }.any? && parameter_types != [:rest] if has_invalid_parameters source_location = helper.source_location file_path = source_location ? source_location.first : "n/a" line_number = source_location ? helper.source_location.last : "n/a" = "#{file_path}:#{line_number} - `#{helper_path}` bad signature " << "for #{helper} - helpers must have only required parameters" raise ::Error::Render.new('invalid_helper_signature', , helper_position) end instrument(helper) do helper.call(*arguments_for_signature(helper, arguments, ), &block) end end |
#check_context_is_hash_or_enum_of_presenters(collection, path, position) ⇒ Object
38 39 40 41 42 43 |
# File 'lib/curlybars/rendering_support.rb', line 38 def check_context_is_hash_or_enum_of_presenters(collection, path, position) return if presenter_collection?(collection) = "`#{path}` is not an array of presenters or a hash of such" raise ::Error::Render.new('context_is_not_an_array_of_presenters', , position) end |
#check_context_is_presenter(context, path, position) ⇒ Object
31 32 33 34 35 36 |
# File 'lib/curlybars/rendering_support.rb', line 31 def check_context_is_presenter(context, path, position) return if presenter?(context) = "`#{path}` is not a context type object" raise ::Error::Render.new('context_is_not_a_presenter', , position) end |
#check_timeout! ⇒ Object
23 24 25 26 27 28 29 |
# File 'lib/curlybars/rendering_support.rb', line 23 def check_timeout! return unless timeout.present? return unless (Time.now - start_time) > timeout = "Rendering took too long (> #{timeout} seconds)" raise ::::Error::Render.new('timeout', , nil) end |
#coerce_to_hash!(collection, path, position) ⇒ Object
138 139 140 141 142 143 144 145 146 147 |
# File 'lib/curlybars/rendering_support.rb', line 138 def coerce_to_hash!(collection, path, position) check_context_is_hash_or_enum_of_presenters(collection, path, position) if collection.is_a?(Hash) collection elsif collection.respond_to? :each_with_index collection.each_with_index.map { |value, index| [index, value] }.to_h else raise "Collection is not coerceable to hash" end end |
#optional_presenter_cache(presenter, template_cache_key, buffer) ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/curlybars/rendering_support.rb', line 161 def optional_presenter_cache(presenter, template_cache_key, buffer) presenter_cache_key = presenter.respond_to?(:cache_key) ? presenter.cache_key : nil if presenter_cache_key cache_key = "#{presenter_cache_key}/#{template_cache_key}" buffer << cache.call(cache_key) do # Output from the block must be isolated from the main output buffer SafeBuffer.new.tap do |cache_buffer| yield cache_buffer end end else yield buffer end end |
#path(path, position) ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/curlybars/rendering_support.rb', line 67 def path(path, position) return global_helpers[path.to_sym] if global_helpers.key?(path.to_sym) check_traverse_not_too_deep(path, position) path_split_by_slashes = path.split('/') backward_steps_on_contexts = path_split_by_slashes.count - 1 base_context_position = contexts.length - backward_steps_on_contexts return -> {} unless base_context_position > 0 base_context_index = base_context_position - 1 base_context = contexts[base_context_index] dotted_path_side = path_split_by_slashes.last chain = dotted_path_side.split('.') method_to_return = chain.pop resolved = chain.inject(base_context) do |context, meth| next context if meth == 'this' next context.count if meth == 'length' && presenter_collection?(context) raise_if_not_traversable(context, meth, position) outcome = instrument(context.method(meth)) { context.public_send(meth) } return -> {} if outcome.nil? outcome end return -> { resolved } if method_to_return == 'this' if method_to_return == 'length' && presenter_collection?(resolved) return -> { resolved.count } end raise_if_not_traversable(resolved, method_to_return, position) resolved.method(method_to_return.to_sym) end |
#position(line_number, line_offset) ⇒ Object
134 135 136 |
# File 'lib/curlybars/rendering_support.rb', line 134 def position(line_number, line_offset) ::Position.new(file_name, line_number, line_offset) end |
#presenter?(context) ⇒ Boolean
149 150 151 |
# File 'lib/curlybars/rendering_support.rb', line 149 def presenter?(context) context.respond_to? :allows_method? end |
#presenter_collection?(collection) ⇒ Boolean
153 154 155 156 157 158 159 |
# File 'lib/curlybars/rendering_support.rb', line 153 def presenter_collection?(collection) collection = collection.values if collection.is_a?(Hash) collection.respond_to?(:each) && collection.all? do |presenter| presenter?(presenter) end end |
#to_bool(condition) ⇒ Object
45 46 47 48 49 50 51 52 |
# File 'lib/curlybars/rendering_support.rb', line 45 def to_bool(condition) condition != false && condition != [] && condition != {} && condition != 0 && condition != '' && !condition.nil? end |
#variable(variable_path, position) ⇒ Object
54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/curlybars/rendering_support.rb', line 54 def variable(variable_path, position) check_traverse_not_too_deep(variable_path, position) variable_split_by_slashes = variable_path.split('/') variable = variable_split_by_slashes.last.to_sym backward_steps_on_variables = variable_split_by_slashes.count - 1 variables_position = variables.length - backward_steps_on_variables scope = variables.first(variables_position).reverse.find do |vars| vars.key? variable end return scope[variable] if scope end |