Class: LcpRuby::Metadata::ModelDefinition

Inherits:
Object
  • Object
show all
Defined in:
lib/lcp_ruby/metadata/model_definition.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attrs = {}) ⇒ ModelDefinition

Returns a new instance of ModelDefinition.



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
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 16

def initialize(attrs = {})
  @name = attrs[:name].to_s
  @label = attrs[:label] || @name.humanize
  @label_plural = attrs[:label_plural] || @label.pluralize
  @table_name = attrs[:table_name] || @name.pluralize
  @fields = attrs[:fields] || []
  @validations = attrs[:validations] || []
  @associations = attrs[:associations] || []
  @scopes = attrs[:scopes] || []
  @events = attrs[:events] || []
  @options = attrs[:options] || {}
  @display_templates = attrs[:display_templates] || {}
  @virtual_columns = attrs[:virtual_columns] || attrs[:aggregates] || {}
  @indexes = attrs[:indexes] || []
  @positioning_config = attrs[:positioning_config]
  @data_source_config = attrs[:data_source_config]
  @raw_hash = attrs[:raw_hash]
  @source_path = attrs[:source_path]
  @source_type = attrs[:source_type]
  @abstract = attrs.fetch(:abstract, false)
  @inherits = attrs[:inherits]
  @sti_child = attrs.fetch(:sti_child, false)
  @bind_to = attrs[:bind_to]
  @bind_to_apply = attrs[:bind_to_apply] || []
  @slug_field = attrs[:slug_field]&.to_s.presence
  # i18n_check Phase 3a façade source-location capture. Set by
  # ModelBuilder; nil for YAML-loaded models (Pass 3 covers YAML).
  @label_source_loc = attrs[:label_source_loc]
  @label_plural_source_loc = attrs[:label_plural_source_loc]

  validate!
end

Instance Attribute Details

#abstractObject (readonly)

Returns the value of attribute abstract.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def abstract
  @abstract
end

#associationsObject (readonly)

Returns the value of attribute associations.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def associations
  @associations
end

#bind_toObject (readonly)

Returns the value of attribute bind_to.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def bind_to
  @bind_to
end

#bind_to_applyObject (readonly)

Returns the value of attribute bind_to_apply.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def bind_to_apply
  @bind_to_apply
end

#data_source_configObject (readonly)

Returns the value of attribute data_source_config.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def data_source_config
  @data_source_config
end

#display_templatesObject (readonly)

Returns the value of attribute display_templates.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def display_templates
  @display_templates
end

#eventsObject (readonly)

Returns the value of attribute events.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def events
  @events
end

#fieldsObject (readonly)

Returns the value of attribute fields.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def fields
  @fields
end

#indexesObject (readonly)

Returns the value of attribute indexes.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def indexes
  @indexes
end

#inheritsObject (readonly)

Returns the value of attribute inherits.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def inherits
  @inherits
end

#labelObject (readonly)

Returns the value of attribute label.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def label
  @label
end

#label_pluralObject (readonly)

Returns the value of attribute label_plural.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def label_plural
  @label_plural
end

#label_plural_source_locObject (readonly)

Returns the value of attribute label_plural_source_loc.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def label_plural_source_loc
  @label_plural_source_loc
end

#label_source_locObject (readonly)

Returns the value of attribute label_source_loc.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def label_source_loc
  @label_source_loc
end

#nameObject (readonly)

Returns the value of attribute name.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def name
  @name
end

#optionsObject (readonly)

Returns the value of attribute options.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def options
  @options
end

#positioning_configObject

Returns the value of attribute positioning_config.



11
12
13
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 11

def positioning_config
  @positioning_config
end

#raw_hashObject (readonly)

Returns the value of attribute raw_hash.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def raw_hash
  @raw_hash
end

#scopesObject (readonly)

Returns the value of attribute scopes.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def scopes
  @scopes
end

#slug_fieldObject (readonly)

Returns the value of attribute slug_field.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def slug_field
  @slug_field
end

#source_pathObject

Returns the value of attribute source_path.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def source_path
  @source_path
end

#source_typeObject

