Class: PgSerializable::Visitors::Json

Inherits:
Base
  • Object
show all
Defined in:
lib/pg_serializable/visitors/json.rb

Instance Method Summary collapse

Methods inherited from Base

#visit, #visit_method_for, #visit_other, #visit_scope

Instance Method Details

#visit_association(subject, **kwargs) ⇒ Object



65
66
67
# File 'lib/pg_serializable/visitors/json.rb', line 65

def visit_association(subject, **kwargs)
  send("visit_#{subject.type}", subject, **kwargs)
end

#visit_attribute(subject, table_alias: nil) ⇒ Object



46
47
48
49
50
51
52
53
# File 'lib/pg_serializable/visitors/json.rb', line 46

def visit_attribute(subject, table_alias: nil)
  return visit_enum(subject, table_alias: table_alias) if subject.enum?
  table_alias ||= alias_tracker
  key = "\'#{subject.label}\'"
  column_name = "\"#{table_alias}\".\"#{subject.column_name}\""
  val = subject.prc ? subject.prc.call(column_name) : column_name
  "#{key}, #{val}"
end

#visit_belongs_to(subject, table_alias:, **kwargs) ⇒ Object



69
70
71
72
73
74
75
76
# File 'lib/pg_serializable/visitors/json.rb', line 69

def visit_belongs_to(subject, table_alias:, **kwargs)
  current_alias = next_alias!
  klass = subject.target
  select_sql = json_build_object(visit(klass.trait_manager, trait: subject.trait, table_alias: current_alias)).to_sql
  query = klass.select(select_sql).from("#{klass.table_name} #{current_alias}")
          .where("#{current_alias}.#{subject.primary_key}=#{table_alias}.#{subject.foreign_key}").to_sql
  "\'#{subject.label}\', (#{query})"
end

#visit_class(subject, trait: :default, **kwargs) ⇒ Object



26
27
28
# File 'lib/pg_serializable/visitors/json.rb', line 26

def visit_class(subject, trait: :default, **kwargs)
  visit(subject.all, trait: trait, **kwargs)
end

#visit_enum(subject, table_alias: nil) ⇒ Object



55
56
57
58
59
60
61
62
63
# File 'lib/pg_serializable/visitors/json.rb', line 55

def visit_enum(subject, table_alias: nil)
  key = "\'#{subject.label}\'"
  enum_hash = subject.klass.defined_enums[subject.column_name.to_s]
  val = "CASE \"#{table_alias}\".\"#{subject.column_name}\" " +
  enum_hash.map do |val, int|
    "WHEN #{int} THEN \'#{subject.prc ? subject.prc.call(val) : val}\'"
  end.join(' ') + " ELSE NULL END"
  "#{key}, #{val}"
end

#visit_has_and_belongs_to_many(subject, table_alias:, **kwargs) ⇒ Object



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/pg_serializable/visitors/json.rb', line 117

def visit_has_and_belongs_to_many(subject, table_alias:, **kwargs)
  current_alias = next_alias!
  association = subject.association
  join_table = association.join_table
  source = association.source_reflection

  query = visit(association
    .klass
    .select("#{source.table_name}.*, #{join_table}.#{source.association_foreign_key}, #{join_table}.#{association.join_primary_key}")
    .joins("INNER JOIN #{join_table} ON #{join_table}.#{source.association_foreign_key}=#{source.table_name}.#{source.association_primary_key}"), table_alias: current_alias)
    .where("#{current_alias}.#{association.join_primary_key}=#{table_alias}.#{subject.foreign_key}")
    .to_sql

  "\'#{subject.label}\', (#{query})"
end

#visit_has_many(subject, table_alias:, **kwargs) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/pg_serializable/visitors/json.rb', line 78

def visit_has_many(subject, table_alias:, **kwargs)
  return visit_has_many_through(subject, table_alias: table_alias, **kwargs) if subject.association.through_reflection?

  current_alias = next_alias!
  klass = subject.target
  select_sql = coalesce(json_agg(json_build_object(visit(klass.trait_manager, trait: subject.trait, table_alias: current_alias)))).to_sql

  query = klass.select(select_sql).from("#{klass.table_name} #{current_alias}")
          .where("#{current_alias}.#{subject.primary_key}=#{table_alias}.#{subject.foreign_key}").to_sql

  "\'#{subject.label}\', (#{query})"
