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