Class: SvelteOnRails::Lib::ViewHelperSupport
- Inherits:
-
Object
- Object
- SvelteOnRails::Lib::ViewHelperSupport
- Defined in:
- lib/svelte_on_rails/lib/view_helper_support.rb
Constant Summary collapse
- UNCACHED_PROPS_PLACEHOLDER =
"**Uncached Props are available only after hydration**"- RENDER_OPTIONS =
{ ssr: [true, false, :auto], hydrate: :bool, debug: :bool, cache_key: :string_array, expires_in: :integer, cached: :bool }
Instance Attribute Summary collapse
-
#conf ⇒ Object
readonly
Returns the value of attribute conf.
Instance Method Summary collapse
- #cached_props ⇒ Object
- #component_paths ⇒ Object
- #debug? ⇒ Boolean
-
#initialize(component, props, html_options, options, request, view_dir, config, caching = false, start_time) ⇒ ViewHelperSupport
constructor
A new instance of ViewHelperSupport.
- #log_completed(message) ⇒ Object
- #render_cached(view_context, &block) ⇒ Object
- #render_svelte(current_template) ⇒ Object
- #request_metrics ⇒ Object
- #set_request_metrics(action_key) ⇒ Object
- #ssr? ⇒ Boolean
- #tag_attributes(html_options, svelte_props) ⇒ Object
Constructor Details
#initialize(component, props, html_options, options, request, view_dir, config, caching = false, start_time) ⇒ ViewHelperSupport
Returns a new instance of ViewHelperSupport.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 11 def initialize( component, props, , , request, view_dir, config, caching = false, start_time ) @start_time = start_time @conf = config @conf.initialize_request_metrics(request.uuid) @utils = SvelteOnRails::Lib::Utils @options = @component_name = component @view_dir = view_dir @request = request @cached_props = if props.key?(:_uncached) props.merge(_uncached: UNCACHED_PROPS_PLACEHOLDER) else props end @html_options = @ssr = resolve_ssr?(request) return unless @ssr if @conf.watch_changes? # check file existence and capitalization p = component_paths if !p[:path] && p[:failed_attempts] raise <<~TEXT [Svelte on Rails] Component source file not found, searched by: • #{p[:failed_attempts].join("\n • ")} TEXT elsif !File.exist?(Rails.root.join(p[:path])) raise <<~TEXT [Svelte on Rails] Source file not found: «#{p[:path]}» TEXT end if p[:path].start_with?('app/views/') if !p[:file_basename].match?(/^[A-Z][A-Za-z0-9]*$/) && !p[:file_basename].match?(/^_[a-z0-9][a-z0-9_]*$/) @utils.puts_warning <<~TEXT Invalid filename: «#{p[:file_basename]}» Component names should be CamelCased, or under_scored and prefixed by an underscore (e.g. «_my_partial»). See: https://svelte-on-rails.dev/naming.html TEXT end elsif !p[:file_basename].match?(/^[A-Z][A-Za-z0-9]*$/) @utils.puts_warning <<~TEXT Invalid filename: «#{p[:file_basename]}» Component names should be CamelCased. See: https://svelte-on-rails.dev/naming.html TEXT end full_path = Rails.root.join(p[:path]) dir, wanted = full_path.dirname.to_s, full_path.basename.to_s unless Dir.children(dir).include?(wanted) raise "ERROR: Incorrect capitalisation: «#{p[:path]}»" end if !@conf.manifest_json_path.exist? || !@conf.dev_module_map_path.exist? || @conf.build_status['mtime'].to_f != @utils.manifest_file_mtime || # if a developer has run build from the console, we must update the build-status object # this is importand for having reliable error-messages (!@conf.build_status['passed'] && !request_metrics[:build_tried_for_error_message]) # when build has failed the developer sees the error message # at this point it is important to see the build-error in the logs # but only ONCE for a request, so we check metrics too run_vite_build set_request_metrics(:build_tried_for_error_message) return unless @conf.build_status['passed'] end # now we are sure to have a valid manifest # and are able to collect the dependent source files, # check their mtime # and run a build if something has changed (is only the case if the build above not was run) ensure_valid_component_and_manifest!(component) if @conf.component_mtime_changed?(component_paths[:path], debug?, component_paths[:file_basename]) run_vite_build end # finally, validate the given options end if caching @cached_content = @conf.debug_log(debug?, component_paths[:name], "Fetch Cache") do ck = (@conf.watch_changes? ? cache_key_fresh : cache_key) @conf.redis_instance.get(ck) end return if @cached_content elsif @conf.watch_changes? raise '[SOR] :expires_in is not allowed for this helper' if @options.key?(:expires_in) raise '[SOR] :cache_key is not allowed for this helper' if @options.key?(:cache_key) end end |
Instance Attribute Details
#conf ⇒ Object (readonly)
Returns the value of attribute conf.
9 10 11 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 9 def conf @conf end |
Instance Method Details
#cached_props ⇒ Object
227 228 229 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 227 def cached_props @cached_props ||= {} end |
#component_paths ⇒ Object
116 117 118 119 120 121 122 123 124 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 116 def component_paths if @conf.watch_changes? @component_paths ||= @utils.component_paths_uncached(@component_name, @view_dir) else key = "#{@component_name}_#{@view_dir}" @conf.component_paths_cache[key] ||= @utils.component_paths_uncached(@component_name, @view_dir) end end |
#debug? ⇒ Boolean
147 148 149 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 147 def debug? @options[:debug] end |
#log_completed(message) ⇒ Object
155 156 157 158 159 160 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 155 def log_completed() ms = ((Time.now - @start_time) * 1000) @conf.request_metrics[:total_time] += ms msg = " [SOR] #{component_paths[:name]}.svelte #{} (#{ms.round(1)}ms)" Rails.logger.info msg end |
#render_cached(view_context, &block) ⇒ Object
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 179 def render_cached(view_context, &block) # increase expired time @conf.redis_instance.expire(cache_key, redis_expiration_seconds) # render res = if @cached_content @cached_content.html_safe else @skip_caching = false @conf.debug_log(debug?, component_paths[:name], "rendered and stored to cache (key: «#{cache_key}»)") do r = view_context.instance_eval(&block) unless @skip_caching @conf.redis_instance.set(cache_key, r) end r end end res end |
#render_svelte(current_template) ⇒ Object
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 162 def render_svelte(current_template) caller_loc = Proc.new do v_path = current_template.identifier caller_locations.find { |loc| loc.to_s.include?(v_path) }.to_s.match(/^[\s\S]+(:[0-9]+(?=:in))/).to_s end r = render_with_ssr_server(caller_loc) || render_with_fallback if r[:success] set_request_metrics(:rendered) else @skip_caching = true end r end |
#request_metrics ⇒ Object
203 204 205 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 203 def request_metrics @conf.request_metrics end |
#set_request_metrics(action_key) ⇒ Object
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 207 def set_request_metrics(action_key) if @conf.watch_changes? && ![ :build, :from_cache, :empty, :rendered, :build_tried_for_error_message ].include?(action_key) raise "[SOR] set_request_metrics: invalid action_key: #{action_key}" end request_metrics @conf.request_metrics[action_key] ||= 0 @conf.request_metrics[action_key] += 1 end |
#ssr? ⇒ Boolean
151 152 153 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 151 def ssr? @ssr end |
#tag_attributes(html_options, svelte_props) ⇒ Object
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 126 def tag_attributes(, svelte_props) ht_opts = .deep_symbolize_keys.deep_merge( { data: { component: component_paths[:vite_path], controller: 'svelte-on-rails' } } ) tnl = SvelteOnRails::Lib::ToSvelteTranslations.instance _tnl = tnl.cached_translations(I18n.locale, :to_svelte_props, nil) svelte_props[:_translations] = _tnl if _tnl svelte_props[:test] = 'hello' ht_opts[:class] = "svelte-component #{ht_opts[:class]}" ht_opts[:data][:props] = svelte_props.to_json ht_opts[:data][:svelte_status] = (@options[:hydrate] == false ? 'do-not-hydrate-me' : 'ssr') ht_opts end |