end

#visit_has_many_through(subject, table_alias:, **kwargs) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/pg_serializable/visitors/json.rb', line 91

def visit_has_many_through(subject, table_alias:, **kwargs)
  current_alias = next_alias!
  association = subject.association
  through = association.through_reflection
  source = association.source_reflection
  join_name = source.collection? ? through.plural_name.to_sym : through.name
  # needs work
  where_clause = begin
    if source.belongs_to?
      "#{table_alias}.#{through.join_foreign_key}=#{through.table_name}.#{through.join_primary_key}"
    elsif through.belongs_to?
      "#{table_alias}.#{through.join_foreign_key}=#{through.table_name}.#{subject.foreign_key}"
    else
      "#{through.table_name}.#{through.join_foreign_key}=#{table_alias}.#{subject.foreign_key}"
    end
  end

  query = visit(association
    .klass
    .joins(join_name)
    .where(where_clause), table_alias: current_alias)
    .to_sql

  "\'#{subject.label}\', (#{query})"
end

#visit_has_one(subject, table_alias:, **kwargs) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/pg_serializable/visitors/json.rb', line 133

def visit_has_one(subject, table_alias:, **kwargs)
  current_alias = next_alias!
  subquery_alias = next_alias!
  klass = subject.target

  select_sql = json_build_object(visit(klass.trait_manager, trait: subject.trait, table_alias: current_alias)).to_sql
  from_sql = klass
    .select("DISTINCT ON (#{subject.primary_key}) #{subquery_alias}.*")
    .from("#{klass.table_name} #{subquery_alias}")

  query = klass.select(select_sql).from("#{as(from_sql, current_alias)}")
    .where("#{current_alias}.#{subject.primary_key}=#{table_alias}.#{subject.foreign_key}").to_sql

  "\'#{subject.label}\', (#{query})"
end

#visit_node(subject, **kwargs) ⇒ Object



38
39
40
41
42
43
44
# File 'lib/pg_serializable/visitors/json.rb', line 38

def visit_node(subject, **kwargs)
  case subject
  when attribute? then visit_attribute subject, **kwargs
  when association? then visit_association subject, **kwargs
  else raise UnknownAttributeError.new
  end
end

#visit_record(subject, trait: :default) ⇒ Object



4
5
6
7
8
9
10
11
12
13
# File 'lib/pg_serializable/visitors/json.rb', line 4

def visit_record(subject, trait: :default)
  table_alias = next_alias!

  klass = subject.class
  base_class = klass.base_class
  select_sql = json_build_object(visit(klass.trait_manager, trait: trait, table_alias: table_alias)).to_sql
  from_sql = base_class.where(id: subject.id).limit(1).to_sql

  base_class.select(select_sql).from("#{as(from_sql, table_alias)}")
end

#visit_relation(subject, table_alias: nil, trait: :default) ⇒ Object



15
16
17
18
19
20
21
22
23
24
# File 'lib/pg_serializable/visitors/json.rb', line 15

def visit_relation(subject, table_alias: nil, trait: :default)
  table_alias ||= next_alias!

  klass = subject.klass
  base_class = klass.base_class
  select_sql = coalesce(json_agg(json_build_object(visit(klass.trait_manager, trait: trait, table_alias: table_alias)))).to_sql
  from_sql = subject.to_sql

  base_class.select(select_sql).from("#{as(from_sql, table_alias)}")
end

#visit_trait(subject, **kwargs) ⇒ Object



34
35
36
# File 'lib/pg_serializable/visitors/json.rb', line 34

def visit_trait(subject, **kwargs)
  subject.attribute_nodes.map { |attribute| visit attribute, **kwargs }.join(', ')
end

#visit_trait_manager(subject, trait: :default, **kwargs) ⇒ Object



30
31
32
# File 'lib/pg_serializable/visitors/json.rb', line 30

def visit_trait_manager(subject, trait: :default, **kwargs)
  visit subject.get_trait(trait), **kwargs
end