Class: ActiveMappers::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/active_mappers.rb

Constant Summary collapse

@@renderers =
{}
@@inheritance_column =
{}

Class Method Summary collapse

Class Method Details

.acts_as_polymorph(**options) ⇒ Object



78
79
80
81
82
83
84
85
# File 'lib/active_mappers.rb', line 78

def self.acts_as_polymorph(**options)
  each do |resource|
    mapper = KeyTransformer.resource_to_mapper(resource, self)
    mapper.with(resource, default_options.merge(options))
  rescue NameError
    raise NotImplementedError, 'No mapper found for this type of resource'
  end
end

.all(collection, options = {}) ⇒ Object



127
128
129
# File 'lib/active_mappers.rb', line 127

def self.all(collection, options = {})
  collection.map { |el| one(el, options) }.compact
end

.attributes(*params) ⇒ Object



27
28
29
30
31
32
33
34
35
# File 'lib/active_mappers.rb', line 27

def self.attributes(*params)
  each do |resource|
    h = {}
    params.each do |param|
      h[param] = resource.try(param)
    end
    h
  end
end

.default_optionsObject



146
147
148
# File 'lib/active_mappers.rb', line 146

def self.default_options
  { rootless: true, fallback_on_missing_scope: true }
end

.delegate(*params) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
# File 'lib/active_mappers.rb', line 37

def self.delegate(*params)
  delegator = params.last[:to]
  params.pop
  each do |resource|
    h = {}
    params.each do |param|
      h[param] = delegator.to_s.split('.').inject(resource, :try).try(param)
    end
    h
  end
end

.each(&block) ⇒ Object



87
88
89
# File 'lib/active_mappers.rb', line 87

def self.each(&block)
  @@renderers[name] = (@@renderers[name] || []) << block
end

.evaluate_scopes(args, options) ⇒ Object



102
103
104
105
# File 'lib/active_mappers.rb', line 102

def self.evaluate_scopes(args, options)
  class_to_call = "::#{name}Scope#{options[:scope].capitalize}".constantize rescue (options[:fallback_on_missing_scope] ? self : raise("ActiveMappers [#{name}] No scope named #{options[:scope]} found"))
  return class_to_call.with(args, options.except(:scope))
end

.inheritance_column(val) ⇒ Object



23
24
25
# File 'lib/active_mappers.rb', line 23

def self.inheritance_column(val)
  @@inheritance_column[name] = val
end

.inherited(subclass) ⇒ Object



19
20
21
# File 'lib/active_mappers.rb', line 19

def self.inherited(subclass)
  Handlers::Inheritance.new(subclass, self).handle
end

.one(resource, options = {}) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/active_mappers.rb', line 131

def self.one(resource, options = {})
  return nil unless resource
  if @@inheritance_column[name] && (mapper = KeyTransformer.resource_to_mapper(resource, self) rescue nil) && name != mapper&.name
    return mapper.with(resource, default_options.merge(options))
  end

  return {} if @@renderers[name].nil? # Mapper is empty

  renderers = @@renderers[name].map do |renderer|
    renderer.call(resource, options[:context])
  end.reduce(&:merge)

  KeyTransformer.format_keys(renderers)
end

.polymorphic(key, **options) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
# File 'lib/active_mappers.rb', line 66

def self.polymorphic(key, **options)
  each do |resource, context|
    options[:context] = context
    if polymorphic_resource = resource.send("#{key}_type")
      resource_mapper = "#{KeyTransformer.base_namespace(self)}::#{polymorphic_resource}Mapper".constantize
      { key => resource_mapper.with(resource.send(key), default_options.merge(options)) }
    else
      {}
    end
  end
end

.relation(key, mapper = nil, **options) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/active_mappers.rb', line 49

def self.relation(key, mapper = nil, **options)
  path = options[:optional_path] || key
  each do |resource|
    mapper_to_use = if mapper
      mapper
    else
      relation_class_name = resource.class&.reflect_on_association(options[:optional_path] || key)&.class_name
      raise "undefined relation : #{key.to_s}" if (mapper.nil? && relation_class_name.nil?)
      KeyTransformer.resource_class_to_mapper(relation_class_name.dup, self)
    end

    raise "'#{mapper_to_use.name}' should be a mapper" unless mapper_to_use.ancestors.map(&:to_s).include?("ActiveMappers::Base")

    { key => mapper_to_use.with(path.to_s.split('.').inject(resource, :try), default_options.merge(options)) }
  end
end

.render_with_root(args, options = {}) ⇒ Object



116
117
118
119
120
121
122
123
124
125
# File 'lib/active_mappers.rb', line 116

def self.render_with_root(args, options = {})
  resource_name = options[:root]
  resource_name ||= KeyTransformer.apply_on(self.name)

  if args.respond_to?(:each)
    { resource_name.to_s.pluralize.to_sym => all(args, options) }
  else
    { resource_name.to_s.singularize.to_sym => one(args, options) }
  end
end

.scope(*params, &block) ⇒ Object



107
108
109
110
111
112
113
114
# File 'lib/active_mappers.rb', line 107

def self.scope(*params, &block)
  raise "ActiveMappers [#{name}] scope must be a block" if block.nil? || !block.respond_to?(:call)

  params.each do |param|
    block_content = Ruby2Ruby.new.process(RubyParser.new.process(block.source).to_a.last)
    eval("class ::#{name}Scope#{param.capitalize} < ::#{name} ; #{block_content}; end")
  end
end

.with(args, options = {}) ⇒ Object



91
92
93
94
95
96
97
98
99
100
# File 'lib/active_mappers.rb', line 91

def self.with(args, options = {})
  return evaluate_scopes(args, options) unless options[:scope].nil?

  response = if options[:rootless]
    args.respond_to?(:each) ? all(args, options) : one(args, options)
  else
    render_with_root(args, options)
  end
  response
end