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
102 103 104 105 |
# File 'lib/curlybars/rendering_support.rb', line 102 def cached_call(meth) return cached_calls[meth] if cached_calls.key? meth instrument(meth) { cached_calls[meth] = meth.call } end |
#call(helper, helper_path, helper_position, arguments, options, &block) ⇒ Object
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/curlybars/rendering_support.rb', line 107 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 Curlybars::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
36 37 38 39 40 41 |
# File 'lib/curlybars/rendering_support.rb', line 36 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 Curlybars::Error::Render.new('context_is_not_an_array_of_presenters', , position) end |
#check_context_is_presenter(context, path, position) ⇒ Object
30 31 32 33 34 |
# File 'lib/curlybars/rendering_support.rb', line 30 def check_context_is_presenter(context, path, position) return if presenter?(context) = "`#{path}` is not a context type object" raise Curlybars::Error::Render.new('context_is_not_a_presenter', , position) end |
#check_timeout! ⇒ Object
23 24 25 26 27 28 |
# 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 ::Curlybars::Error::Render.new('timeout', , nil) end |
#coerce_to_hash!(collection, path, position) ⇒ Object
133 134 135 136 137 138 139 140 141 142 |
# File 'lib/curlybars/rendering_support.rb', line 133 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
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/curlybars/rendering_support.rb', line 156 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
65 66 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 |
# File 'lib/curlybars/rendering_support.rb', line 65 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
129 130 131 |
# File 'lib/curlybars/rendering_support.rb', line 129 def position(line_number, line_offset) Curlybars::Position.new(file_name, line_number, line_offset) end |
#presenter?(context) ⇒ Boolean
144 145 146 |
# File 'lib/curlybars/rendering_support.rb', line 144 def presenter?(context) context.respond_to? :allows_method? end |
#presenter_collection?(collection) ⇒ Boolean
148 149 150 151 152 153 154 |
# File 'lib/curlybars/rendering_support.rb', line 148 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
43 44 45 46 47 48 49 50 |
# File 'lib/curlybars/rendering_support.rb', line 43 def to_bool(condition) condition != false && condition != [] && condition != {} && condition != 0 && condition != '' && !condition.nil? end |
#variable(variable_path, position) ⇒ Object
52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/curlybars/rendering_support.rb', line 52 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 |