Class: SvelteOnRails::Lib::ViewHelperSupport
- Inherits:
-
Object
- Object
- SvelteOnRails::Lib::ViewHelperSupport
- Defined in:
- lib/svelte_on_rails/lib/view_helper_support.rb
Constant Summary collapse
- 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
- #component_paths ⇒ Object
- #debug? ⇒ Boolean
-
#initialize(component, props, html_options, options, request, view_dir, caching = false) ⇒ ViewHelperSupport
constructor
A new instance of ViewHelperSupport.
- #log_completed(message) ⇒ Object
- #render_cached(view_context, &block) ⇒ 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, caching = false) ⇒ ViewHelperSupport
Returns a new instance of ViewHelperSupport.
10 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 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 10 def initialize(component, props, , , request, view_dir, caching = false) @start_time = Time.now @conf = SvelteOnRails::Configuration.instance @utils = SvelteOnRails::Lib::Utils @options = @component_name = component @view_dir = view_dir @request = request @props = props @html_options = @ssr = if request == :cache_warmer true else resolve_ssr?(request) end return unless @ssr if @conf.watch_changes? # check file existence and capitalization p = component_paths unless File.exist?(Rails.root.join(p[:path])) raise <<~TEXT [SOR] Source file not found: «#{p[:path]}» TEXT end if p[:path][0..9] == 'app/views/' if !p[:file_basename].match?(/^[A-Z][A-Za-z0-9]+$/) && !p[:file_basename].match?(/^[a-z0-9][a-z0-9_]+$/) raise <<~TEXT [SOR] Invalid filename: «#{p[:file_basename]}» Component names must be CamelCased or under_scored and must be prefixed by underscore. TEXT end elsif !p[:file_basename].match?(/^[A-Z][A-Za-z0-9]+$/) raise <<~TEXT [SOR] Invalid filename: «#{p[:file_basename]}» Component names must be CamelCased. 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 importand 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 dependend source files, # check theyr 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 @conf.configs[:cache_warmer] && caching Thread.new do SvelteOnRails::Lib::CacheWarmer.instance.store_request(component, props, , , view_dir) end 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.
8 9 10 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 8 def conf @conf end |
Instance Method Details
#component_paths ⇒ Object
112 113 114 115 116 117 118 119 120 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 112 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
148 149 150 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 148 def debug? @options[:debug] end |
#log_completed(message) ⇒ Object
156 157 158 159 160 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 156 def log_completed() ms = ((Time.now - @start_time) * 1000) @conf.request_metrics[:total_time] += ms Rails.logger.info " [SOR] #{component_paths[:name]}.svelte #{} (#{ms.round(1)}ms)" end |
#render_cached(view_context, &block) ⇒ Object
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 162 def render_cached(view_context, &block) # increase expired time @conf.redis_instance.expire(cache_key, redis_expiration_seconds) # render res = if @cached_content msg = "returned from cache" @cached_content.html_safe else msg = "Rendered" @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 log_completed(msg) res end |
#request_metrics ⇒ Object
189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 189 def request_metrics @conf.request_metrics ||= {} _req_id = @conf.request_metrics[:request_uuid] if @request.uuid != _req_id @conf.request_metrics = { request_uuid: @request.uuid, total_time: 0.0 } end @conf.request_metrics end |
#set_request_metrics(action_key) ⇒ Object
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 203 def set_request_metrics(action_key) if @conf.watch_changes? && ![ :build, :build_failed, :render_failed, :from_cache, :empty, :rendered, :build_tried_for_error_message, :ssr_server_unreachable ].include?(action_key) raise "[SOR] set_request_metrics: invalid action_key" end request_metrics @conf.request_metrics[action_key] ||= 0 @conf.request_metrics[action_key] += 1 end |
#ssr? ⇒ Boolean
152 153 154 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 152 def ssr? @ssr end |
#tag_attributes(html_options, svelte_props) ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/svelte_on_rails/lib/view_helper_support.rb', line 122 def tag_attributes(, svelte_props) ht_opts = .deep_symbolize_keys.deep_merge( { data: { component: component_paths[:vite_path], controller: 'svelte-on-rails' } } ) cl = "svelte-component #{ht_opts[:class]}".split(' ') _cl = 'svelte-' + component_paths[:name].underscore.gsub('_', '-') cl.push(_cl) unless cl.include?(_cl) 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' #svelte_props = {my: :joke} ht_opts[:class] = cl.compact.join(' ') ht_opts[:data][:props] = svelte_props.to_json ht_opts[:data][:svelte_status] = 'do-not-hydrate-me' if @options[:hydrate] == false ht_opts end |