Returns the value of attribute source_type.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def source_type
  @source_type
end

#sti_childObject (readonly)

Returns the value of attribute sti_child.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def sti_child
  @sti_child
end

#table_nameObject

Returns the value of attribute table_name.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def table_name
  @table_name
end

#validationsObject (readonly)

Returns the value of attribute validations.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def validations
  @validations
end

#virtual_columnsObject (readonly) Also known as: aggregates

Returns the value of attribute virtual_columns.



4
5
6
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 4

def virtual_columns
  @virtual_columns
end

Class Method Details

.from_hash(hash) ⇒ Object



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
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 49

def self.from_hash(hash)
  new(
    name: hash["name"],
    label: hash["label"],
    label_plural: hash["label_plural"],
    table_name: hash["table_name"],
    fields: parse_fields(hash["fields"]),
    validations: parse_validations(hash["validations"]),
    associations: parse_associations(hash["associations"], hash["name"]),
    scopes: (hash["scopes"] || []).map { |s| HashUtils.stringify_deep(s) },
    events: parse_events(hash["events"]),
    options: hash["options"] || {},
    display_templates: parse_display_templates(hash["display_templates"]),
    virtual_columns: parse_virtual_columns(hash),
    indexes: parse_indexes(hash["indexes"]),
    positioning_config: normalize_positioning(hash["positioning"]),
    data_source_config: hash["data_source"],
    raw_hash: hash,
    abstract: hash["abstract"] == true,
    inherits: hash["inherits"],
    sti_child: hash[ModelInheritanceResolver::STI_CHILD_KEY] == true,
    bind_to: hash["bind_to"],
    bind_to_apply: hash["bind_to_apply"],
    slug_field: hash["slug_field"],
    label_source_loc: hash["_label_source_loc"],
    label_plural_source_loc: hash["_label_plural_source_loc"]
  )
end

.parse_associations(associations_data, owner_name = nil) ⇒ Object



565
566
567
568
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 565

def self.parse_associations(associations_data, owner_name = nil)
  return [] unless associations_data.is_a?(Array)
  associations_data.map { |a| AssociationDefinition.from_hash(a, owner_name) }
end

.parse_display_templates(data) ⇒ Object



599
600
601
602
603
604
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 599

def self.parse_display_templates(data)
  return {} unless data.is_a?(Hash)
  data.each_with_object({}) do |(name, hash), result|
    result[name.to_s] = DisplayTemplateDefinition.from_hash(name, hash)
  end
end

.parse_events(events_data) ⇒ Object



570
571
572
573
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 570

def self.parse_events(events_data)
  return [] unless events_data.is_a?(Array)
  events_data.map { |e| EventDefinition.from_hash(e) }
end

.parse_fields(fields_data) ⇒ Object



555
556
557
558
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 555

def self.parse_fields(fields_data)
  return [] unless fields_data.is_a?(Array)
  fields_data.map { |f| FieldDefinition.from_hash(f) }
end

.parse_indexes(data) ⇒ Object



606
607
608
609
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 606

def self.parse_indexes(data)
  return [] unless data.is_a?(Array)
  data.map { |idx| HashUtils.stringify_deep(idx) }
end

.parse_validations(validations_data) ⇒ Object



560
561
562
563
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 560

def self.parse_validations(validations_data)
  return [] unless validations_data.is_a?(Array)
  validations_data.map { |v| ValidationDefinition.new(v) }
end

.parse_vc_hash(data, result) ⇒ Object



593
594
595
596
597
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 593

def self.parse_vc_hash(data, result)
  data.each do |name, hash|
    result[name.to_s] = VirtualColumnDefinition.from_hash(name, hash)
  end
end

.parse_virtual_columns(hash) ⇒ Object

Parse both “aggregates” and “virtual_columns” keys, merge, and error on collision.



576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 576

