Class: Props::Partialer

Inherits:
Object
  • Object
show all
Defined in:
lib/props_template/extensions/partial_renderer.rb

Constant Summary collapse

INVALID_PARTIAL_MESSAGE =
"The partial name must be a string, but received (%s)."
OPTION_AS_ERROR_MESSAGE =
"The value (%s) of the option `as` is not a valid Ruby identifier; " \
"make sure it starts with lowercase letter, " \
"and is followed by any combination of letters, numbers and underscores."
IDENTIFIER_ERROR_MESSAGE =
"The partial name (%s) is not a valid Ruby identifier; " \
"make sure your partial name starts with underscore."

Instance Method Summary collapse

Constructor Details

#initialize(base, context, builder) ⇒ Partialer

Returns a new instance of Partialer.



26
27
28
29
30
# File 'lib/props_template/extensions/partial_renderer.rb', line 26

def initialize(base, context, builder)
  @context = context
  @builder = builder
  @base = base
end

Instance Method Details

#block_opts_to_render_opts(builder, options) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/props_template/extensions/partial_renderer.rb', line 79

def block_opts_to_render_opts(builder, options)
  partial, pass_opts = [*options[:partial]]
  pass_opts ||= {}
  pass_opts[:locals] ||= {}
  pass_opts[:partial] = partial
  pass_opts[:formats] = [:json]
  pass_opts.delete(:handlers)

  if !(String === partial)
    raise ArgumentError.new(INVALID_PARTIAL_MESSAGE % partial.inspect)
  end

  pass_opts
end

#build_rendered_template(content, template, layout = nil) ⇒ Object



111
112
113
# File 'lib/props_template/extensions/partial_renderer.rb', line 111

def build_rendered_template(content, template, layout = nil)
  RenderedTemplate.new content, layout, template
end

#extract_details(options) ⇒ Object



32
33
34
35
36
37
38
# File 'lib/props_template/extensions/partial_renderer.rb', line 32

def extract_details(options)
  registered_details.each_with_object({}) do |key, details|
    value = options[key]

    details[key] = Array(value) if value
  end
end

#find_and_add_template(all_options) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/props_template/extensions/partial_renderer.rb', line 48

def find_and_add_template(all_options)
  first_opts = all_options[0]

  if first_opts[:partial]
    partial_opts = block_opts_to_render_opts(@builder, first_opts)
    template = find_template(partial_opts)

    all_options.map do |opts|
      opts[:_template] = template
      opts
    end
  else
    all_options
  end
end

#find_template(partial_opts) ⇒ Object



64
65
66
67
68
69
70
71
# File 'lib/props_template/extensions/partial_renderer.rb', line 64

def find_template(partial_opts)
  partial = partial_opts[:partial]
  template_keys = retrieve_template_keys(partial_opts)
  details = extract_details(partial_opts)

  prefixes = partial.include?("/") ? [] : @context.lookup_context.prefixes
  @context.lookup_context.find_template(partial, prefixes, true, template_keys, details)
end

#handle(options) ⇒ Object



94
95
96
97
98
99
# File 'lib/props_template/extensions/partial_renderer.rb', line 94

def handle(options)
  partial_opts = block_opts_to_render_opts(@builder, options)
  template = options[:_template] || find_template(partial_opts)

  render_partial(template, @context, partial_opts)
end

#instrument(name, **options) ⇒ Object

:doc:



115
116
117
118
119
# File 'lib/props_template/extensions/partial_renderer.rb', line 115

def instrument(name, **options) # :doc:
  ActiveSupport::Notifications.instrument("render_#{name}.action_view", options) do |payload|
    yield payload
  end
end

#raise_invalid_identifier(path) ⇒ Object

Raises:

  • (ArgumentError)


125
126
127
# File 'lib/props_template/extensions/partial_renderer.rb', line 125

def raise_invalid_identifier(path)
  raise ArgumentError.new(IDENTIFIER_ERROR_MESSAGE % path)
end

#raise_invalid_option_as(as) ⇒ Object

Raises:

  • (ArgumentError)


121
122
123
# File 'lib/props_template/extensions/partial_renderer.rb', line 121

def raise_invalid_option_as(as)
  raise ArgumentError.new(OPTION_AS_ERROR_MESSAGE % as)
end

#refine_options(options, item = nil) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/props_template/extensions/partial_renderer.rb', line 135

def refine_options(options, item = nil)
  return options if !options[:partial]

  partial, rest = [*options[:partial]]
  rest = (rest || {}).clone
  locals = (rest[:locals] || {}).clone
  rest[:locals] = locals

  if item
    as = if !rest[:as]
      retrieve_variable(partial)
    else
      rest[:as].to_sym
    end

    raise_invalid_option_as(as) unless /\A[a-z_]\w*\z/.match?(as.to_s)

    locals[as] = item

    if (fragment_name = rest[:fragment])
      rest[:fragment] = fragment_name.to_s
    end
  end

  pass_opts = options.clone
  pass_opts[:partial] = [partial, rest]

  pass_opts
end

#registered_detailsObject



40
41
42
43
44
45
46
# File 'lib/props_template/extensions/partial_renderer.rb', line 40

def registered_details
  if ActionView.version.to_s >= "7"
    ActionView::LookupContext.registered_details
  else
    @context.lookup_context.registered_details
  end
end

#render_partial(template, view, options) ⇒ Object



101
102
103
104
105
106
107
108
109
# File 'lib/props_template/extensions/partial_renderer.rb', line 101

def render_partial(template, view, options)
  instrument(:partial, identifier: template.identifier) do |payload|
    locals = options[:locals]
    content = template.render(view, locals)

    payload[:cache_hit] = view.view_renderer.cache_hits[template.virtual_path]
    build_rendered_template(content, template)
  end
end

#retrieve_template_keys(options) ⇒ Object



73
74
75
76
77
# File 'lib/props_template/extensions/partial_renderer.rb', line 73

def retrieve_template_keys(options)
  template_keys = options[:locals].keys
  template_keys << options[:as] if options[:as]
  template_keys
end

#retrieve_variable(path) ⇒ Object



129
130
131
132
133
# File 'lib/props_template/extensions/partial_renderer.rb', line 129

def retrieve_variable(path)
  base = (path[-1] == "/") ? "" : File.basename(path)
  raise_invalid_identifier(path) unless base =~ /\A_?(.*?)(?:\.\w+)*\z/
  $1.to_sym
end