Class: ActiveAdmin::Favorites::Favorite

Inherits:
ApplicationRecord show all
Includes:
UserRecord
Defined in:
app/models/active_admin/favorites/favorite.rb,
app/models/active_admin/favorites/favorite/query_params.rb,
app/models/active_admin/favorites/favorite/macro_builder.rb,
app/models/active_admin/favorites/favorite/macro_catalog.rb,
app/models/active_admin/favorites/favorite/macro_resolver.rb,
app/models/active_admin/favorites/favorite/range_detector.rb,
app/models/active_admin/favorites/favorite/macro_validator.rb

Direct Known Subclasses

CombinedFavorite, FiltersFavorite, LensFavorite

Defined Under Namespace

Modules: QueryParams Classes: MacroBuilder, MacroCatalog, MacroResolver, MacroValidator, RangeDetector

Constant Summary collapse

KINDS =
%w[filters lens combined].freeze
ACTIONS =
%w[index show].freeze
STI_TYPE_BY_KIND =
{
  "filters" => "ActiveAdmin::Favorites::FiltersFavorite",
  "lens" => "ActiveAdmin::Favorites::LensFavorite",
  "combined" => "ActiveAdmin::Favorites::CombinedFavorite"
}.freeze
KIND_BY_STI_TYPE =
STI_TYPE_BY_KIND.invert.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#include_layoutObject

Returns the value of attribute include_layout.



22
23
24
# File 'app/models/active_admin/favorites/favorite.rb', line 22

def include_layout
  @include_layout
end

#macros_jsonObject

Returns the value of attribute macros_json.



22
23
24
# File 'app/models/active_admin/favorites/favorite.rb', line 22

def macros_json
  @macros_json
end

#use_advanced_macrosObject

Returns the value of attribute use_advanced_macros.



22
23
24
# File 'app/models/active_admin/favorites/favorite.rb', line 22

def use_advanced_macros
  @use_advanced_macros
end

Class Method Details

.active_admin_resource_for(resource_key) ⇒ Object



126
127
128
129
130
131
# File 'app/models/active_admin/favorites/favorite.rb', line 126

def self.active_admin_resource_for(resource_key)
  namespace = ActiveAdmin.application.namespace(ActiveAdmin::Favorites.config.namespace_name)
  namespace.resources.find do |resource|
    resource.is_a?(ActiveAdmin::Resource) && resource.resource_name.route_key == resource_key
  end
end

.detected_ranges(query_string:, resource_key:) ⇒ Object



133
134
135
# File 'app/models/active_admin/favorites/favorite.rb', line 133

def self.detected_ranges(query_string:, resource_key:)
  RangeDetector.call(query_string:, resource_key:)
end

.filter_summary_for(query_string, macros: []) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'app/models/active_admin/favorites/favorite.rb', line 94

def self.filter_summary_for(query_string, macros: [])
  params = QueryParams.parse(query_string)
  parts = []
  parts << "scope: #{params["scope"]}" if params["scope"].present?

  macro_parts = Array(macros).map { |macro| MacroCatalog.describe(macro) }
  parts.concat(macro_parts)

  query_filters = params["q"]
  if query_filters.is_a?(Hash) && query_filters.any?
    parts << query_filters.keys.map { |key| key.sub(/_(eq|gteq|lteq|cont)\z/, "").tr("_", " ") }.join(", ")
  end

  parts << "sort: #{params["order"]}" if params["order"].present?
  parts.join(" · ").presence
end

.kind_for_type(type_name) ⇒ Object



63
64
65
# File 'app/models/active_admin/favorites/favorite.rb', line 63

def self.kind_for_type(type_name)
  KIND_BY_STI_TYPE.fetch(type_name)
end

.macro_assignments_from_macros(macros) ⇒ Object



137
138
139
140
141
142
143
144
145
146
147
# File 'app/models/active_admin/favorites/favorite.rb', line 137

def self.macro_assignments_from_macros(macros)
  Array(macros).filter_map do |macro|
    next unless macro["type"] == "template"

    {
      "enabled" => "1",
      "attribute" => macro["attribute"],
      "name" => macro["name"]
    }
  end
end

.model_nameObject



51
52
53
# File 'app/models/active_admin/favorites/favorite.rb', line 51