def self.parse_virtual_columns(hash)
  agg_data = hash["aggregates"] || {}
  vc_data = hash["virtual_columns"] || {}

  if agg_data.is_a?(Hash) && vc_data.is_a?(Hash)
    collisions = agg_data.keys.map(&:to_s) & vc_data.keys.map(&:to_s)
    if collisions.any?
      raise MetadataError, "Model '#{hash['name']}': name collision between aggregates and virtual_columns: #{collisions.join(', ')}"
    end
  end

  merged = {}
  parse_vc_hash(agg_data, merged) if agg_data.is_a?(Hash)
  parse_vc_hash(vc_data, merged) if vc_data.is_a?(Hash)
  merged
end

Instance Method Details

#abstract?Boolean

Returns:

  • (Boolean)


148
149
150
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 148

def abstract?
  @abstract == true
end

#api_model?Boolean

Returns true if this model is backed by an external data source (REST API, host adapter).

Returns:

  • (Boolean)


193
194
195
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 193

def api_model?
  @data_source_config.is_a?(Hash) && @data_source_config["type"].present?
end

#auditing?Boolean

Returns:

  • (Boolean)


228
229
230
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 228

def auditing?
  boolean_or_hash_option("auditing").first
end

#auditing_optionsObject



232
233
234
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 232

def auditing_options
  boolean_or_hash_option("auditing").last
end

#belongs_to_fk_mapObject

Returns a Hash mapping FK field name to its belongs_to AssociationDefinition. e.g. { “company_id” => <AssociationDefinition name=“company”> } Memoized since it’s called from multiple places (ColumnSet, DependencyCollector, PermissionEvaluator). Includes tree-generated parent association when tree? is enabled.



460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 460

def belongs_to_fk_map
  @belongs_to_fk_map ||= begin
    map = associations
      .select { |a| a.type == "belongs_to" && a.foreign_key.present? }
      .each_with_object({}) { |a, h| h[a.foreign_key] = a }

    # Add tree-generated parent association if not already present
    if tree? && !map.key?(tree_parent_field)
      map[tree_parent_field] = AssociationDefinition.new(
        type: "belongs_to",
        name: tree_parent_name,
        target_model: name,
        foreign_key: tree_parent_field,
        required: false
      )
    end

    map
  end
end

#bind_to?Boolean

Returns true if this model binds to an existing ActiveRecord class in the host app.

Returns:

  • (Boolean)


170
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 170

def bind_to? = bind_to.present?

#bind_to_auto_featuresObject

Bind-to applicator features that must run even if not listed in ‘bind_to_apply`, because the corresponding YAML-declared virtual fields are otherwise unreachable at runtime.



367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 367

def bind_to_auto_features
  features = []
  features << "enums" if enum_fields.any?(&:virtual?)
  features << "service_accessors" if fields.any?(&:service_accessor?)
  # Auto-enable defaults so bind_to models get the same default-on-create
  # semantics as dynamic LCP models. Without this, fields like
  # `theme: enum, default: auto, source: json_field` on a bind_to model
  # never get the after_initialize callback that writes the default into
  # the underlying store — host.create! leaves the JSON key absent.
  features << "defaults" if fields.any? { |f| !f.default.nil? }
  features
end

#custom_fields_enabled?Boolean

Returns:

  • (Boolean)


144
145
146
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 144

def custom_fields_enabled?
  options.fetch("custom_fields", false) == true
end

#data_source_typeObject

Returns the data source type as a symbol: :db, :rest_json, or :host.



198
199
200
201
202
203
204
205
206
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 198

def data_source_type
  return :db unless api_model?

  case @data_source_config["type"]
  when "rest_json" then :rest_json
  when "host" then :host
  else :db
  end
end

#declared_macrosObject

Returns the macros this model declares, as an array of symbols. Consumed by Metadata::ReservedNames.reserved_clashes_for_macro to iterate macro-specific reserved-name lookups, and by future Phase 3 ConfigurationValidator passes that need a single source of truth for “which macros does this model declare.” Memoized.



435
436
437
438
439
440
441
442
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 435

def declared_macros
  @declared_macros ||= [].tap do |m|
    m << :auditing if auditing?
    m << :tree if tree?
    m << :positioning if positioned?
    m << :workflow if workflow?
  end
end

#display_bind_toObject

Normalized bind_to class name for display in error / warning / log messages: strips the leading “::” so output reads “LcpRuby::User” not “::LcpRuby::User”. Returns nil for non-bind_to models.



175
176
177
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 175

def display_bind_to
  bind_to&.to_s&.delete_prefix("::")
end

#display_template(name = "default") ⇒ Object



380
381
382
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 380

def display_template(name = "default")
  display_templates[name.to_s]
end

#each_enum_valueObject

Yields per-enum-value labels. The source location is the enclosing field declaration (‘field :status, :enum, values: { … }`), not the specific value entry — see spec §I “Special case: enum value labels”. Pass 2 (AST) catches the precise value pair.



