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[:handlers] = [:props]

  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
164
165
166
167
# 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])
      if item && ::Proc === fragment_name
        fragment_name = fragment_name.call(item)
      end

      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