def self.model_name
  @model_name ||= ActiveModel::Name.new(self, nil, "Favorite")
end

.policy_classObject



55
56
57
# File 'app/models/active_admin/favorites/favorite.rb', line 55

def self.policy_class
  ActiveAdmin::Favorites::FavoritePolicy
end

.ransackable_attributes_for(resource_key) ⇒ Object



111
112
113
114
115
116
117
118
119
120
# File 'app/models/active_admin/favorites/favorite.rb', line 111

def self.ransackable_attributes_for(resource_key)
  resource_class = resource_class_for(resource_key)
  return [] unless resource_class

  if resource_class.respond_to?(:ransackable_attributes)
    resource_class.ransackable_attributes
  else
    []
  end
end

.resource_class_for(resource_key) ⇒ Object



122
123
124
# File 'app/models/active_admin/favorites/favorite.rb', line 122

def self.resource_class_for(resource_key)
  active_admin_resource_for(resource_key)&.resource_class
end

.resource_label_for(resource_key) ⇒ Object



87
88
89
90
91
92
# File 'app/models/active_admin/favorites/favorite.rb', line 87

def self.resource_label_for(resource_key)
  return resource_key.humanize if resource_key.blank?

  config = active_admin_resource_for(resource_key)
  config&.resource_label || resource_key.tr("_", " ").titleize
end

.sanitize_query_string(raw_query_string) ⇒ Object



67
68
69
70
71
# File 'app/models/active_admin/favorites/favorite.rb', line 67

def self.sanitize_query_string(raw_query_string)
  return if raw_query_string.blank?

  QueryParams.build(QueryParams.parse(raw_query_string))
end

.sti_class_for_kind(kind) ⇒ Object



59
60
61
# File 'app/models/active_admin/favorites/favorite.rb', line 59

def self.sti_class_for_kind(kind)
  STI_TYPE_BY_KIND.fetch(kind.to_s).constantize
end

.suggested_name(resource_key:, query_string:, kind: "filters") ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'app/models/active_admin/favorites/favorite.rb', line 73

def self.suggested_name(resource_key:, query_string:, kind: "filters")
  label = resource_label_for(resource_key)
  summary =
    case kind
    when "lens"
      I18n.t("active_admin.favorites.lens_summary", default: "Page layout")
    when "combined"
      [filter_summary_for(query_string, macros: []), I18n.t("active_admin.favorites.lens_summary", default: "Page layout")].compact.join(" · ")
    else
      filter_summary_for(query_string, macros: [])
    end
  [label, summary].compact.join("").truncate(120)
end

.table_nameObject



47
48
49
# File 'app/models/active_admin/favorites/favorite.rb', line 47

def self.table_name
  ActiveAdmin::Favorites.config.table_name
end

Instance Method Details

#assign_macros_from_form!(template_assignments:, macros_json:, use_advanced_macros:) ⇒ Object



254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
# File 'app/models/active_admin/favorites/favorite.rb', line 254

def assign_macros_from_form!(template_assignments:, macros_json:, use_advanced_macros:)
  parsed_macros =
    if ActiveModel::Type::Boolean.new.cast(use_advanced_macros) && macros_json.present?
      MacroBuilder.from_json(macros_json)
    else
      MacroBuilder.from_template_assignments(template_assignments)
    end

  self.macros = parsed_macros
  MacroValidator.validate!(macros, resource_key: resource_key)
  strip_query_string_for_macros!
  true
rescue JSON::ParserError
  errors.add(:macros_json, I18n.t("active_admin.favorites.macros_json_invalid"))
  false
rescue MacroValidator::ValidationError => error
  errors.add(:macros, error.message)
  false
end

#detected_rangesObject



217
218
219
# File 'app/models/active_admin/favorites/favorite.rb', line 217

def detected_ranges
  self.class.detected_ranges(query_string:, resource_key: resource_key)
end

#filter_summaryObject



166
167
168
# File 'app/models/active_admin/favorites/favorite.rb', line 166

def filter_summary
  self.class.filter_summary_for(query_string, macros: macros)
end

#index_url(at: Time.zone.now, favorite_id: nil) ⇒ Object



185
186
187
188
189
190
191
192
193
194
195
196
# File 'app/models/active_admin/favorites/favorite.rb', line 185

