Initial import
This commit is contained in:
12
vendor/gems/dr_nic_magic_models-0.9.2/lib/base.rb
vendored
Normal file
12
vendor/gems/dr_nic_magic_models-0.9.2/lib/base.rb
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#TODO: Use :dependent for FK cascade?
|
||||
|
||||
module ActiveRecord
|
||||
class Base
|
||||
class << self
|
||||
public
|
||||
def get_unique_index_columns
|
||||
self.connection.indexes(self.table_name, "#{self.name} Indexes").select { |index| index.unique && index.columns.size == 1 }.map{ |index| index.columns.first }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
0
vendor/gems/dr_nic_magic_models-0.9.2/lib/connection_adapters/abstract/schema_statements.rb
vendored
Normal file
0
vendor/gems/dr_nic_magic_models-0.9.2/lib/connection_adapters/abstract/schema_statements.rb
vendored
Normal file
32
vendor/gems/dr_nic_magic_models-0.9.2/lib/connection_adapters/abstract_adapter.rb
vendored
Normal file
32
vendor/gems/dr_nic_magic_models-0.9.2/lib/connection_adapters/abstract_adapter.rb
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
module ActiveRecord
|
||||
module ConnectionAdapters # :nodoc:
|
||||
|
||||
# Generic holder for foreign key constraint meta-data from the database schema.
|
||||
class ForeignKeyConstraint < Struct.new(:name, :table, :foreign_key, :reference_table, :reference_column, :on_update, :on_delete)
|
||||
end
|
||||
|
||||
class AbstractAdapter
|
||||
|
||||
# Does this adapter support the ability to fetch foreign key information?
|
||||
# Backend specific, as the abstract adapter always returns +false+.
|
||||
def supports_fetch_foreign_keys?
|
||||
false
|
||||
end
|
||||
|
||||
def foreign_key_constraints(table, name = nil)
|
||||
raise NotImplementedError, "foreign_key_constraints is not implemented for #{self.class}"
|
||||
end
|
||||
|
||||
def remove_foreign_key_constraint(table_name, constraint_name)
|
||||
raise NotImplementedError, "rename_table is not implemented for #{self.class}"
|
||||
end
|
||||
|
||||
protected
|
||||
def symbolize_foreign_key_constraint_action(constraint_action)
|
||||
return nil if constraint_action.nil?
|
||||
constraint_action.downcase.gsub(/\s/, '_').to_sym
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
42
vendor/gems/dr_nic_magic_models-0.9.2/lib/connection_adapters/mysql_adapter.rb
vendored
Normal file
42
vendor/gems/dr_nic_magic_models-0.9.2/lib/connection_adapters/mysql_adapter.rb
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
# Foreign Key support from http://wiki.rubyonrails.org/rails/pages/Foreign+Key+Schema+Dumper+Plugin
|
||||
|
||||
module ActiveRecord
|
||||
module ConnectionAdapters
|
||||
class MysqlAdapter < AbstractAdapter
|
||||
def supports_fetch_foreign_keys?
|
||||
true
|
||||
end
|
||||
|
||||
def foreign_key_constraints(table, name = nil)
|
||||
constraints = []
|
||||
execute("SHOW CREATE TABLE #{table}", name).each do |row|
|
||||
row[1].each do |create_line|
|
||||
if create_line.strip =~ /CONSTRAINT `([^`]+)` FOREIGN KEY \(`([^`]+)`\) REFERENCES `([^`]+)` \(`([^`]+)`\)([^,]*)/
|
||||
constraint = ForeignKeyConstraint.new(Regexp.last_match(1), table, Regexp.last_match(2), Regexp.last_match(3), Regexp.last_match(4), nil, nil)
|
||||
|
||||
constraint_params = {}
|
||||
|
||||
unless Regexp.last_match(5).nil?
|
||||
Regexp.last_match(5).strip.split('ON ').each do |param|
|
||||
constraint_params[Regexp.last_match(1).upcase] = Regexp.last_match(2).strip.upcase if param.strip =~ /([^ ]+) (.+)/
|
||||
end
|
||||
end
|
||||
|
||||
constraint.on_update = symbolize_foreign_key_constraint_action(constraint_params['UPDATE']) if constraint_params.include? 'UPDATE'
|
||||
constraint.on_delete = symbolize_foreign_key_constraint_action(constraint_params['DELETE']) if constraint_params.include? 'DELETE'
|
||||
|
||||
constraints << constraint
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
constraints
|
||||
end
|
||||
|
||||
def remove_foreign_key_constraint(table_name, constraint_name)
|
||||
execute "ALTER TABLE #{table_name} DROP FOREIGN KEY #{constraint_name}"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
45
vendor/gems/dr_nic_magic_models-0.9.2/lib/connection_adapters/postgresql_adapter.rb
vendored
Normal file
45
vendor/gems/dr_nic_magic_models-0.9.2/lib/connection_adapters/postgresql_adapter.rb
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
# Foreign Key support from http://wiki.rubyonrails.org/rails/pages/Foreign+Key+Schema+Dumper+Plugin
|
||||
|
||||
module ActiveRecord
|
||||
module ConnectionAdapters
|
||||
class PostgreSQLAdapter < AbstractAdapter
|
||||
|
||||
def supports_fetch_foreign_keys?
|
||||
true
|
||||
end
|
||||
|
||||
def foreign_key_constraints(table, name = nil)
|
||||
|
||||
|
||||
sql = "SELECT conname, pg_catalog.pg_get_constraintdef(oid) AS consrc FROM pg_catalog.pg_constraint WHERE contype='f' "
|
||||
sql += "AND conrelid = (SELECT oid FROM pg_catalog.pg_class WHERE relname='#{table}')"
|
||||
|
||||
result = query(sql, name)
|
||||
|
||||
keys = []
|
||||
re = /(?i)^FOREIGN KEY \((.+)\) REFERENCES (.+)\((.+)\)(?: ON UPDATE (\w+))?(?: ON DELETE (\w+))?$/
|
||||
result.each do |row|
|
||||
# pg_catalog.pg_get_constraintdef returns a string like this:
|
||||
# FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE
|
||||
if match = re.match(row[1])
|
||||
|
||||
keys << ForeignKeyConstraint.new(row[0],
|
||||
table,
|
||||
match[1],
|
||||
match[2],
|
||||
match[3],
|
||||
symbolize_foreign_key_constraint_action(match[4]),
|
||||
symbolize_foreign_key_constraint_action(match[5]))
|
||||
end
|
||||
end
|
||||
|
||||
keys
|
||||
end
|
||||
|
||||
def remove_foreign_key_constraint(table_name, constraint_name)
|
||||
execute "ALTER TABLE #{table_name} DROP CONSTRAINT #{constraint_name}"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
34
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models.rb
vendored
Normal file
34
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models.rb
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
$:.unshift(File.dirname(__FILE__)) unless
|
||||
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
||||
|
||||
unless defined?(ActiveRecord)
|
||||
begin
|
||||
require 'active_record'
|
||||
rescue LoadError
|
||||
require 'rubygems'
|
||||
require_gem 'activerecord'
|
||||
end
|
||||
end
|
||||
|
||||
module DrNicMagicModels
|
||||
Logger = RAILS_DEFAULT_LOGGER rescue Logger.new(STDERR)
|
||||
end
|
||||
|
||||
require 'dr_nic_magic_models/magic_model'
|
||||
require 'dr_nic_magic_models/schema'
|
||||
require 'dr_nic_magic_models/validations'
|
||||
require 'dr_nic_magic_models/inflector'
|
||||
require 'base'
|
||||
require 'module'
|
||||
require 'rails' rescue nil
|
||||
require 'connection_adapters/abstract_adapter'
|
||||
require 'connection_adapters/mysql_adapter'
|
||||
require 'connection_adapters/postgresql_adapter'
|
||||
|
||||
# load the schema
|
||||
# TODO - add this to README - DrNicMagicModels::Schema.load_schema(true)
|
||||
|
||||
class ActiveRecord::Base
|
||||
include DrNicMagicModels::MagicModel
|
||||
extend DrNicMagicModels::Validations
|
||||
end
|
||||
14
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/inflector.rb
vendored
Normal file
14
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/inflector.rb
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
module DrNicMagicModels
|
||||
class Inflector
|
||||
def table_names ; DrNicMagicModels::Schema.table_names; end
|
||||
def tables ; DrNicMagicModels::Schema.tables; end
|
||||
def models ; DrNicMagicModels::Schema.model; end
|
||||
|
||||
def class_name(table_name)
|
||||
ActiveRecord::Base.class_name(table_name)
|
||||
end
|
||||
|
||||
def post_class_creation(klass)
|
||||
end
|
||||
end
|
||||
end
|
||||
133
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/magic_model.rb
vendored
Normal file
133
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/magic_model.rb
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
# Mixed into a class that is dynamically created, unless
|
||||
# the class was created by the Schema.load_schema process
|
||||
# which builds the whole class, thus no magicalness is
|
||||
# needed
|
||||
module DrNicMagicModels::MagicModel
|
||||
def self.append_features(base)
|
||||
super
|
||||
base.send(:include, InstanceMethods)
|
||||
class << base
|
||||
# Returns the AssociationReflection object for the named +aggregation+ (use the symbol). Example:
|
||||
# Account.reflect_on_association(:owner) # returns the owner AssociationReflection
|
||||
# Invoice.reflect_on_association(:line_items).macro # returns :has_many
|
||||
def reflect_on_association(association)
|
||||
unless reflections[association]
|
||||
# See if an assocation can be generated
|
||||
self.new.send(association) rescue nil
|
||||
end
|
||||
reflections[association].is_a?(ActiveRecord::Reflection::AssociationReflection) ? reflections[association] : nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module InstanceMethods
|
||||
|
||||
def method_missing(method, *args, &block)
|
||||
begin
|
||||
super
|
||||
rescue
|
||||
if unknown_method? method
|
||||
result = find_belongs_to method, *args, &block
|
||||
result = find_has_some method, *args, &block if not result
|
||||
result = find_has_some_indirect method, *args, &block if not result
|
||||
return result if result
|
||||
end
|
||||
add_known_unknown method
|
||||
raise
|
||||
end
|
||||
end
|
||||
|
||||
def add_known_unknown(method)
|
||||
@known_unknowns ||= {}
|
||||
@known_unknowns[method] = true
|
||||
end
|
||||
|
||||
def unknown_method?(method)
|
||||
@known_unknowns.nil? or @known_unknowns.include? method
|
||||
end
|
||||
|
||||
def find_belongs_to(method, *args, &block)
|
||||
method_clean = clean_method method
|
||||
fkc =
|
||||
begin
|
||||
self.class.connection.foreign_key_constraints(self.class.table_name, method_clean)
|
||||
rescue NotImplementedError
|
||||
nil
|
||||
end
|
||||
if !fkc.nil? && fkc.length > 0
|
||||
foreign_key = fkc.first.foreign_key
|
||||
options = {:dependent => :destroy,
|
||||
:foreign_key => fkc.first.foreign_key,
|
||||
:class_name => self.class.class_name(fkc.first.reference_table)}
|
||||
else
|
||||
foreign_key = self.class.columns.select {|column| column.name == method_clean.to_s.foreign_key}.first
|
||||
end
|
||||
options ||= {}
|
||||
return add_belongs_to(method, method_clean, options, *args, &block) if foreign_key
|
||||
end
|
||||
|
||||
def add_belongs_to(method, method_clean, options, *args, &block)
|
||||
self.class.send 'belongs_to', method_clean.to_sym, options rescue puts $!
|
||||
self.send(method, *args, &block)
|
||||
end
|
||||
|
||||
def find_has_some(method, *args, &block)
|
||||
method_clean = clean_method method
|
||||
fkc = [method_clean.to_s.pluralize, method_clean.to_s.singularize].inject({}) do |pair, table_name|
|
||||
fkc = begin
|
||||
self.class.connection.foreign_key_constraints(table_name)
|
||||
rescue NotImplementedError
|
||||
nil
|
||||
end
|
||||
pair[table_name] = fkc if not fkc.blank?
|
||||
pair
|
||||
end
|
||||
if not fkc.blank?
|
||||
# assumes there is only one table found - that schema doesn't have a singular and plural table of same name
|
||||
foreign_key = fkc.values.first.find {|fk| fk.reference_table == self.class.table_name}
|
||||
if foreign_key
|
||||
foreign_key = foreign_key.foreign_key
|
||||
table_name = fkc.keys.first
|
||||
klass = Module.const_get table_name.singularize.camelize rescue nil
|
||||
options = {:foreign_key => foreign_key, :class_name => klass.name}
|
||||
end
|
||||
end
|
||||
unless foreign_key
|
||||
klass = Module.const_get method_clean.to_s.downcase.singularize.camelize rescue nil
|
||||
foreign_key = klass.columns.select {|column| column.name == self.class.name.foreign_key}.first if klass
|
||||
end
|
||||
options ||= {}
|
||||
return add_has_some(method, method_clean, options, *args, &block) if foreign_key
|
||||
end
|
||||
|
||||
def add_has_some(method, method_clean, options, *args, &block)
|
||||
association = method_clean.singularize == method_clean ? 'has_one' : 'has_many'
|
||||
self.class.send association, method_clean.to_sym, options rescue puts $!
|
||||
self.send(method, *args, &block)
|
||||
end
|
||||
|
||||
def find_has_some_indirect(method, *args, &block)
|
||||
klass = Module.const_get method.to_s.downcase.singularize.camelize rescue return
|
||||
join_table = nil
|
||||
self.connection.tables.each do |table|
|
||||
unless [self.class.table_name, klass.table_name].include? table
|
||||
columns = self.connection.columns(table).map(&:name)
|
||||
join_table = table if columns.include?(self.class.to_s.foreign_key) and columns.include?(klass.to_s.foreign_key)
|
||||
end
|
||||
break if join_table
|
||||
end
|
||||
return add_has_some_through(join_table, method, *args, &block) if join_table
|
||||
end
|
||||
|
||||
def add_has_some_through(join_table, method, *args, &block)
|
||||
self.class.send 'has_many', method, :through => join_table.to_sym
|
||||
self.send(method, *args, &block)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def clean_method(method)
|
||||
method.to_s.gsub(/=$/,'') # remove any = from the end of the method name
|
||||
end
|
||||
end
|
||||
end
|
||||
270
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/schema.rb
vendored
Normal file
270
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/schema.rb
vendored
Normal file
@@ -0,0 +1,270 @@
|
||||
module DrNicMagicModels
|
||||
|
||||
# ONE Schema per namespace module
|
||||
# Person, Company, etc share the Object namespace module, ie. ::Person, ::Company
|
||||
# Blog::Post, Blog::Comment, share the Blog namespace module
|
||||
class Schema
|
||||
attr_reader :modul
|
||||
|
||||
def initialize(modul)
|
||||
@modul = modul
|
||||
@table_name_prefix = modul.instance_variable_get("@table_name_prefix") rescue ''
|
||||
logger.info "Create Schema for #{@modul}, table_name_prefix '#{@table_name_prefix}'"
|
||||
end
|
||||
|
||||
cattr_accessor :inflector
|
||||
cattr_accessor :superklass
|
||||
|
||||
# Need to store models etc per-module, not in @ @models
|
||||
def inflector
|
||||
@inflector ||= Inflector.new
|
||||
end
|
||||
|
||||
# all in lower case please
|
||||
ReservedTables = [:schema_info, :sessions]
|
||||
@models = nil
|
||||
|
||||
def logger
|
||||
@logger ||= DrNicMagicModels::Logger
|
||||
end
|
||||
|
||||
def models
|
||||
load_schema if @models.nil?
|
||||
@models
|
||||
end
|
||||
|
||||
def tables
|
||||
load_schema if @tables.nil?
|
||||
@tables
|
||||
end
|
||||
|
||||
def table_names
|
||||
load_schema if @table_names.nil?
|
||||
@table_names
|
||||
end
|
||||
|
||||
def fks_on_table(table_name)
|
||||
load_schema if @models.nil?
|
||||
@fks_by_table[table_name.to_s] || []
|
||||
end
|
||||
|
||||
# active record only support 2 column link tables, otherwise use a model table, has_many and through
|
||||
def is_link_table?(table_name)
|
||||
load_schema if @models.nil?
|
||||
return @link_tables[table_name] if ! @link_tables[table_name].nil?
|
||||
column_names = @conn.columns(table_name).map{|x| x.name }
|
||||
@link_tables[table_name] = ! column_names.include?("id") && column_names.length == 2 && column_names.select { |x| x =~ /_id$/ } == column_names
|
||||
return @link_tables[table_name]
|
||||
end
|
||||
|
||||
def link_tables_for_class(klass)
|
||||
load_schema if @models.nil?
|
||||
end
|
||||
|
||||
def load_schema(preload = false)
|
||||
return if !@models.nil?
|
||||
|
||||
@superklass ||= ActiveRecord::Base
|
||||
raise "No database connection" if !(@conn = @superklass.connection)
|
||||
|
||||
@models = ModelHash.new
|
||||
@tables = Hash.new
|
||||
@fks_by_table = Hash.new
|
||||
@link_tables = Hash.new
|
||||
|
||||
@table_names = @conn.tables
|
||||
@table_names = @table_names.grep(/^#{@table_name_prefix}/) if @table_name_prefix
|
||||
@table_names = @table_names.sort
|
||||
|
||||
logger.info "For #{modul} tables are #{@table_names.inspect}"
|
||||
|
||||
# Work out which tables are in the model and which aren't
|
||||
@table_names.each do |table_name|
|
||||
|
||||
# deal with reserved tables & link_tables && other stray id-less tables
|
||||
#key = 'id'
|
||||
#case ActiveRecord::Base.primary_key_prefix_type
|
||||
# when :table_name
|
||||
# key = Inflector.foreign_key(table_name, false)
|
||||
# when :table_name_with_underscore
|
||||
# key = Inflector.foreign_key(table_name)
|
||||
#end
|
||||
#next if ReservedTables.include?(table_name.downcase.to_sym) ||
|
||||
# is_link_table?(table_name) ||
|
||||
# ! @conn.columns(table_name).map{ |x| x.name}.include?(key)
|
||||
|
||||
table_name_clean = table_name.gsub(/^#{@table_name_prefix}/,'')
|
||||
|
||||
# a model table then...
|
||||
model_class_name = inflector.class_name(table_name_clean)
|
||||
|
||||
logger.debug "Got a model table: #{table_name} => class #{model_class_name}"
|
||||
|
||||
@models[model_class_name] = table_name
|
||||
@tables[table_name] = model_class_name
|
||||
|
||||
if preload
|
||||
# create by MAGIC!
|
||||
klass = model_class_name.constantize
|
||||
|
||||
# Process FKs?
|
||||
if @conn.supports_fetch_foreign_keys?
|
||||
|
||||
tables.each do |table_name|
|
||||
logger.debug "Getting FKs for #{table_name}"
|
||||
@fks_by_table[table_name] = Array.new
|
||||
@conn.foreign_key_constraints(table_name).each do |fk|
|
||||
logger.debug "Got one: #{fk}"
|
||||
@fks_by_table[table_name].push(fk)
|
||||
end # do each fk
|
||||
|
||||
end # each table
|
||||
end
|
||||
|
||||
# Try to work out our link tables now...
|
||||
@models.keys.sort.each{|klass| process_table(@models[klass.to_s])}
|
||||
@link_tables.keys.sort.each{|table_name| process_link_table(table_name) if @link_tables[table_name]}
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def process_table(table_name)
|
||||
|
||||
logger.debug "Processing model table #{table_name}"
|
||||
|
||||
# ok, so let's look at the foreign keys on the table...
|
||||
belongs_to_klass = @tables[table_name].constantize rescue return
|
||||
|
||||
processed_columns = Hash.new
|
||||
|
||||
fks_on_table(table_name).each do |fk|
|
||||
logger.debug "Found FK column by suffix _id [#{fk.foreign_key}]"
|
||||
has_some_klass = Inflector.classify(fk.reference_table).constantize rescue next
|
||||
processed_columns[fk.foreign_key] = { :has_some_klass => has_some_klass }
|
||||
processed_columns[fk.foreign_key].merge! add_has_some_belongs_to(belongs_to_klass, fk.foreign_key, has_some_klass) rescue next
|
||||
end
|
||||
|
||||
column_names = @conn.columns(table_name).map{ |x| x.name}
|
||||
column_names.each do |column_name|
|
||||
next if not column_name =~ /_id$/
|
||||
logger.debug "Found FK column by suffix _id [#{column_name}]"
|
||||
if processed_columns.key?(column_name)
|
||||
logger.debug "Skipping, already processed"
|
||||
next
|
||||
end
|
||||
has_some_klass = Inflector.classify(column_name.sub(/_id$/,"")).constantize rescue next
|
||||
processed_columns[column_name] = { :has_some_klass => has_some_klass }
|
||||
processed_columns[column_name].merge! add_has_some_belongs_to(belongs_to_klass, column_name, has_some_klass) rescue next
|
||||
end
|
||||
|
||||
#TODO: what if same classes in table?
|
||||
|
||||
# is this a link table with attributes? (has_many through?)
|
||||
return if processed_columns.keys.length < 2
|
||||
|
||||
processed_columns.keys.each do |key1|
|
||||
processed_columns.keys.each do |key2|
|
||||
next if key1 == key2
|
||||
logger.debug "\n*** #{processed_columns[key1][:has_some_class]}.send 'has_many', #{processed_columns[key2][:belongs_to_name].to_s.pluralize.to_sym}, :through => #{processed_columns[key2][:has_some_name]}\n\n"
|
||||
processed_columns[key1][:has_some_class].send 'has_many', processed_columns[key2][:belongs_to_name].to_s.pluralize.to_sym, :through => processed_columns[key2][:has_some_name].to_sym
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def add_has_some_belongs_to(belongs_to_klass, belongs_to_fk, has_some_klass)
|
||||
|
||||
logger.debug "Trying to add a #{belongs_to_klass} belongs_to #{has_some_klass}..."
|
||||
|
||||
# so this is a belongs_to & has_some style relationship...
|
||||
# is it a has_many, or a has_one? Well, let's assume a has_one has a unique index on the column please... good db design, haha!
|
||||
unique = belongs_to_klass.get_unique_index_columns.include?(belongs_to_fk)
|
||||
belongs_to_name = belongs_to_fk.sub(/_id$/, '').to_sym
|
||||
|
||||
logger.debug "\n*** #{belongs_to_klass}.send 'belongs_to', #{belongs_to_name}, :class_name => #{has_some_klass}, :foreign_key => #{belongs_to_fk}\n"
|
||||
belongs_to_klass.send(:belongs_to, belongs_to_name, :class_name => has_some_klass.to_s, :foreign_key => belongs_to_fk.to_sym)
|
||||
|
||||
# work out if we need a prefix
|
||||
has_some_name = (
|
||||
(unique ? belongs_to_klass.table_name.singularize : belongs_to_klass.table_name) +
|
||||
(belongs_to_name.to_s == has_some_klass.table_name.singularize ? "" : "_as_"+belongs_to_name.to_s)
|
||||
).downcase.to_sym
|
||||
method = unique ? :has_one : :has_many
|
||||
logger.debug "\n*** #{has_some_klass}.send(#{method}, #{has_some_name}, :class_name => #{belongs_to_klass.to_s}, :foreign_key => #{belongs_to_fk.to_sym})\n\n"
|
||||
has_some_klass.send(method, has_some_name, :class_name => belongs_to_klass.to_s, :foreign_key => belongs_to_fk.to_sym)
|
||||
|
||||
return { :method => method, :belongs_to_name => belongs_to_name, :has_some_name => has_some_name, :has_some_class => has_some_klass }
|
||||
|
||||
end
|
||||
|
||||
def process_link_table(table_name)
|
||||
|
||||
logger.debug "Processing link table #{table_name}"
|
||||
|
||||
classes_map = Hash.new
|
||||
column_names = @conn.columns(table_name).map{ |x| x.name}
|
||||
|
||||
# use foreign keys first
|
||||
fks_on_table(table_name).each do |fk|
|
||||
logger.debug "Processing fk: #{fk}"
|
||||
klass = Inflector.classify(fk.reference_table).constantize rescue logger.debug("Cannot find model #{class_name} for table #{fk.reference_table}") && return
|
||||
classes_map[fk.foreign_key] = klass
|
||||
end
|
||||
|
||||
logger.debug "Got #{classes_map.keys.length} references from FKs"
|
||||
|
||||
if classes_map.keys.length < 2
|
||||
|
||||
#Fall back on good ol _id recognition
|
||||
|
||||
column_names.each do |column_name|
|
||||
|
||||
# check we haven't processed by fks already
|
||||
next if ! classes_map[column_name].nil?
|
||||
referenced_table = column_name.sub(/_id$/, '')
|
||||
|
||||
begin
|
||||
klass = Inflector.classify(referenced_table).constantize
|
||||
# fall back on FKs here
|
||||
if ! klass.nil?
|
||||
classes_map[column_name] = klass
|
||||
end
|
||||
rescue
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# not detected the link table?
|
||||
logger.debug "Got #{classes_map.keys.length} references"
|
||||
logger.debug "Cannot detect both tables referenced in link table" && return if classes_map.keys.length != 2
|
||||
|
||||
logger.debug "Adding habtm relationship"
|
||||
|
||||
logger.debug "\n*** #{classes_map[column_names[0]]}.send 'has_and_belongs_to_many', #{column_names[1].sub(/_id$/,'').pluralize.to_sym}, :class_name => #{classes_map[column_names[1]].to_s}, :join_table => #{table_name.to_sym}\n"
|
||||
logger.debug "\n*** #{classes_map[column_names[1]]}.send 'has_and_belongs_to_many', #{column_names[0].sub(/_id$/,'').pluralize.to_sym}, :class_name => #{classes_map[column_names[0]].to_s}, :join_table => #{table_name.to_sym}\n\n"
|
||||
|
||||
classes_map[column_names[0]].send 'has_and_belongs_to_many', column_names[1].sub(/_id$/,'').pluralize.to_sym, :class_name => classes_map[column_names[1]].to_s, :join_table => table_name.to_sym
|
||||
classes_map[column_names[1]].send 'has_and_belongs_to_many', column_names[0].sub(/_id$/,'').pluralize.to_sym, :class_name => classes_map[column_names[0]].to_s, :join_table => table_name.to_sym
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
class ModelHash < Hash
|
||||
def unenquire(class_id)
|
||||
@enquired ||= {}
|
||||
@enquired[class_id = class_id.to_s] = false
|
||||
end
|
||||
|
||||
def enquired?(class_id)
|
||||
@enquired ||= {}
|
||||
@enquired[class_id.to_s]
|
||||
end
|
||||
|
||||
def [](class_id)
|
||||
enquired?(class_id = class_id.to_s)
|
||||
@enquired[class_id] = true
|
||||
super(class_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
46
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/validations.rb
vendored
Normal file
46
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/validations.rb
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
module DrNicMagicModels
|
||||
module Validations
|
||||
|
||||
def generate_validations
|
||||
|
||||
logger = DrNicMagicModels::Logger
|
||||
|
||||
# Ensure that the connection to db is established, else validations don't get created.
|
||||
ActiveRecord::Base.connection
|
||||
|
||||
# Code reworked from http://www.redhillconsulting.com.au/rails_plugins.html
|
||||
# Thanks Red Hill Consulting for using an MIT licence :o)
|
||||
|
||||
# NOT NULL constraints
|
||||
self.columns.reject { |column| column.name =~ /(?i)^(((created|updated)_(at|on))|position|type|id)$/ }.each do |column|
|
||||
|
||||
if column.type == :integer
|
||||
logger.debug "validates_numericality_of #{column.name}, :allow_nil => #{column.null.inspect}, :only_integer => true"
|
||||
self.validates_numericality_of column.name, :allow_nil => column.null, :only_integer => true
|
||||
elsif column.number?
|
||||
logger.debug "validates_numericality_of #{column.name}, :allow_nil => #{column.null.inspect}"
|
||||
self.validates_numericality_of column.name, :allow_nil => column.null
|
||||
elsif column.text? && column.limit
|
||||
logger.debug "validates_length_of #{column.name}, :allow_nil => #{column.null.inspect}, :maximum => #{column.limit}"
|
||||
self.validates_length_of column.name, :allow_nil => column.null, :maximum => column.limit
|
||||
end
|
||||
|
||||
# Active record seems to interpolate booleans anyway to either true, false or nil...
|
||||
if column.type == :boolean
|
||||
logger.debug "validates_inclusion_of #{column.name}, :in => [true, false], :allow_nil => #{column.null}, :message => ActiveRecord::Errors.default_error_messages[:blank]"
|
||||
self.validates_inclusion_of column.name, :in => [true, false], :allow_nil => column.null, :message => ActiveRecord::Errors.default_error_messages[:blank]
|
||||
elsif !column.null
|
||||
logger.debug "validates_presence_of #{column.name}"
|
||||
self.validates_presence_of column.name
|
||||
end
|
||||
end
|
||||
|
||||
# Single-column UNIQUE indexes
|
||||
get_unique_index_columns.each do |col|
|
||||
logger.debug "validates_uniqueness_of #{col}"
|
||||
self.validates_uniqueness_of col
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
9
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/version.rb
vendored
Normal file
9
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/version.rb
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
module DrNicMagicModels #:nodoc:
|
||||
module VERSION #:nodoc:
|
||||
MAJOR = 0
|
||||
MINOR = 9
|
||||
TINY = 2
|
||||
|
||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||
end
|
||||
end
|
||||
33
vendor/gems/dr_nic_magic_models-0.9.2/lib/module.rb
vendored
Normal file
33
vendor/gems/dr_nic_magic_models-0.9.2/lib/module.rb
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
class Module
|
||||
alias :normal_const_missing :const_missing
|
||||
|
||||
def const_missing(class_id)
|
||||
begin
|
||||
return normal_const_missing(class_id)
|
||||
rescue
|
||||
end
|
||||
@magic_schema ||= DrNicMagicModels::Schema.new self
|
||||
unless table_name = @magic_schema.models[class_id]
|
||||
raise NameError.new("uninitialized constant #{class_id}") if @magic_schema.models.enquired? class_id
|
||||
end
|
||||
superklass = @magic_schema.superklass || ActiveRecord::Base
|
||||
klass = create_class(class_id, superklass) do
|
||||
set_table_name table_name
|
||||
# include DrNicMagicModels::MagicModel
|
||||
# extend DrNicMagicModels::Validations
|
||||
end
|
||||
klass.generate_validations # need to call this AFTER the class name has been assigned
|
||||
@magic_schema.inflector.post_class_creation klass
|
||||
klass
|
||||
end
|
||||
|
||||
def magic_module(options)
|
||||
self.instance_variable_set "@table_name_prefix", options[:table_name_prefix] if options[:table_name_prefix]
|
||||
end
|
||||
|
||||
private
|
||||
def create_class(class_name, superclass, &block)
|
||||
klass = Class.new superclass, &block
|
||||
self.const_set class_name, klass
|
||||
end
|
||||
end
|
||||
19
vendor/gems/dr_nic_magic_models-0.9.2/lib/rails.rb
vendored
Normal file
19
vendor/gems/dr_nic_magic_models-0.9.2/lib/rails.rb
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
module Dependencies #:nodoc:#
|
||||
|
||||
@@models_dir = File.expand_path(File.join(RAILS_ROOT,'app','models'))
|
||||
|
||||
# don't reload models... it doesn't work anyway, not sure why they haven't done this?
|
||||
# submit as patch?
|
||||
alias require_or_load_old require_or_load
|
||||
def require_or_load(file_name, *args)
|
||||
file_name = $1 if file_name =~ /^(.*)\.rb$/
|
||||
expanded = File.expand_path(file_name)
|
||||
old_mechanism = Dependencies.mechanism
|
||||
if expanded =~ /^#{@@models_dir}/
|
||||
RAILS_DEFAULT_LOGGER.debug "*** Not reloading #{file_name}"
|
||||
Dependencies.mechanism = :require
|
||||
end
|
||||
require_or_load_old(file_name, *args)
|
||||
Dependencies.mechanism = old_mechanism
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user