Class: ActiveRecord::ModelInheritance::ViewDefinition

Inherits:
Object
  • Object
show all
Defined in:
lib/active_record/model_inheritance/view_definition.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model_class, definition) ⇒ ViewDefinition

Returns a new instance of ViewDefinition.



12
13
14
15
# File 'lib/active_record/model_inheritance/view_definition.rb', line 12

def initialize model_class, definition
  @model_class = model_class
  @definition = definition
end

Instance Attribute Details

#definitionObject (readonly)

Returns the value of attribute definition.



9
10
11
# File 'lib/active_record/model_inheritance/view_definition.rb', line 9

def definition
  @definition
end

#model_classObject (readonly)

Returns the value of attribute model_class.



10
11
12
# File 'lib/active_record/model_inheritance/view_definition.rb', line 10

def model_class
  @model_class
end

Class Method Details

.define_derived_view(model_class, &block) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/active_record/model_inheritance/view_definition.rb', line 69

def self.define_derived_view model_class, &block
  inner_model = model_class.model_inheritance_inner_model
  base_model = model_class.model_inheritance_base_model

  inner_table = inner_model.arel_table
  base_table = base_model.arel_table

  definition = if block_given?
                 block.call(inner_table, base_table).tap do |d|
                   unless d.is_a? Arel::SelectManager
                     raise DefinitionError, 'Defined view must evaluate to Arel::SelectManager'
                   end
                 end
               else
                 selected_base_columns = if inner_model.primary_key == base_model.primary_key
                                           # this is a common naming conflict problem
                                           # makes sense to try and solve automatically

                                           # just delete the base primary key from columns that will be selected
                                           base_model
                                             .column_names
                                             .dup
                                             .delete_if { |column_name| column_name == base_model.primary_key }
                                         else
                                           base_model.column_names
                                         end.map { |column_name| base_table[column_name.to_sym] }

                 base_reference = model_class
                                    .reflect_on_association(model_class.model_inheritance_base_name)
                                    .foreign_key
                                    .to_sym

                 inner_table
                   .project(inner_table[Arel.star])
                   .project(*selected_base_columns)
                   .join(base_table)
                   .on(inner_table[base_reference].eq base_table[base_model.primary_key])
               end

  ViewDefinition.new model_class, definition
end

.from_model(model_class) ⇒ Object



54
55
56
57
58
59
60
# File 'lib/active_record/model_inheritance/view_definition.rb', line 54

def self.from_model model_class
  unless model_class.include? Model
    raise ArgumentError, "#{model_class.name} doesn't include ActiveRecord::ModelInheritance::Model"
  end

  ViewDefinition.from_name model_class.model_name.plural
end

.from_name(name) ⇒ Object

Raises:

  • (ArgumentError)


62
63
64
65
66
67
# File 'lib/active_record/model_inheritance/view_definition.rb', line 62

def self.from_name name
  definition_filename = Pathname(ModelInheritance.config.definitions_path).join "#{name}.rb"
  raise ArgumentError, "Definition for \"#{name}\" doesn't exist" unless definition_filename.file?

  eval File.read definition_filename
end

Instance Method Details

#attributes_mappingObject



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
48
49
50
51
52
# File 'lib/active_record/model_inheritance/view_definition.rb', line 21

def attributes_mapping
  definition
    .projections
    .each_with_object({base: [], inner: []}) do |projection, attributes_mapping|
      if projection.is_a? Arel::Nodes::As
        relation = projection.left.relation
        name = projection.right
      else
        relation = projection.relation
        name = projection.name
      end

      case relation
      when model_class.model_inheritance_inner_model.arel_table
        relation_type = :inner
        relation_model = model_class.model_inheritance_inner_model
      when model_class.model_inheritance_base_model.arel_table
        relation_type = :base
        relation_model = model_class.model_inheritance_base_model
      else
        raise DefinitionError, "Invalid \"#{relation}\" relation"
      end

      attributes = if name == Arel.star
                     relation_model.attribute_names.map(&:to_sym)
                   else
                     [name.to_sym]
                   end

      attributes_mapping[relation_type] += attributes
    end
end

#to_sqlObject



17
18
19
# File 'lib/active_record/model_inheritance/view_definition.rb', line 17

def to_sql
  @definition.to_sql
end