Module: ActiveRecord::ConnectionAdapters::ConstraintHandlers::Postgresql::ClassMethods
- Defined in:
- lib/activerecord_constraint_handlers.rb
Overview
We need class methods and class instance variables to hold the data. We want them in the class so that the work is done only once for the life of the application. In the PostgreSQL case, we leverage off of ActiveRecord::Base by creating three nested models so they are hidden syntactically that use the model as their base class so that they use the same connection as the model itself. This allows other models to use other connections and the data is kept separate.
Instance Method Summary collapse
-
#constraint_to_columns(constraint) ⇒ Object
Converts the constraint name into a list of column names.
-
#create_subclasses ⇒ Object
At the time of the first call, we create the models needed for the code above as a nested subclass of the model using the model as the base.
-
#pg_attribute_constant ⇒ Object
Create the constant for the PgAttribute nested model.
-
#pg_attribute_hash ⇒ Object
Accessor for the attribute hash.
-
#pg_attributes ⇒ Object
Find the attributes for this model.
-
#pg_class ⇒ Object
Turns out, we don’t really use this…
-
#pg_class_constant ⇒ Object
Create the constant for the PgClass nested model.
-
#pg_constraint_constant ⇒ Object
Create the constant for the PgConstraint nested model.
-
#pg_constraint_hash ⇒ Object
Accessor for the constraint hash.
-
#pg_constraints ⇒ Object
Find the constraints for this model / table.
-
#pre_fetch ⇒ Object
We can not rummage around in the database after an error has occurred or we will get back more errors that an error has already occurred and further queries will be ignored.
Instance Method Details
#constraint_to_columns(constraint) ⇒ Object
Converts the constraint name into a list of column names.
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/activerecord_constraint_handlers.rb', line 181 def constraint_to_columns(constraint) ActiveRecord::Base.logger.debug("constraint_to_columns: '#{constraint}' (#{constraint.class})") # Should never hit this now... added during debugging. unless pg_constraint_hash.has_key?(constraint) ActiveRecord::Base.logger.debug("constraint_to_columns: constraint not found") return end # pg_constraint_hash is a hash from the contraint name to # the constraint. The conkey is a string of the form: # +{2,3,4}+ (with the curly braces). The numbers are # column indexes which we pull out from pg_attribute and # convert to a name. Note that the PostgreSQL tables are # singular in name: pg_constraint and pg_attribute k = pg_constraint_hash[constraint].conkey k[1 ... (k.length - 1)]. split(','). map{ |s| pg_attribute_hash[s.to_i].attname } end |
#create_subclasses ⇒ Object
At the time of the first call, we create the models needed for the code above as a nested subclass of the model using the model as the base.
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/activerecord_constraint_handlers.rb', line 140 def create_subclasses ActiveRecord::Base.logger.debug("create_subclasses") self.class_eval <<-EOF class PgClass < #{self} set_table_name "pg_class" set_primary_key "oid" self.default_scoping = [] end class PgAttribute < #{self} set_table_name "pg_attribute" set_primary_key "oid" belongs_to :attrel, :class_name => "PgClass", :foreign_key => :attrelid self.default_scoping = [] end class PgConstraint < #{self} set_table_name "pg_constraint" set_primary_key "oid" belongs_to :conrel, :class_name => "PgClass", :foreign_key => :conrelid self.default_scoping = [] end EOF end |
#pg_attribute_constant ⇒ Object
Create the constant for the PgAttribute nested model.
88 89 90 |
# File 'lib/activerecord_constraint_handlers.rb', line 88 def pg_attribute_constant "#{self}::PgAttribute".constantize end |
#pg_attribute_hash ⇒ Object
Accessor for the attribute hash
133 134 135 |
# File 'lib/activerecord_constraint_handlers.rb', line 133 def pg_attribute_hash @pg_attribute_hash end |
#pg_attributes ⇒ Object
Find the attributes for this model
120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/activerecord_constraint_handlers.rb', line 120 def pg_attributes ActiveRecord::Base.logger.debug("pg_attributes") if @pg_attributes.nil? @pg_attributes = pg_attribute_constant.find(:all, :joins => :attrel, :conditions => { :pg_class => { :relname => table_name }}) @pg_attribute_hash = Hash.new @pg_attributes.each { |a| @pg_attribute_hash[a.attnum] = a } end @pg_attributes end |
#pg_class ⇒ Object
Turns out, we don’t really use this…
93 94 95 96 |
# File 'lib/activerecord_constraint_handlers.rb', line 93 def pg_class ActiveRecord::Base.logger.debug("pg_class") @pg_class ||= pg_class_constant.find_by_relname(table_name) end |
#pg_class_constant ⇒ Object
Create the constant for the PgClass nested model.
78 79 80 |
# File 'lib/activerecord_constraint_handlers.rb', line 78 def pg_class_constant "#{self}::PgClass".constantize end |
#pg_constraint_constant ⇒ Object
Create the constant for the PgConstraint nested model.
83 84 85 |
# File 'lib/activerecord_constraint_handlers.rb', line 83 def pg_constraint_constant "#{self}::PgConstraint".constantize end |
#pg_constraint_hash ⇒ Object
Accessor for the constraint hash
115 116 117 |
# File 'lib/activerecord_constraint_handlers.rb', line 115 def pg_constraint_hash @pg_constraint_hash end |
#pg_constraints ⇒ Object
Find the constraints for this model / table
99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/activerecord_constraint_handlers.rb', line 99 def pg_constraints ActiveRecord::Base.logger.debug("pg_constraints") if @pg_constraints.nil? @pg_constraints = pg_constraint_constant.find(:all, :joins => :conrel, :conditions => { :pg_class => { :relname => table_name }}) @pg_constraint_hash = Hash.new @pg_constraints.each { |c| ActiveRecord::Base.logger.debug("Adding '#{c.conname}' to constraint_hash") @pg_constraint_hash[c.conname] = c } end @pg_constraints end |
#pre_fetch ⇒ Object
We can not rummage around in the database after an error has occurred or we will get back more errors that an error has already occurred and further queries will be ignored. So, we pre-fetch the system tables that we need and save them in our pockets.
170 171 172 173 174 175 176 177 178 |
# File 'lib/activerecord_constraint_handlers.rb', line 170 def pre_fetch ActiveRecord::Base.logger.debug("pre_fetch #{self} #{table_name} #{@pg_class.nil?}") if @pg_class.nil? create_subclasses pg_class pg_constraints pg_attributes end end |