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



62
63
64
# File 'lib/pg_serializable/visitors/json.rb', line 62

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

#visit_attribute(subject, table_alias: nil) ⇒ Object



44
45
46
47
48
49
50
# File 'lib/pg_serializable/visitors/json.rb', line 44

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}\'"
  val = "\"#{table_alias}\".\"#{subject.prc ? subject.prc.call(column_name) : subject.column_name}\""
  "#{key}, #{val}"
end

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



66
67
68
69
70
71
72
73
# File 'lib/pg_serializable/visitors/json.rb', line 66

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



24
25
26
# File 'lib/pg_serializable/visitors/json.rb', line 24

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

#visit_enum(subject, table_alias: nil) ⇒ Object



52
53
54
55
56
57
58
59
60
# File 'lib/pg_serializable/visitors/json.rb', line 52

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



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/pg_serializable/visitors/json.rb', line 105

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



75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/pg_serializable/visitors/json.rb', line 75

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



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/pg_serializable/visitors/json.rb', line 88

def visit_has_many_through(subject, table_alias:, **kwargs)
  current_alias = next_alias!

  association = subject.association
  through = association.through_reflection
  source = association.source_reflection

  query = visit(association
    .klass
    .select("#{source.table_name}.*, #{through.table_name}.#{source.join_foreign_key}, #{through.table_name}.#{through.join_primary_key}")
    .joins(through.name), table_alias: current_alias)
    .where("#{current_alias}.#{through.join_primary_key}=#{table_alias}.#{subject.foreign_key}")
    .to_sql

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

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



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/pg_serializable/visitors/json.rb', line 121

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



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

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
# File 'lib/pg_serializable/visitors/json.rb', line 4

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

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

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

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



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

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

  klass = subject.klass
  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

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

#visit_trait(subject, **kwargs) ⇒ Object



32
33
34
# File 'lib/pg_serializable/visitors/json.rb', line 32

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

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



28
29
30
# File 'lib/pg_serializable/visitors/json.rb', line 28

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