116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 116

def each_enum_value
  return enum_for(:each_enum_value) unless block_given?
  fields.each do |field|
    next unless field.enum?
    field.enum_values.each do |entry|
      next unless entry.is_a?(Hash)
      value = entry["value"] || entry[:value]
      next if value.nil?
      label  = entry["label"] || entry[:label]
      source = entry["_label_source_loc"] || entry[:_label_source_loc]
      yield(label: label, field: field.name, value: value, source: source)
    end
  end
end

#each_fieldObject

Yields per-field label info for the i18n_check lint walker. Includes EVERY field — author-set explicit labels and humanize fallbacks alike. The walker uses the missing-translation check to decide whether to flag (a humanize-fallback field with no locale entry is still broken UX in non-default locales). Source is nil for fields without an explicit DSL ‘label:`.



96
97
98
99
100
101
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 96

def each_field
  return enum_for(:each_field) unless block_given?
  fields.each do |field|
    yield(label: field.label, field: field.name, source: field.label_source_loc)
  end
end

#enum_fieldsObject



360
361
362
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 360

def enum_fields
  fields.select(&:enum?)
end

#field(name) ⇒ Object



325
326
327
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 325

def field(name)
  fields.find { |f| f.name == name.to_s }
end

#find_belongs_to(name) ⇒ Object

Look up a belongs_to association by name. Returns nil when the name doesn’t match or matches a non-belongs_to (has_many, has_one, polymorphic through) association.



332
333
334
335
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 332

def find_belongs_to(name)
  assoc = associations.find { |a| a.name == name.to_s }
  assoc if assoc&.belongs_to?
end

#has_index_for?(field_name) ⇒ Boolean

Returns:

  • (Boolean)


344
345
346
347
348
349
350
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 344

def has_index_for?(field_name)
  name = field_name.to_s
  indexes.any? { |idx|
    cols = Array(idx["columns"] || idx["column"])
    cols.include?(name)
  }
end

#has_uniqueness_validation?(field_name) ⇒ Boolean

Returns:

  • (Boolean)


337
338
339
340
341
342
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 337

def has_uniqueness_validation?(field_name)
  name = field_name.to_s
  f = field(name)
  (f && f.validations.any? { |v| v.type == "uniqueness" }) ||
    validations.any? { |v| v.type == "uniqueness" && v.target_field == name }
end

#label_methodObject



140
141
142
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 140

def label_method
  options["label_method"] || "to_s"
end

#managed_fk_columnsObject

Required column names for every ‘lcp_managed: true` belongs_to on this model. Polymorphic associations contribute both `<name>_id` and `<name>_type`; non-polymorphic contribute just the FK column. Used by SchemaManager (which columns to add) and Engine (the auto_migrate=false escape hatch). Memoized — ModelDefinition is immutable after initialize, same invariant `belongs_to_fk_map` already relies on.



186
187
188
189
190
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 186

def managed_fk_columns
  @managed_fk_columns ||= associations
    .select { |a| a.belongs_to? && a.lcp_managed? }
    .flat_map { |a| a.polymorphic ? [ a.foreign_key, "#{a.name}_type" ] : [ a.foreign_key ] }
end

#parameterized_scope(name) ⇒ Object



356
357
358
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 356

def parameterized_scope(name)
  parameterized_scopes.find { |s| s["name"] == name.to_s }
end

#parameterized_scopesObject



352
353
354
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 352

def parameterized_scopes
  scopes.select { |s| s["type"] == "parameterized" }
end

#positioned?Boolean

