Module: Moderate::Macros

Defined in:
lib/moderate/macros.rb

Overview

The class-level DSL the gem adds to every ActiveRecord model.

The engine does ‘ActiveSupport.on_load(:active_record) { extend Moderate::Macros }`, so `has_reporting_and_blocking`, `has_reportable_content`, and `moderates` become class methods on ActiveRecord::Base — readable plain-English declarations that sit alongside the rest of a host’s stack (‘has_credits`, `has_wallets`, `has_api_keys`):

class User    < ApplicationRecord; has_reporting_and_blocking; end
class Listing < ApplicationRecord; has_reportable_content :title, :description; end
class Message < ApplicationRecord; moderates :body, mode: :flag; end

Each macro is exact sugar for an ‘include` + a declaration — the README documents both forms as equivalent. The macros are deliberately thin: they lazily include the right concern (only models that opt in pay for it) and then forward to that concern’s declaration method. All behavior lives in the concerns, never here.

Instance Method Summary collapse

Instance Method Details

#has_reportable_content(*fields) ⇒ Object

‘has_reportable_content(*fields)` — mark this model as REPORTABLE content, optionally narrowing to specific fields. Bare `has_reportable_content` (no fields) means “the whole record is reportable” (the field whitelist stays empty, and a blank reported_field is then allowed — see Reportable#reportable_field_allowed?).

Equivalent to ‘include Moderate::Reportable` + `reportable_fields(*fields)`.



55
56
57
58
59
# File 'lib/moderate/macros.rb', line 55

def has_reportable_content(*fields)
  include Moderate::Reportable unless include?(Moderate::Reportable)
  reportable_fields(*fields) if fields.any?
  self
end

#has_reporting_and_blockingObject

‘has_reporting_and_blocking` — make this model an ACTOR in the Trust & Safety system: it can report content/users and block/unblock other users (report!/block!/unblock!/blocks?/blocked_by?/blocked_with?, plus the block & report associations), and — since the actor is usually itself reportable and is the be-banned target — it’s also made reportable. One macro, both halves.

Equivalent to ‘include Moderate::Actor`. Idempotent: re-declaring (or both macro + explicit include) won’t double-include.



44
45
46
# File 'lib/moderate/macros.rb', line 44

def has_reporting_and_blocking
  include Moderate::Actor unless include?(Moderate::Actor)
end

#moderates(*fields, mode: nil, with: nil) ⇒ Object

‘moderates(*fields, mode:, with:)` — filter one or more fields before they’re saved. ‘mode:`/`with:` default to nil so the field inherits the global `config.default_filter_mode` / `config.filter_adapter` (resolved inside `config.filter`), letting a bare `moderates :body` Just Work.

Two things happen, per field:

1. The field is registered on the model (Moderate::ContentFilterable), so
   the :block validation and :flag after_commit hook run for it.
2. A Configuration FilterPolicy is recorded keyed by [class_name, field],
   so `Moderate.filter_policy_for` (which the concern consults at
   validate/commit time, walking the ancestor chain) can find the field's
   adapter + mode. This is the exact twin of `config.filter "Class", :field,
   with:, mode:` in the initializer — same storage, same resolution.

Equivalent to ‘include Moderate::ContentFilterable` + `moderates_fields(*fields)` plus the per-field policy registration.



77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/moderate/macros.rb', line 77

def moderates(*fields, mode: nil, with: nil)
  include Moderate::ContentFilterable unless include?(Moderate::ContentFilterable)
  moderates_fields(*fields)

  fields.each do |field|
    # `config.filter` normalizes/validates the adapter+mode and stores the
    # policy; passing `self` (the class) lets it record the class NAME string.
    Moderate.config.filter(self, field, with: with, mode: mode)
  end

  self
end