Module: Upkeep::Rails::Replay
- Defined in:
- lib/upkeep/rails/replay.rb
Defined Under Namespace
Classes: RackSession
Class Method Summary collapse
- .application_env_config ⇒ Object
- .collect_response_body(body) ⇒ Object
- .constantize(name) ⇒ Object
- .inferred_local_name(partial) ⇒ Object
- .partial_path(template) ⇒ Object
- .rack_env(env) ⇒ Object
- .render(recipe) ⇒ Object
- .render_collection(replay) ⇒ Object
- .render_collection_member(replay) ⇒ Object
- .render_controller_page(replay, env: replay.env) ⇒ Object
- .render_controller_turbo_frame(replay) ⇒ Object
- .render_fragment(replay) ⇒ Object
- .render_template(replay) ⇒ Object
- .renderer_for(replay) ⇒ Object
- .replay_session_snapshot?(value) ⇒ Boolean
- .replay_template_context ⇒ Object
- .replay_warden_snapshot?(value) ⇒ Boolean
- .revive_env_value(value) ⇒ Object
- .revive_form_builder(snapshot, template:) ⇒ Object
- .revive_hash(values, template: replay_template_context) ⇒ Object
- .revive_replay_session(snapshot) ⇒ Object
- .revive_replay_warden(snapshot) ⇒ Object
- .revive_value(snapshot, template: replay_template_context) ⇒ Object
- .turbo_frame_src(env) ⇒ Object
Class Method Details
.application_env_config ⇒ Object
133 134 135 136 137 138 |
# File 'lib/upkeep/rails/replay.rb', line 133 def application_env_config return {} unless defined?(::Rails) && ::Rails.respond_to?(:application) application = ::Rails.application application.respond_to?(:env_config) ? application.env_config : {} end |
.collect_response_body(body) ⇒ Object
236 237 238 239 240 |
# File 'lib/upkeep/rails/replay.rb', line 236 def collect_response_body(body) body.each.to_a.join ensure body.close if body.respond_to?(:close) end |
.constantize(name) ⇒ Object
232 233 234 |
# File 'lib/upkeep/rails/replay.rb', line 232 def constantize(name) name.to_s.split("::").reduce(Object) { |namespace, constant_name| namespace.const_get(constant_name) } end |
.inferred_local_name(partial) ⇒ Object
228 229 230 |
# File 'lib/upkeep/rails/replay.rb', line 228 def inferred_local_name(partial) File.basename(partial.to_s).sub(/\A_/, "").to_sym end |
.partial_path(template) ⇒ Object
224 225 226 |
# File 'lib/upkeep/rails/replay.rb', line 224 def partial_path(template) template.to_s.sub(%r{(^|/)_([^/]+)\z}, "\\1\\2") end |
.rack_env(env) ⇒ Object
124 125 126 127 128 129 130 131 |
# File 'lib/upkeep/rails/replay.rb', line 124 def rack_env(env) env = application_env_config.merge( env.each_with_object({}) { |(key, value), copy| copy[key.to_s] = revive_env_value(value) } ) env["rack.input"] = StringIO.new env["rack.errors"] ||= StringIO.new env end |
.render(recipe) ⇒ Object
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/upkeep/rails/replay.rb', line 22 def render(recipe) replay = recipe.replay case replay when ::Upkeep::Replay::ControllerPage render_controller_page(replay) when ::Upkeep::Replay::ControllerTurboFrame render_controller_turbo_frame(replay) when ::Upkeep::Replay::Template render_template(replay) when ::Upkeep::Replay::Fragment render_fragment(replay) when ::Upkeep::Replay::Collection render_collection(replay) when ::Upkeep::Replay::CollectionMember render_collection_member(replay) else raise "unknown Rails replay recipe type: #{replay.class.name}" end end |
.render_collection(replay) ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/upkeep/rails/replay.rb', line 88 def render_collection(replay) template_context = replay_template_context = revive_hash(replay., template: template_context) collection = revive_value(replay.collection, template: template_context) if replay.derived_partial? renderer_for(replay).render(collection) else renderer_for(replay).render(.merge( partial: replay.partial, collection: collection )) end end |
.render_collection_member(replay) ⇒ Object
103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/upkeep/rails/replay.rb', line 103 def render_collection_member(replay) template_context = replay_template_context = revive_hash(replay., template: template_context) record = revive_value(replay.record, template: template_context) locals = .fetch(:locals, {}) local_name = ([:as] || inferred_local_name(replay.partial)).to_sym renderer_for(replay).render( partial: replay.partial, locals: locals.merge(local_name => record) ) end |
.render_controller_page(replay, env: replay.env) ⇒ Object
43 44 45 46 47 48 49 |
# File 'lib/upkeep/rails/replay.rb', line 43 def render_controller_page(replay, env: replay.env) controller = constantize(replay.controller_class) _status, _headers, body = ControllerRuntime.suppress do controller.action(replay.action).call(rack_env(env)) end collect_response_body(body) end |
.render_controller_turbo_frame(replay) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/upkeep/rails/replay.rb', line 51 def render_controller_turbo_frame(replay) html = render_controller_page( replay, env: replay.env.merge("HTTP_TURBO_FRAME" => replay.target_id) ) target = Targeting::Target.new("turbo_frame", replay.target_id, "Turbo Frame replay") frame_html = Targeting::Extraction.extract_target_html(html, target) frame = Nokogiri::HTML5.fragment(frame_html).at_css("turbo-frame") frame["src"] = turbo_frame_src(replay.env) frame.to_html end |
.render_fragment(replay) ⇒ Object
79 80 81 82 83 84 85 86 |
# File 'lib/upkeep/rails/replay.rb', line 79 def render_fragment(replay) template_context = replay_template_context renderer_for(replay).render( partial: partial_path(replay.template), locals: revive_hash(replay.locals, template: template_context), assigns: revive_hash(replay.assigns, template: template_context) ) end |
.render_template(replay) ⇒ Object
70 71 72 73 74 75 76 77 |
# File 'lib/upkeep/rails/replay.rb', line 70 def render_template(replay) template_context = replay_template_context renderer_for(replay).render( template: replay.template, locals: revive_hash(replay.locals, template: template_context), assigns: revive_hash(replay.assigns, template: template_context) ) end |
.renderer_for(replay) ⇒ Object
116 117 118 119 120 121 122 |
# File 'lib/upkeep/rails/replay.rb', line 116 def renderer_for(replay) if replay.controller_class constantize(replay.controller_class).renderer else ::ActionController::Base.renderer end end |
.replay_session_snapshot?(value) ⇒ Boolean
196 197 198 199 200 201 |
# File 'lib/upkeep/rails/replay.rb', line 196 def replay_session_snapshot?(value) return false unless value.is_a?(Hash) type = value["__upkeep_replay_type"] || value[:__upkeep_replay_type] type == "rack_session" end |
.replay_template_context ⇒ Object
178 179 180 |
# File 'lib/upkeep/rails/replay.rb', line 178 def replay_template_context ::ActionView::Base.empty end |
.replay_warden_snapshot?(value) ⇒ Boolean
208 209 210 211 212 213 |
# File 'lib/upkeep/rails/replay.rb', line 208 def replay_warden_snapshot?(value) return false unless value.is_a?(Hash) type = value["__upkeep_replay_type"] || value[:__upkeep_replay_type] type == "warden" end |
.revive_env_value(value) ⇒ Object
182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/upkeep/rails/replay.rb', line 182 def revive_env_value(value) return revive_replay_session(value) if replay_session_snapshot?(value) return revive_replay_warden(value) if replay_warden_snapshot?(value) case value when Hash value.transform_values { |nested_value| revive_env_value(nested_value) } when Array value.map { |nested_value| revive_env_value(nested_value) } else value end end |
.revive_form_builder(snapshot, template:) ⇒ Object
169 170 171 172 173 174 175 176 |
# File 'lib/upkeep/rails/replay.rb', line 169 def revive_form_builder(snapshot, template:) constantize(snapshot.builder_class).new( snapshot.object_name, revive_value(snapshot.object, template: template), template, revive_hash(snapshot., template: template) ) end |
.revive_hash(values, template: replay_template_context) ⇒ Object
140 141 142 143 144 145 146 |
# File 'lib/upkeep/rails/replay.rb', line 140 def revive_hash(values, template: replay_template_context) values = values.entries if values.is_a?(::Upkeep::Replay::HashValue) values.each_with_object({}) do |(key, value), revived| revived[key.to_sym] = revive_value(value, template: template) end end |
.revive_replay_session(snapshot) ⇒ Object
203 204 205 206 |
# File 'lib/upkeep/rails/replay.rb', line 203 def revive_replay_session(snapshot) values = snapshot["values"] || snapshot[:values] || {} RackSession.new(revive_env_value(values)) end |
.revive_replay_warden(snapshot) ⇒ Object
215 216 217 218 219 220 221 222 |
# File 'lib/upkeep/rails/replay.rb', line 215 def revive_replay_warden(snapshot) users = snapshot["users"] || snapshot[:users] || {} revived_users = users.to_h do |scope, user_snapshot| value = ::Upkeep::Replay::Value.from_h(user_snapshot) [scope, revive_value(value)] end Runtime::ObservedWarden.new(revived_users) end |
.revive_value(snapshot, template: replay_template_context) ⇒ Object
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/upkeep/rails/replay.rb', line 148 def revive_value(snapshot, template: replay_template_context) snapshot = ::Upkeep::Replay.value(snapshot) case snapshot when ::Upkeep::Replay::ActiveRecordValue constantize(snapshot.model).find(snapshot.id) when ::Upkeep::Replay::ActiveRecordRelationValue constantize(snapshot.model).find_by_sql(snapshot.sql) when ::Upkeep::Replay::ArrayValue snapshot.items.map { |item| revive_value(item, template: template) } when ::Upkeep::Replay::HashValue revive_hash(snapshot.entries, template: template) when ::Upkeep::Replay::LiteralValue snapshot.value when ::Upkeep::Replay::RailsFormBuilderValue revive_form_builder(snapshot, template: template) else raise "unsupported Rails replay value type: #{snapshot.class.name}" end end |
.turbo_frame_src(env) ⇒ Object
63 64 65 66 67 68 |
# File 'lib/upkeep/rails/replay.rb', line 63 def turbo_frame_src(env) env = env.transform_keys(&:to_s) path = "#{env["SCRIPT_NAME"]}#{env["PATH_INFO"]}" query = env["QUERY_STRING"].to_s query.empty? ? path : "#{path}?#{query}" end |