Returns:

  • (Boolean)


396
397
398
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 396

def positioned?
  @positioning_config.present?
end

#positioning_fieldObject



400
401
402
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 400

def positioning_field
  positioning_config&.fetch("field", "position") || "position"
end

#positioning_scopeObject



404
405
406
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 404

def positioning_scope
  Array(positioning_config&.fetch("scope", nil)).compact
end

#primary_key_columnObject

Neutral primary-key column accessor. Defaults to “id” to match Rails. Overridden by custom_primary_key.md Tier 2 when/if that spec lands.



446
447
448
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 446

def primary_key_column
  "id"
end

#primary_key_typeObject

Neutral primary-key type accessor. Defaults to :bigint to match Rails. Overridden by custom_primary_key.md Tier 1 when/if that spec lands.



452
453
454
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 452

def primary_key_type
  :bigint
end

#resolved_labelObject

Returns the singular model label resolved via i18n.



132
133
134
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 132

def resolved_label
  I18n.t("lcp_ruby.models.#{name}.one", default: @label)
end

#scope_namesObject

Returns the names of named scopes declared in the YAML ‘scopes:` block as Strings. Scopes are stored as String-keyed Hashes after `HashUtils.stringify_deep` (see `from_hash`), so the right accessor is `s`. Falls back to Symbol key, then to the entry’s ‘to_s` for legacy bare-symbol forms.



108
109
110
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 108

def scope_names
  scopes.map { |s| s.is_a?(Hash) ? (s["name"] || s[:name]).to_s : s.to_s }
end

#soft_delete?Boolean

Returns:

  • (Boolean)


216
217
218
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 216

def soft_delete?
  boolean_or_hash_option("soft_delete").first
end

#soft_delete_columnObject



224
225
226
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 224

def soft_delete_column
  soft_delete_options.fetch("column", "discarded_at")
end

#soft_delete_optionsObject



220
221
222
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 220

def soft_delete_options
  boolean_or_hash_option("soft_delete").last
end

#source_location_for(attribute) ⇒ Object

