Class: CamaleonRecord

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
app/models/camaleon_record.rb

Overview

rubocop:disable Rails/ApplicationRecord

Constant Summary collapse

TRANSLATION_TAG_HIDE_SENTINELS =

Sentinels used to shield HTML comment delimiters (the translation locale markers such as <!--:en-->) from ActionController's sanitize(), which strips HTML comments. Private-Use-Area code points are used so that plain text typed by a user can never be rewritten into a comment delimiter after sanitization: the previous !--/--! tokens collided with ordinary text (e.g. "Read more !--"), so the restore pass would inject stray <!--/--> into the output. The hide map also strips any raw sentinel characters supplied in the input, so they cannot be smuggled through to become delimiters on restore.

{ open: "\u{E000}", close: "\u{E001}" }.freeze
TRANSLATION_TAG_HIDE_MAP =
{
  '<!--' => TRANSLATION_TAG_HIDE_SENTINELS[:open],
  '-->' => TRANSLATION_TAG_HIDE_SENTINELS[:close],
  TRANSLATION_TAG_HIDE_SENTINELS[:open] => '',
  TRANSLATION_TAG_HIDE_SENTINELS[:close] => ''
}.freeze
TRANSLATION_TAG_HIDE_REGEX =
Regexp.new(TRANSLATION_TAG_HIDE_MAP.keys.map { |x| Regexp.escape(x) }.join('|')).freeze
TRANSLATION_TAG_RESTORE_MAP =
{
  TRANSLATION_TAG_HIDE_SENTINELS[:open] => '<!--',
  TRANSLATION_TAG_HIDE_SENTINELS[:close] => '-->'
}.freeze
TRANSLATION_TAG_RESTORE_REGEX =
Regexp.new(TRANSLATION_TAG_RESTORE_MAP.keys.map { |x| Regexp.escape(x) }.join('|')).freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.cama_sanitize_translatable(value, tags: nil, attributes: nil) ⇒ Object

Sanitize a value with ActionController's sanitize() while preserving translation locale markers (). Shared by Post#sanitize_content and the NormalizeAttrs concern so the transform lives in one place. Returns nil unchanged. tags:/attributes: default to nil, i.e. the sanitizer's own allowlist, so NormalizeAttrs and other callers are unaffected; Post#content passes a widened list.



31
32
33
34
35
36
37
38
39
40
# File 'app/models/camaleon_record.rb', line 31

def self.cama_sanitize_translatable(value, tags: nil, attributes: nil)
  return value if value.nil?

  options = {}
  options[:tags] = tags if tags
  options[:attributes] = attributes if attributes
  ActionController::Base.helpers.sanitize(
    value.to_s.gsub(TRANSLATION_TAG_HIDE_REGEX, TRANSLATION_TAG_HIDE_MAP), **options
  ).gsub(TRANSLATION_TAG_RESTORE_REGEX, TRANSLATION_TAG_RESTORE_MAP)
end

.polymorphic_class_for(name) ⇒ Object



48
49
50
51
52
53
54
55
56
# File 'app/models/camaleon_record.rb', line 48

def self.polymorphic_class_for(name)
  super
rescue NameError
  legacy_class = legacy_camaleon_polymorphic_class(name)
  return legacy_class if legacy_class
  return nil if legacy_polymorphic_marker?(name)

  raise
end

.polymorphic_nameObject



42
43
44
45
46
# File 'app/models/camaleon_record.rb', line 42

def self.polymorphic_name
  return super unless name.to_s.start_with?('CamaleonCms::')

  name.demodulize
end

Instance Method Details

#abilityObject



115
116
117
118
119
# File 'app/models/camaleon_record.rb', line 115

def ability
  # Memoize Ability per request to avoid repeated DB queries and object instantiation.
  # In tests that modify role meta mid-request, call reset_ability to invalidate cache.
  @ability ||= CamaleonCms::Ability.new(current_user, current_site)
end

#cama_build_cache_key(key) ⇒ Object

internal helper to generate cache key



95
96
97
# File 'app/models/camaleon_record.rb', line 95

def cama_build_cache_key(key)
  _key = "cama_cache_#{self.class.name}_#{id}_#{key}"
end

#cama_fetch_cache(key) ⇒ Object

fetch the cache value for this key



73
74
75
76
77
78
79
80
81
82
# File 'app/models/camaleon_record.rb', line 73

def cama_fetch_cache(key)
  @cama_cache_vars ||= {}
  _key = cama_build_cache_key(key)
  if @cama_cache_vars.key?(_key)
    # puts "*********** using model cache var: #{_key}"
  else
    @cama_cache_vars[_key] = yield
  end
  @cama_cache_vars[_key]
end

#cama_get_cache(key) ⇒ Object

return the cache value for this key



85
86
87
88
89
90
91
92
# File 'app/models/camaleon_record.rb', line 85

def cama_get_cache(key)
  @cama_cache_vars ||= {}
  begin
    @cama_cache_vars[cama_build_cache_key(key)]
  rescue StandardError
    nil
  end
end

#cama_remove_cache(key) ⇒ Object

remove cache value for this key



66
67
68
69
70
# File 'app/models/camaleon_record.rb', line 66

def cama_remove_cache(key)
  return unless @cama_cache_vars

  @cama_cache_vars.delete(cama_build_cache_key(key))
end

#cama_set_cache(key, val) ⇒ Object

save cache value for this key



59
60
61
62
63
# File 'app/models/camaleon_record.rb', line 59

def cama_set_cache(key, val)
  @cama_cache_vars ||= {}
  @cama_cache_vars[cama_build_cache_key(key)] = val
  val
end

#can?(*args) ⇒ Boolean

Authorization helpers that delegate to central Ability (CanCan)

Returns:

  • (Boolean)


108
109
110
111
112
113
# File 'app/models/camaleon_record.rb', line 108

def can?(*args)
  # Return false if no user or site context (e.g., background jobs, console)
  return false if current_user.nil? || current_site.nil?

  ability.can?(*args)
end

#current_siteObject

current_site memoized from the CurrentRequest.site



127
128
129
130
131
# File 'app/models/camaleon_record.rb', line 127

def current_site
  return @current_site if defined?(@current_site) && @current_site.present?

  @current_site = CurrentRequest.site
end

#current_userObject

Return the current user for this thread/request context. Uses ActiveSupport::CurrentAttributes (CurrentRequest.user)



101
102
103
104
105
# File 'app/models/camaleon_record.rb', line 101

def current_user
  return @current_user if defined?(@current_user)

  @current_user = CurrentRequest.user
end

#reset_abilityObject

Reset cached ability instance (useful in tests when role meta changes)



122
123
124
# File 'app/models/camaleon_record.rb', line 122

def reset_ability
  @ability = nil
end