Class: Wallaby::ActiveRecord::ModelDecorator

Inherits:
ModelDecorator
  • Object
show all
Defined in:
lib/adapters/wallaby/active_record/model_decorator.rb,
lib/adapters/wallaby/active_record/model_decorator/fields_builder.rb,
lib/adapters/wallaby/active_record/model_decorator/title_field_finder.rb,
lib/adapters/wallaby/active_record/model_decorator/fields_builder/sti_builder.rb,
lib/adapters/wallaby/active_record/model_decorator/fields_builder/association_builder.rb,
lib/adapters/wallaby/active_record/model_decorator/fields_builder/polymorphic_builder.rb

Overview

Modal decorator for Wallaby::ActiveRecord

Defined Under Namespace

Classes: FieldsBuilder, TitleFieldFinder

Constant Summary collapse

INDEX_EXCLUSIVE_DATA_TYPES =

Data types to exclude for #index_field_names

%w[
  binary citext hstore json jsonb tsvector xml
  blob mediumblob longblob text mediumtext longtext
].freeze
SHOW_EXCLUSIVE_CLASS_NAMES =

Classes to exclude for #show_field_names

%w[ActiveStorage::Attachment ActiveStorage::Blob].freeze
FORM_EXCLUSIVE_DATA_TYPES =

Fields to exclude for #form_field_names

%w[created_at updated_at].freeze

Instance Method Summary collapse

Instance Method Details

#fieldsActiveSupport::HashWithIndifferentAccess

Original metadata information of the primative and association fields pulling out from the ActiveRecord model.

It needs to be frozen so that we can keep the metadata intact.

Examples:

sample fields metadata:

model_decorator.fields
# =>
{
  # general field
  id: { name: 'id', type: 'integer', label: 'Id' },
  # association field
  category: {
    name: 'category',
    type: 'belongs_to',
    label: 'Category',
    is_association: true,
    is_through: false,
    has_scope: false,
    foreign_key: 'category_id',
    class: Category
  }
}

Returns:

  • (ActiveSupport::HashWithIndifferentAccess)

    metadata



42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/adapters/wallaby/active_record/model_decorator.rb', line 42

def fields
  # NOTE: Need to check the database and table's existence before building up the metadata
  # so that the database creation and migration related task can be executed.
  @fields ||= ::ActiveSupport::HashWithIndifferentAccess.new.tap do |hash|
    next hash.default = {} unless @model_class.table_exists?

    hash.merge!(association_fields)
    hash.merge!(general_fields)
  rescue ::ActiveRecord::NoDatabaseError
    hash.default = {}
  end.freeze
end

#form_active_errors(resource) ⇒ ActiveModel::Errors

Returns errors for resource.

Returns:

  • (ActiveModel::Errors)

    errors for resource



108
109
110
# File 'lib/adapters/wallaby/active_record/model_decorator.rb', line 108

def form_active_errors(resource)
  resource.errors
end

#form_field_namesArray<String>

Returns a list of field names for form (new/edit) page (note: timestamps fields (e.g. created_at/updated_at) and complex relation fields are excluded).

Returns:

  • (Array<String>)

    a list of field names for form (new/edit) page (note: timestamps fields (e.g. created_at/updated_at) and complex relation fields are excluded).



96
97
98
99
100
101
102
103
104
105
# File 'lib/adapters/wallaby/active_record/model_decorator.rb', line 96

def form_field_names
  @form_field_names ||=
    form_fields.reject do |field_name, |
      field_name == primary_key || # primary key
        [:has_scope] || # not a regular association
        [:is_through] || # not direct association
        [:hidden] || # e.g. foreign keys, polymorphic columns
        FORM_EXCLUSIVE_DATA_TYPES.include?(field_name) # not the types for form page
    end.keys
end

#form_fieldsActiveSupport::HashWithIndifferentAccess

A copy of #fields for form (new/edit) page

Returns:

  • (ActiveSupport::HashWithIndifferentAccess)

    metadata



69
70
71
# File 'lib/adapters/wallaby/active_record/model_decorator.rb', line 69

def form_fields
  @form_fields ||= Utils.clone(fields)
end

#guess_title(resource) ⇒ String

To guess the title for resource.

It will go through the fields and try to find out the one that looks like a name or text representing this resource. Otherwise, it will fall back to primary key.

Parameters:

  • resource (Object)

Returns:

  • (String)

    the title of given resource



134
135
136
137
138
# File 'lib/adapters/wallaby/active_record/model_decorator.rb', line 134

def guess_title(resource)
  title_field_finder.find.try do |title_method|
    resource.try(title_method)
  end
end

#index_field_namesArray<String>

Returns a list of field names for index page (note: only primitive SQL types are included).

Returns:

  • (Array<String>)

    a list of field names for index page (note: only primitive SQL types are included).



74
75
76
77
78
79
80
81
82
83
# File 'lib/adapters/wallaby/active_record/model_decorator.rb', line 74

def index_field_names
  @index_field_names ||=
    reposition(
      index_fields.reject do |_field_name, |
        [:hidden] || # e.g. foreign keys, polymorphic columns
          [:is_association] || # associations
          INDEX_EXCLUSIVE_DATA_TYPES.include?([:type]) # not the types for index page
      end.keys
    )
end

#index_fieldsActiveSupport::HashWithIndifferentAccess

A copy of #fields for index page

Returns:

  • (ActiveSupport::HashWithIndifferentAccess)

    metadata



57
58
59
# File 'lib/adapters/wallaby/active_record/model_decorator.rb', line 57

def index_fields
  @index_fields ||= Utils.clone(fields)
end

#primary_keyString

Returns primary key for the resource.

Returns:

  • (String)

    primary key for the resource



113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/adapters/wallaby/active_record/model_decorator.rb', line 113

def primary_key
  @primary_key ||=
    @model_class.primary_key || Wallaby::Logger.warn(<<~WARNING)
      No primary key is found and all resource pages (show/edit) will fail to build.

      If the resource pages are needed, try:

      - Set `self.primary_key=` in the model #{@model_class}
      - Set `self.primary_key=` in the decorator

      Otherwise, configure to disable access to new/show/edit/destroy
    WARNING
end

#show_field_namesArray<String>

Returns a list of field names for show page (note: ActiveStorage fields are excluded).

Returns:

  • (Array<String>)

    a list of field names for show page (note: ActiveStorage fields are excluded).



86
87
88
89
90
91
92
# File 'lib/adapters/wallaby/active_record/model_decorator.rb', line 86

def show_field_names
  @show_field_names ||=
    show_fields.reject do |_field_name, |
      [:hidden] || # e.g. foreign keys, polymorphic columns
        SHOW_EXCLUSIVE_CLASS_NAMES.include?([:class].try(:name)) # not the types for show page
    end.keys
end

#show_fieldsActiveSupport::HashWithIndifferentAccess

A copy of #fields for show page

Returns:

  • (ActiveSupport::HashWithIndifferentAccess)

    metadata



63
64
65
# File 'lib/adapters/wallaby/active_record/model_decorator.rb', line 63

def show_fields
  @show_fields ||= Utils.clone(fields)
end