i18n_check Phase 3a façade — returns ‘{ “file” => …, “line” => N }` for the DSL line that set this attribute, or nil when the model was loaded from YAML (or the attribute was not set at all). See `docs/design/i18n_consistency_check.md` §B “Façade method signatures”.



83
84
85
86
87
88
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 83

def source_location_for(attribute)
  case attribute
  when :label        then @label_source_loc
  when :label_plural then @label_plural_source_loc
  end
end

#sti_child?Boolean

Returns:

  • (Boolean)


156
157
158
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 156

def sti_child?
  @sti_child == true
end

#sti_parent?Boolean

Returns:

  • (Boolean)


152
153
154
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 152

def sti_parent?
  options.fetch("sti", false) == true && !sti_child?
end

#sti_parent_nameObject

Returns the STI parent model name, or nil if not an STI child.



161
162
163
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 161

def sti_parent_name
  @inherits if sti_child?
end

#supported_filter_operatorsObject

Returns supported filter operators for this model’s data source. Falls back to a standard set for DB models.



210
211
212
213
214
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 210

def supported_filter_operators
  return nil unless api_model?

  @data_source_config["supported_operators"]
end

#timestamps?Boolean

Returns:

  • (Boolean)


136
137
138
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 136

def timestamps?
  options.fetch("timestamps", true)
end

#tree?Boolean

Returns:

  • (Boolean)


289
290
291
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 289

def tree?
  boolean_or_hash_option("tree").first
end

#tree_children_nameObject



301
302
303
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 301

def tree_children_name
  tree_options.fetch("children_name", "children")
end

#tree_dependentObject



309
310
311
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 309

def tree_dependent
  tree_options.fetch("dependent", "destroy")
end

#tree_max_depthObject



313
314
315
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 313

def tree_max_depth
  tree_options.fetch("max_depth", 10)
end

#tree_optionsObject



293
294
295
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 293

def tree_options
  @tree_options ||= boolean_or_hash_option("tree").last
end

#tree_ordered?Boolean

Returns:

  • (Boolean)


317
318
319
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 317

def tree_ordered?
  tree_options.fetch("ordered", false) == true
end

#tree_parent_fieldObject



297
298
299
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 297

def tree_parent_field
  tree_options.fetch("parent_field", "parent_id")
end

#tree_parent_nameObject



305
306
307
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 305

def tree_parent_name
  tree_options.fetch("parent_name", "parent")
end

#tree_position_fieldObject



321
322
323
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 321

def tree_position_field
  tree_options.fetch("position_field", "position")
end

#userstamp_column_namesObject



278
279
280
281
282
283
284
285
286
287
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 278

def userstamp_column_names
  return [] unless userstamps?

  cols = [ userstamps_creator_field, userstamps_updater_field ]
  if userstamps_store_name?
    cols << userstamps_creator_name_field
    cols << userstamps_updater_name_field
  end
  cols
end

#userstamps?Boolean

Returns:

  • (Boolean)


236
237
238
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 236

def userstamps?
  boolean_or_hash_option("userstamps").first
end

#userstamps_creator_association_nameObject



256
257
258
259
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 256

def userstamps_creator_association_name
  userstamps_options.fetch("created_by_association",
    strip_id_suffix(userstamps_creator_field))
end

#userstamps_creator_fieldObject



244
245
246
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 244

def userstamps_creator_field
  userstamps_options.fetch("created_by", "created_by_id")
end

#userstamps_creator_name_fieldObject



266
267
268
269
270
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 266

def userstamps_creator_name_field
  return nil unless userstamps_store_name?
  userstamps_options.fetch("created_by_name_field",
    "#{strip_id_suffix(userstamps_creator_field)}_name")
end

#userstamps_optionsObject



240
241
242
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 240

def userstamps_options
  boolean_or_hash_option("userstamps").last
end

#userstamps_store_name?Boolean

Returns:

  • (Boolean)


252
253
254
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 252

def userstamps_store_name?
  userstamps_options.fetch("store_name", false) == true
end

#userstamps_updater_association_nameObject



261
262
263
264
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 261

def userstamps_updater_association_name
  userstamps_options.fetch("updated_by_association",
    strip_id_suffix(userstamps_updater_field))
end

#userstamps_updater_fieldObject



248
249
250
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 248

def userstamps_updater_field
  userstamps_options.fetch("updated_by", "updated_by_id")
end

#userstamps_updater_name_fieldObject



272
273
274
275
276
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 272

def userstamps_updater_name_field
  return nil unless userstamps_store_name?
  userstamps_options.fetch("updated_by_name_field",
    "#{strip_id_suffix(userstamps_updater_field)}_name")
end

#virtual?Boolean

Returns:

  • (Boolean)


165
166
167
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 165

def virtual?
  table_name == "_virtual"
end

#virtual_column(name) ⇒ Object Also known as: aggregate



384
385
386
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 384

def virtual_column(name)
  virtual_columns[name.to_s]
end

#virtual_column_namesObject Also known as: aggregate_names



388
389
390
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 388

def virtual_column_names
  virtual_columns.keys
end

#workflowObject

Returns the registered workflow object for this model, or nil if no workflow is declared (or Workflow::Registry isn’t available yet). Memoized. Side-benefit: collapses the duplicated workflow_for_model memoizers in presenter/action_set.rb and presenter/layout_builder.rb to a single call site (deferred to follow-up PR).



422
423
424
425
426
427
428
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 422

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

  @workflow = if LcpRuby::Workflow::Registry.available?
    LcpRuby::Workflow::Registry.workflow_for_model(name)
  end
end

#workflow?Boolean

Predicate paralleling auditing?, tree?, positioned?, soft_delete? — true when this model declares a workflow (via Workflow::Registry, populated at engine boot from any of the three sources: YAML/DSL, DB, host adapter). Requires Workflow::Registry to be ‘available?` (Setup.apply! has run); see lib/tasks/lcp_ruby.rake which invokes Setup.apply! before validation.

Returns:

  • (Boolean)


413
414
415
# File 'lib/lcp_ruby/metadata/model_definition.rb', line 413

def workflow?
  !workflow.nil?
end