def index_url(at: Time.zone.now, favorite_id: nil)
  resolved = resolved_query_string(at: at)
  url = resolved.present? ? "#{path}?#{resolved}" : path
  if favorite_id.present?
    separator = url.include?("?") ? "&" : "?"
    url = "#{url}#{separator}favorite_id=#{favorite_id}"
  elsif id.present? && layout.present?
    separator = url.include?("?") ? "&" : "?"
    url = "#{url}#{separator}favorite_id=#{id}"
  end
  url
end

#kindObject



149
150
151
# File 'app/models/active_admin/favorites/favorite.rb', line 149

def kind
  self.class.kind_for_type(type)
end

#kind=(value) ⇒ Object



153
154
155
# File 'app/models/active_admin/favorites/favorite.rb', line 153

def kind=(value)
  self.type = self.class.sti_class_for_kind(value).name
end

#kind_labelObject



274
275
276
# File 'app/models/active_admin/favorites/favorite.rb', line 274

def kind_label
  I18n.t("active_admin.favorites.kinds.#{kind}", default: kind.humanize)
end

#layout_objectObject



174
175
176
# File 'app/models/active_admin/favorites/favorite.rb', line 174

def layout_object
  ViewLens::Layout.new(layout || {})
end

#macro_form_rowsObject



221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'app/models/active_admin/favorites/favorite.rb', line 221

def macro_form_rows
  rows_by_attribute = {}

  detected_ranges.each do |range|
    rows_by_attribute[range[:attribute]] = {
      attribute: range[:attribute],
      gteq: range[:gteq],
      lteq: range[:lteq],
      enabled: false,
      name: "previous_calendar_month"
    }
  end

  Array(macros).each do |macro|
    next unless macro["type"] == "template"

    attribute = macro["attribute"]
    rows_by_attribute[attribute] ||= {attribute: attribute}
    rows_by_attribute[attribute][:enabled] = true
    rows_by_attribute[attribute][:name] = macro["name"]
  end

  rows_by_attribute.values
end

#macros_json_for_formObject



246
247
248
# File 'app/models/active_admin/favorites/favorite.rb', line 246

def macros_json_for_form
  macros_json.presence || JSON.pretty_generate(macros)
end

#open_url(at: Time.zone.now) ⇒ Object



209
210
211
212
213
214
215
# File 'app/models/active_admin/favorites/favorite.rb', line 209

def open_url(at: Time.zone.now)
  if is_a?(LensFavorite)
    (action == "show") ? show_url : index_url(at: at)
  else
    index_url(at: at)
  end
end

#owned_by?(user) ⇒ Boolean

Returns:

  • (Boolean)


250
251
252
# File 'app/models/active_admin/favorites/favorite.rb', line 250

def owned_by?(user)
  public_send(:"#{ActiveAdmin::Favorites.config.user_foreign_key}") == user.id
end

#promote_to_kind!(value) ⇒ Object



157
158
159
160
161
162
163
164
# File 'app/models/active_admin/favorites/favorite.rb', line 157

def promote_to_kind!(value)
  sti_class = self.class.sti_class_for_kind(value)
  return self if is_a?(sti_class)

  promoted = becomes(sti_class)
  promoted.type = sti_class.name
  promoted
end

#resolved_query_string(at: Time.zone.now) ⇒ Object



178
179
180
181
182
183
# File 'app/models/active_admin/favorites/favorite.rb', line 178

def resolved_query_string(at: Time.zone.now)
  return query_string if macros.blank?

  q_overrides = MacroResolver.call(macros: macros, at: at)
  QueryParams.merge_query_string(query_string, q_overrides: q_overrides)
end

#resource_labelObject



170
171
172
# File 'app/models/active_admin/favorites/favorite.rb', line 170

def resource_label
  self.class.resource_label_for(resource_key)
end

#show_url(favorite_id: nil) ⇒ Object



198
199
200
201
202
203
204
205
206
207
# File 'app/models/active_admin/favorites/favorite.rb', line 198

def show_url(favorite_id: nil)
  return path if path.blank?

  if favorite_id.present? || (id.present? && layout.present?)
    favorite_param = favorite_id || id
    "#{path}?favorite_id=#{favorite_param}"
  else
    path
  end
end