class ModelBase::MetaModel

Constants

SPEC_EXCLUSED_COLS

Attributes

class_name[R]
name[R]

Public Class Methods

new(name) click to toggle source
# File lib/model_base/meta_model.rb, line 7
def initialize(name)
  @name = name
end

Public Instance Methods

[](name) click to toggle source
# File lib/model_base/meta_model.rb, line 69
def [](name)
  raw_columns.detect{|c| c.name == name.to_s}
end
active_record?() click to toggle source
# File lib/model_base/meta_model.rb, line 37
def active_record?
  defined?(ActiveRecord) == "constant" && ActiveRecord.class == Module && model_class < ActiveRecord::Base
end
all_dependencies(required = true) click to toggle source
# File lib/model_base/meta_model.rb, line 110
def all_dependencies(required = true)
  dependencies.values.map{|m| [m] + m.all_dependencies(required)}.flatten.uniq(&:name)
end
columns() click to toggle source
# File lib/model_base/meta_model.rb, line 73
def columns
  @columns ||=
    title_column ? raw_columns : [ColumnAttribute.new(self, 'id', :integer, title: true)] + raw_columns
end
columns_for(type) click to toggle source
# File lib/model_base/meta_model.rb, line 79
def columns_for(type)
  case type
  when :form, :index, :show
    columns.reject{|c| exclude_for?(type, c) }
  when :params     then columns_for(:form).reject{|c| c.name.to_s == 'id'}
  when :spec_index then columns_for(:index).reject{|c| SPEC_EXCLUSED_COLS.include?(c.name)}
  when :spec_show  then columns_for(:show ).reject{|c| SPEC_EXCLUSED_COLS.include?(c.name)}
  when :factory     then columns_for(:params).reject{|c| SPEC_EXCLUSED_COLS.include?(c.name)}
  else
    raise "Unknown template type: #{type.inspect}"
  end
end
dependencies(required = true) click to toggle source
# File lib/model_base/meta_model.rb, line 97
def dependencies(required = true)
  # c: c.required?
  # r: required (the argument)
  #
  # | c \ r | true  | false |
  # |-------|-------|-------|
  # | true  | true  | true  |
  # | false | false | true  |
  raw_columns.select{|c| !required || c.required? }.
    select(&:reference).
    each_with_object({}){|c,d| d[c.reference.name] = c.ref_model }
end
exclude_for?(type, col_attr) click to toggle source
# File lib/model_base/meta_model.rb, line 92
def exclude_for?(type, col_attr)
  excluded_columns = ModelBase.config.send("excluded_columns_of_#{type}")
  excluded_columns.any?{|ex| ex === col_attr.name && !col_attr.title? }
end
factory_bot_let_definition(action: :create) click to toggle source
# File lib/model_base/meta_model.rb, line 135
def factory_bot_let_definition(action: :create)
  'let(:%s) { %s }' % [full_resource_name, factory_bot_to(action)]
end
factory_bot_let_definitions(spacer = " ") click to toggle source
# File lib/model_base/meta_model.rb, line 139
def factory_bot_let_definitions(spacer = "  ")
  deps = all_dependencies
  r = deps.reverse.map(&:factory_bot_let_definition)
  r << "let(:user){ FactoryBot.create(:user) }" unless deps.any?{|m| m.full_resource_name == 'user' }
  r.join("\n" << spacer)
end
factory_bot_method(name, extra) click to toggle source
# File lib/model_base/meta_model.rb, line 118
def factory_bot_method(name, extra)
  extra_str = extra.blank? ? '' : ', ' << extra.map{|k,v| "#{k}: '#{v}'"}.join(', ')
  options = factory_bot_options
  options_str = options.empty? ? '' : ', ' <<  factory_bot_options.join(', ')
  'FactoryBot.%s(:%s%s%s)' % [name, full_resource_name, options_str, extra_str]
end
factory_bot_options() click to toggle source
# File lib/model_base/meta_model.rb, line 114
def factory_bot_options
  dependencies.map{|attr, model| "#{attr}: #{model.full_resource_name}" }
end
factory_bot_to(name, context: nil, index: 1, extra: {}) click to toggle source
# File lib/model_base/meta_model.rb, line 125
def factory_bot_to(name, context: nil, index: 1, extra: {})
  case context
  when :spec_index
    columns_for(:spec_index).delete_if(&:single_sample_only?).delete_if(&:reference).each do |col|
      extra[col.name] = col.sample_value(index)
    end
  end
  factory_bot_method(name, extra)
end
full_resource_name() click to toggle source
# File lib/model_base/meta_model.rb, line 25
def full_resource_name
  name.underscore.gsub('/', '_').sub(/\A_/, '')
end
model_class() click to toggle source
# File lib/model_base/meta_model.rb, line 33
def model_class
  @model_class ||= name.constantize
end
plural_full_resource_name() click to toggle source
# File lib/model_base/meta_model.rb, line 29
def plural_full_resource_name
  full_resource_name.pluralize
end
plural_name() click to toggle source
# File lib/model_base/meta_model.rb, line 13
def plural_name
  name.pluralize
end
plural_resource_name() click to toggle source
# File lib/model_base/meta_model.rb, line 21
def plural_resource_name
  resource_name.pluralize
end
raw_columns() click to toggle source
# File lib/model_base/meta_model.rb, line 65
def raw_columns
  @raw_columns ||= retrieve_columns
end
resource_name() click to toggle source
# File lib/model_base/meta_model.rb, line 17
def resource_name
  name.demodulize.underscore
end
retrieve_columns() click to toggle source
# File lib/model_base/meta_model.rb, line 46
def retrieve_columns
  raw_cols = active_record? ? model_class.columns : model_class.fields.map {|c| c[1] }
  belongs_to_refs = model_class.reflections.values.select{|ref| ref.is_a?(ActiveRecord::Reflection::BelongsToReflection) }
  cols = raw_cols.map do |col|
    ref = belongs_to_refs.detect{|ref| ref.foreign_key == col.name}
    ColumnAttribute.new(self, col.name, col.type, column: col, reference: ref)
  end
  @title_column = nil
  ModelBase.config.title_column_candidates.each do |tcc|
    @title_column = cols.detect{|col| tcc === col.name}
    if @title_column
      @title_column.title = true
      break
    end
  end
  @title_column.linkable = true if @title_column
  cols
end
sample_value() click to toggle source
# File lib/model_base/meta_model.rb, line 146
def sample_value
  @sample_value ||= name.split('').map(&:ord).sum
end
title_column() click to toggle source
# File lib/model_base/meta_model.rb, line 41
def title_column
  retrieve_columns unless defined?(@title_column)
  @title_column
end