Class: OData::ActiveRecordSchema::Association

Inherits:
OData::AbstractSchema::Association show all
Defined in:
lib/o_data/active_record_schema/association.rb

Instance Attribute Summary collapse

Attributes inherited from OData::AbstractSchema::Association

#from_end, #to_end

Attributes inherited from OData::AbstractSchema::SchemaObject

#name, #schema

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from OData::AbstractSchema::Association

#FromEnd, #ToEnd, #inspect

Methods inherited from OData::AbstractSchema::SchemaObject

#<=>, #inspect, #plural_name, #qualified_name, #singular_name

Methods included from OData::AbstractSchema::Comparable

#compare, #sort

Constructor Details

#initialize(schema, reflection) ⇒ Association

Returns a new instance of Association.



123
124
125
126
127
# File 'lib/o_data/active_record_schema/association.rb', line 123

def initialize(schema, reflection)
  super(schema, self.class.name_for(reflection), self.class.from_end_options_for(schema, reflection), self.class.to_end_options_for(schema, reflection))
  
  @reflection = reflection
end

Instance Attribute Details

#reflectionObject (readonly)

Returns the value of attribute reflection.



121
122
123
# File 'lib/o_data/active_record_schema/association.rb', line 121

def reflection
  @reflection
end

Class Method Details

.active_record_for_from_end(reflection) ⇒ Object



15
16
17
# File 'lib/o_data/active_record_schema/association.rb', line 15

def self.active_record_for_from_end(reflection)
  reflection.active_record
end

.active_record_for_to_end(reflection) ⇒ Object



19
20
21
22
23
24
25
26
# File 'lib/o_data/active_record_schema/association.rb', line 19

def self.active_record_for_to_end(reflection)
  return nil if reflection.options[:polymorphic]
  begin
      reflection.class_name.constantize
  rescue => ex
    raise "Failed to handle class <#{reflection.active_record}> #{reflection.macro} #{reflection.name}"
  end
end

.column_names_for_from_end(reflection) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/o_data/active_record_schema/association.rb', line 37

def self.column_names_for_from_end(reflection)
  out = []
  
  case reflection.macro
  when :belongs_to
    out << reflection.primary_key_name
    out << reflection.options[:foreign_type] if reflection.options[:polymorphic]
  else
    out << EntityType.primary_key_for(reflection.active_record)
    out << polymorphic_column_name(reflection, 'ReturnType') if reflection.options[:as]
  end
  
  out
end

.column_names_for_to_end(reflection) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/o_data/active_record_schema/association.rb', line 52

def self.column_names_for_to_end(reflection)
  out = []
  
  case reflection.macro
  when :belongs_to
    if reflection.options[:polymorphic]
      out << polymorphic_column_name(reflection, 'Key')
      out << polymorphic_column_name(reflection, 'ReturnType')
    else
      out << EntityType.primary_key_for(reflection.class_name.constantize)
    end
  else
    out << reflection.primary_key_name
    
    if reflection.options[:as]
      out << reflection.options[:as].to_s + '_type'
    end
  end
  
  out
end

.from_end_options_for(schema, reflection) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/o_data/active_record_schema/association.rb', line 74

def self.from_end_options_for(schema, reflection)
  active_record = active_record_for_from_end(reflection)
  
  entity_type = schema.find_entity_type(:active_record => active_record)
  raise OData::AbstractQuery::Errors::EntityTypeNotFound.new(nil, active_record.class_name) if entity_type.blank?
  
  polymorphic = false
  
  # TODO: detect 'nullable' for FromEnd of Association
  nullable = false
  
  multiple = reflection.macro == :has_and_belongs_to_many
  
  name = entity_type.name
  name = name.pluralize if multiple
  
  { :name => name, :entity_type => entity_type, :return_type => entity_type.qualified_name, :multiple => multiple, :nullable => nullable, :polymorphic => polymorphic }
end

.name_for(reflection) ⇒ Object



4
5
6
# File 'lib/o_data/active_record_schema/association.rb', line 4

def self.name_for(reflection)
  EntityType.name_for(reflection.active_record) + '#' + reflection.name.to_s
end

.nullable?(active_record, association_columns) ⇒ Boolean

Returns:

  • (Boolean)


8
9
10
11
12
13
# File 'lib/o_data/active_record_schema/association.rb', line 8

def self.nullable?(active_record, association_columns)
  association_columns.all? { |column_name|
    column = active_record.columns.find { |c| c.name == column_name }
    column.blank? ? true : column.null
  }
end

.polymorphic_column_name(reflection, column_name) ⇒ Object

def self.foreign_keys_for(reflection)

[reflection.options[:foreign_key] || reflection.association_foreign_key, reflection.options[:foreign_type]].compact

end



32
33
34
35
# File 'lib/o_data/active_record_schema/association.rb', line 32

def self.polymorphic_column_name(reflection, column_name)
  # self.polymorphic_namespace_name.to_s + '.' + (reflection.options[:as] ? reflection.options[:as].to_s.classify : reflection.class_name.to_s) + '#' + column_name.to_s
  self.polymorphic_namespace_name.to_s + '#' + column_name.to_s
end

.to_end_options_for(schema, reflection) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/o_data/active_record_schema/association.rb', line 93

def self.to_end_options_for(schema, reflection)
  Rails.logger.info("Processing #{reflection.active_record}")
  active_record = active_record_for_to_end(reflection)
  entity_type = schema.find_entity_type(:active_record => active_record)
  
  polymorphic = reflection.options[:polymorphic] # || reflection.options[:as]

  multiple = [:has_many, :has_and_belongs_to_many].include?(reflection.macro)
  
  nullable = begin
    case reflection.macro
    when :belongs_to
      nullable?(active_record_for_from_end(reflection), column_names_for_from_end(reflection))
    else
      true
    end
  end
  
  name = EntityType.name_for(reflection.class_name)
  name = name.pluralize if multiple
  
  unless active_record.blank? || entity_type.blank?
    { :name => name, :entity_type => entity_type, :return_type => entity_type.qualified_name, :multiple => multiple, :nullable => nullable, :polymorphic => polymorphic }
  else
    { :name => name, :return_type => self.polymorphic_namespace_name, :multiple => multiple, :nullable => nullable, :polymorphic => polymorphic }
  end
end