dr_nic_magic_models 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG ADDED
@@ -0,0 +1,9 @@
1
+ * 0.2.5 * - Initial public release
2
+ - ActiveRecords can now be auto-created in memory when first referenced
3
+ from their table name, without an explicit class definition.
4
+ - ActiveRecords will automatically include validates_presence_of on
5
+ each field with :null => false
6
+ - ActiveRecords will automatically generate simple has_many, has_one,
7
+ belongs_to assocations based upon assumed foreign keys. E.g.
8
+ foreign key to products table is assumed to be product_id.
9
+
data/README ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,159 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/contrib/rubyforgepublisher'
8
+ require File.join(File.dirname(__FILE__), 'lib', 'dr_nic', 'magic_models', 'version')
9
+
10
+ PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
11
+ PKG_NAME = 'dr_nic_magic_models'
12
+ PKG_VERSION = DrNic::MagicModels::VERSION::STRING + PKG_BUILD
13
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
14
+
15
+ RELEASE_NAME = "REL #{PKG_VERSION}"
16
+
17
+ RUBY_FORGE_PROJECT = "magicmodels"
18
+ RUBY_FORGE_USER = "nicwilliams"
19
+
20
+ PKG_FILES = FileList[
21
+ "lib/**/*", "test/**/*", "examples/**/*", "doc/**/*", "website/**/*", "[A-Z]*", "install.rb", "Rakefile"
22
+ ].exclude(/\bCVS\b|~$/)
23
+
24
+
25
+ desc "Default Task"
26
+ task :default => [ :test_mysql ] # UNTESTED =, :test_sqlite, :test_postgresql ]
27
+ task :test => [ :test_mysql ]
28
+
29
+ # Run the unit tests
30
+
31
+ for adapter in %w( mysql ) # UNTESTED - postgresql sqlite sqlite3 firebird sqlserver sqlserver_odbc db2 oracle sybase openbase )
32
+ Rake::TestTask.new("test_#{adapter}") { |t|
33
+ t.libs << "test" << "test/connections/native_#{adapter}"
34
+ t.pattern = "test/*_test{,_#{adapter}}.rb"
35
+ t.verbose = true
36
+ }
37
+ end
38
+
39
+ SCHEMA_PATH = File.join(File.dirname(__FILE__), *%w(test fixtures db_definitions))
40
+
41
+ desc 'Build the MySQL test databases'
42
+ task :build_mysql_databases do
43
+ puts File.join(SCHEMA_PATH, 'mysql.sql')
44
+ %x( mysqladmin -u root create "#{PKG_NAME}_unittest" )
45
+ %x( mysql -u root "#{PKG_NAME}_unittest" < #{File.join(SCHEMA_PATH, 'mysql.sql')} )
46
+ end
47
+
48
+ desc 'Drop the MySQL test databases'
49
+ task :drop_mysql_databases do
50
+ %x( mysqladmin -u root -f drop "#{PKG_NAME}_unittest" )
51
+ end
52
+
53
+ desc 'Rebuild the MySQL test databases'
54
+ task :rebuild_mysql_databases => [:drop_mysql_databases, :build_mysql_databases]
55
+
56
+ desc 'Build the PostgreSQL test databases'
57
+ task :build_postgresql_databases do
58
+ %x( createdb "#{PKG_NAME}_unittest" )
59
+ %x( psql "#{PKG_NAME}_unittest" -f #{File.join(SCHEMA_PATH, 'postgresql.sql')} )
60
+ end
61
+
62
+ desc 'Drop the PostgreSQL test databases'
63
+ task :drop_postgresql_databases do
64
+ %x( dropdb "#{PKG_NAME}_unittest" )
65
+ end
66
+
67
+ desc 'Rebuild the PostgreSQL test databases'
68
+ task :rebuild_postgresql_databases => [:drop_postgresql_databases, :build_postgresql_databases]
69
+
70
+ # Generate the RDoc documentation
71
+
72
+ Rake::RDocTask.new { |rdoc|
73
+ rdoc.rdoc_dir = 'doc'
74
+ rdoc.title = "Dr Nic's Magic Models - Invisible validations, assocations and Active Record models themselves!"
75
+ rdoc.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object'
76
+ rdoc.template = "#{ENV['template']}.rb" if ENV['template']
77
+ rdoc.rdoc_files.include('README', 'CHANGELOG')
78
+ rdoc.rdoc_files.include('lib/**/*.rb')
79
+ }
80
+
81
+ # Enhance rdoc task to copy referenced images also
82
+ task :rdoc do
83
+ FileUtils.mkdir_p "doc/files/examples/"
84
+ end
85
+
86
+
87
+ # Create compressed packages
88
+
89
+ dist_dirs = [ "lib", "test", "examples", "website" ]
90
+
91
+ spec = Gem::Specification.new do |s|
92
+ s.name = PKG_NAME
93
+ s.version = PKG_VERSION
94
+ s.summary = "Invisible validations, assocations and Active Record models themselves!"
95
+ s.description = %q{Associations and validations are automagically available to your ActiveRecord models. Model classes themselves are automagically generated if you haven't defined them already!}
96
+
97
+ s.files = [ "Rakefile", "install.rb", "README", "CHANGELOG" ]
98
+ dist_dirs.each do |dir|
99
+ s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
100
+ end
101
+
102
+ s.add_dependency('activerecord', '= 1.14.3' + PKG_BUILD)
103
+
104
+ s.require_path = 'lib'
105
+ s.autorequire = 'dr_nic'
106
+
107
+ s.has_rdoc = true
108
+ s.extra_rdoc_files = %w( README )
109
+ s.rdoc_options.concat ['--main', 'README']
110
+
111
+ s.author = "Dr Nic Williams"
112
+ s.email = "drnicwilliams@gmail.com"
113
+ s.homepage = "http://magicmodels.rubyforge.org"
114
+ s.rubyforge_project = "magicmodels"
115
+ end
116
+
117
+ Rake::GemPackageTask.new(spec) do |p|
118
+ p.gem_spec = spec
119
+ p.need_tar = false
120
+ p.need_zip = false
121
+ end
122
+
123
+ task :lines do
124
+ lines, codelines, total_lines, total_codelines = 0, 0, 0, 0
125
+
126
+ for file_name in FileList["lib/**/*.rb"]
127
+ next if file_name =~ /vendor/
128
+ f = File.open(file_name)
129
+
130
+ while line = f.gets
131
+ lines += 1
132
+ next if line =~ /^\s*$/
133
+ next if line =~ /^\s*#/
134
+ codelines += 1
135
+ end
136
+ puts "L: #{sprintf("%4d", lines)}, LOC #{sprintf("%4d", codelines)} | #{file_name}"
137
+
138
+ total_lines += lines
139
+ total_codelines += codelines
140
+
141
+ lines, codelines = 0, 0
142
+ end
143
+
144
+ puts "Total: Lines #{total_lines}, LOC #{total_codelines}"
145
+ end
146
+
147
+
148
+ # Publishing ------------------------------------------------------
149
+
150
+ desc "Publish the release files to RubyForge."
151
+ task :release => [ :package ] do
152
+ `ruby scripts/rubyforge login`
153
+
154
+ for ext in %w( gem tgz zip )
155
+ release_command = "ruby scripts/rubyforge add_release #{PKG_NAME} #{PKG_NAME} 'REL #{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}"
156
+ puts release_command
157
+ system(release_command)
158
+ end
159
+ end
data/install.rb ADDED
@@ -0,0 +1,30 @@
1
+ require 'rbconfig'
2
+ require 'find'
3
+ require 'ftools'
4
+
5
+ include Config
6
+
7
+ # this was adapted from rdoc's install.rb by ways of Log4r
8
+
9
+ $sitedir = CONFIG["sitelibdir"]
10
+ unless $sitedir
11
+ version = CONFIG["MAJOR"] + "." + CONFIG["MINOR"]
12
+ $libdir = File.join(CONFIG["libdir"], "ruby", version)
13
+ $sitedir = $:.find {|x| x =~ /site_ruby/ }
14
+ if !$sitedir
15
+ $sitedir = File.join($libdir, "site_ruby")
16
+ elsif $sitedir !~ Regexp.quote(version)
17
+ $sitedir = File.join($sitedir, version)
18
+ end
19
+ end
20
+
21
+ # the acual gruntwork
22
+ Dir.chdir("lib")
23
+
24
+ Find.find("dr_nic", "dr_nic.rb") { |f|
25
+ if f[-3..-1] == ".rb"
26
+ File::install(f, File.join($sitedir, *f.split(/\//)), 0644, true)
27
+ else
28
+ File::makedirs(File.join($sitedir, *f.split(/\//)))
29
+ end
30
+ }
data/lib/base.rb ADDED
@@ -0,0 +1,70 @@
1
+ # Only needs to be an Include module for the generated classes, not for all ARs
2
+ module ActiveRecord
3
+ class Base
4
+ class << self
5
+ alias old_new new
6
+ def new(*args)
7
+ obj = old_new(*args)
8
+ unless self.methods.include? 'generate_validations'
9
+ self.send(:include, DrNic::MagicModels::Validations)
10
+ self.generate_validations
11
+ end
12
+ obj
13
+ end
14
+ alias old_allocate allocate
15
+ def allocate
16
+ obj = old_allocate
17
+ unless self.methods.include? 'generate_validations'
18
+ self.send(:include, DrNic::MagicModels::Validations)
19
+ self.generate_validations
20
+ end
21
+ obj
22
+ end
23
+ end
24
+
25
+ alias :normal_method_missing :method_missing
26
+ class_eval do
27
+ def method_missing(method, *args, &block)
28
+ if unknown_method? method
29
+ result = find_has_some method, *args, &block
30
+ result = find_belongs_to method, *args, &block if not result
31
+ return result if result
32
+ end
33
+ known_unknown method
34
+ normal_method_missing(method, *args, &block)
35
+ end
36
+
37
+ def known_unknown(method)
38
+ @known_unknowns ||= {}
39
+ @known_unknowns[method] = true
40
+ end
41
+
42
+ def unknown_method?(method)
43
+ @known_unknowns.nil? or @known_unknowns.include? method
44
+ end
45
+
46
+ def find_has_some(method, *args, &block)
47
+ klass = Module.const_get method.to_s.downcase.singularize.camelize rescue nil
48
+ foreign_key = klass.columns.select {|column| column.name == self.class.name.foreign_key}.first if klass
49
+ return add_has_some(method, *args, &block) if foreign_key
50
+ end
51
+
52
+ def add_has_some(method, *args, &block)
53
+ _method = method.to_s
54
+ association = _method.singularize == _method ? 'has_one' : 'has_many'
55
+ self.class.send association, method
56
+ self.send(method, *args, &block)
57
+ end
58
+
59
+ def find_belongs_to(method, *args, &block)
60
+ foreign_key = self.class.columns.select {|column| column.name == method.to_s.foreign_key}.first
61
+ return add_belongs_to(method, *args, &block) if foreign_key
62
+ end
63
+
64
+ def add_belongs_to(method, *args, &block)
65
+ self.class.send 'belongs_to', method
66
+ self.send(method, *args, &block)
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,45 @@
1
+ module DrNic
2
+ module MagicModels
3
+ class Schema
4
+ class << self
5
+ def models
6
+ @@models ||= nil
7
+ load_schema if @@models.blank?
8
+ @@models
9
+ end
10
+
11
+ def reset
12
+ @@models = nil
13
+ end
14
+
15
+ def load_schema
16
+ if conn = ActiveRecord::Base.connection
17
+ @@models = DrNic::MagicModels::ModelHash.new
18
+ conn.tables.inspect
19
+ @@models.merge! conn.tables.inject({}) {|model_list,table_name| model_list[ActiveRecord::Base.class_name(table_name)] = table_name; model_list}
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ class ModelHash < Hash
26
+ def unenquire(class_id)
27
+ @enquired ||= {}
28
+ @enquired[class_id = class_id.to_s] = false
29
+ end
30
+
31
+ def enquired?(class_id)
32
+ @enquired ||= {}
33
+ result = @enquired[class_id.to_s]
34
+ #@enquired[class_id = class_id.to_s] = true
35
+ result
36
+ end
37
+
38
+ def [](class_id)
39
+ enquired?(class_id = class_id.to_s)
40
+ @enquired[class_id] = true
41
+ super(class_id)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,28 @@
1
+ module DrNic
2
+ module MagicModels
3
+ module Validations
4
+ def self.append_features(base)
5
+ super
6
+ base.extend(ClassMethods)
7
+ base.generate_validations
8
+
9
+ # Currently only invoked on generated classes
10
+ # How to include and invoke on all ARs? - hook into class loading??
11
+ end
12
+
13
+ module ClassMethods
14
+ def generate_validations
15
+ unless @@generated_validations ||= false
16
+ @@generated_validations = true
17
+ column_names = self.columns.select {|column| !column.null and !column.primary}.map {|column| column.name.to_sym}
18
+ add_validation :validates_presence_of, column_names
19
+ end
20
+ end
21
+
22
+ def add_validation(validation, column_names)
23
+ self.send validation, *column_names
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ module DrNic #:nodoc:
2
+ module MagicModels #:nodoc:
3
+ module VERSION #:nodoc:
4
+ MAJOR = 0
5
+ MINOR = 2
6
+ TINY = 5
7
+
8
+ STRING = [MAJOR, MINOR, TINY].join('.')
9
+ end
10
+ end
11
+ end
data/lib/dr_nic.rb ADDED
@@ -0,0 +1,17 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ unless defined?(ActiveRecord)
5
+ begin
6
+ $:.unshift(File.dirname(__FILE__) + "/../../activerecord/lib")
7
+ require 'active_record'
8
+ rescue LoadError
9
+ require 'rubygems'
10
+ require_gem 'activerecord'
11
+ end
12
+ end
13
+
14
+ require 'dr_nic/magic_models/schema'
15
+ require 'dr_nic/magic_models/validations'
16
+ require 'module'
17
+ require 'base'
data/lib/module.rb ADDED
@@ -0,0 +1,16 @@
1
+ class Module
2
+ alias :normal_const_missing :const_missing
3
+
4
+ def const_missing(class_id)
5
+ begin
6
+ return normal_const_missing(class_id)
7
+ rescue
8
+ end
9
+ unless table_name = DrNic::MagicModels::Schema.models[class_id]
10
+ raise NameError.new("uninitialized constant #{class_id}") if DrNic::MagicModels::Schema.models.enquired? class_id
11
+ end
12
+ klass_code = lambda {klass_code}
13
+ klass = Class.new ActiveRecord::Base, &klass_code
14
+ const_set class_id, klass
15
+ end
16
+ end
@@ -0,0 +1,68 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'test/unit'
4
+ require 'active_record'
5
+ require 'active_record/fixtures'
6
+ require 'active_support/binding_of_caller'
7
+ require 'active_support/breakpoint'
8
+ require 'connection'
9
+ require 'dr_nic'
10
+
11
+ QUOTED_TYPE = ActiveRecord::Base.connection.quote_column_name('type') unless Object.const_defined?(:QUOTED_TYPE)
12
+
13
+ class Test::Unit::TestCase #:nodoc:
14
+ self.fixture_path = File.dirname(__FILE__) + "/fixtures/"
15
+ self.use_instantiated_fixtures = false
16
+ self.use_transactional_fixtures = true #(ENV['AR_NO_TX_FIXTURES'] != "yes")
17
+
18
+ def create_fixtures(*table_names, &block)
19
+ Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures/", table_names, {}, &block)
20
+ end
21
+
22
+ def assert_date_from_db(expected, actual, message = nil)
23
+ # SQL Server doesn't have a separate column type just for dates,
24
+ # so the time is in the string and incorrectly formatted
25
+ if current_adapter?(:SQLServerAdapter)
26
+ assert_equal expected.strftime("%Y/%m/%d 00:00:00"), actual.strftime("%Y/%m/%d 00:00:00")
27
+ elsif current_adapter?(:SybaseAdapter)
28
+ assert_equal expected.to_s, actual.to_date.to_s, message
29
+ else
30
+ assert_equal expected.to_s, actual.to_s, message
31
+ end
32
+ end
33
+
34
+ def assert_queries(num = 1)
35
+ ActiveRecord::Base.connection.class.class_eval do
36
+ self.query_count = 0
37
+ alias_method :execute, :execute_with_query_counting
38
+ end
39
+ yield
40
+ ensure
41
+ ActiveRecord::Base.connection.class.class_eval do
42
+ alias_method :execute, :execute_without_query_counting
43
+ end
44
+ assert_equal num, ActiveRecord::Base.connection.query_count, "#{ActiveRecord::Base.connection.query_count} instead of #{num} queries were executed."
45
+ end
46
+
47
+ def assert_no_queries(&block)
48
+ assert_queries(0, &block)
49
+ end
50
+
51
+ end
52
+
53
+ def current_adapter?(type)
54
+ ActiveRecord::ConnectionAdapters.const_defined?(type) &&
55
+ ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters.const_get(type))
56
+ end
57
+
58
+ ActiveRecord::Base.connection.class.class_eval do
59
+ cattr_accessor :query_count
60
+ alias_method :execute_without_query_counting, :execute
61
+ def execute_with_query_counting(sql, name = nil)
62
+ self.query_count += 1
63
+ execute_without_query_counting(sql, name)
64
+ end
65
+ end
66
+
67
+ #ActiveRecord::Base.logger = Logger.new(STDOUT)
68
+ #ActiveRecord::Base.colorize_logging = false
@@ -0,0 +1,13 @@
1
+ print "Using native MySQL\n"
2
+ require 'logger'
3
+
4
+ ActiveRecord::Base.logger = Logger.new("debug.log")
5
+
6
+ db1 = "dr_nic_magic_models_unittest"
7
+
8
+ ActiveRecord::Base.establish_connection(
9
+ :adapter => "mysql",
10
+ :username => "root",
11
+ :encoding => "utf8",
12
+ :database => db1
13
+ )
@@ -0,0 +1,13 @@
1
+ require 'abstract_unit'
2
+ #require 'fixtures/users'
3
+ #require 'fixtures/groups'
4
+ #require 'fixtures/memberships'
5
+
6
+ class DummyTest < Test::Unit::TestCase
7
+ def setup
8
+ end
9
+
10
+ def test_truth
11
+ assert true
12
+ end
13
+ end
data/test/env_test.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'abstract_unit'
2
+
3
+ class EnvTest < Test::Unit::TestCase
4
+
5
+ def test_modules
6
+ assert_not_nil DrNic
7
+ assert_not_nil DrNic::MagicModels
8
+ assert_not_nil DrNic::MagicModels::Validations
9
+ assert_not_nil DrNic::MagicModels::Schema
10
+ end
11
+ end
@@ -0,0 +1,30 @@
1
+ DROP TABLE accounts;
2
+ DROP TABLE funny_jokes;
3
+ DROP TABLE companies;
4
+ DROP TABLE topics;
5
+ DROP TABLE developers;
6
+ DROP TABLE projects;
7
+ DROP TABLE developers_projects;
8
+ DROP TABLE customers;
9
+ DROP TABLE orders;
10
+ DROP TABLE movies;
11
+ DROP TABLE subscribers;
12
+ DROP TABLE booleantests;
13
+ DROP TABLE auto_id_tests;
14
+ DROP TABLE entrants;
15
+ DROP TABLE colnametests;
16
+ DROP TABLE mixins;
17
+ DROP TABLE people;
18
+ DROP TABLE readers;
19
+ DROP TABLE binaries;
20
+ DROP TABLE computers;
21
+ DROP TABLE tasks;
22
+ DROP TABLE posts;
23
+ DROP TABLE comments;
24
+ DROP TABLE authors;
25
+ DROP TABLE categories;
26
+ DROP TABLE categories_posts;
27
+ DROP TABLE fk_test_has_fk;
28
+ DROP TABLE fk_test_has_pk;
29
+ DROP TABLE keyboards;
30
+ DROP TABLE legacy_things;
@@ -0,0 +1,32 @@
1
+ CREATE TABLE `users` (
2
+ `id` int(11) NOT NULL auto_increment,
3
+ `firstname` varchar(50) NOT NULL,
4
+ `lastname` varchar(50) NOT NULL,
5
+ `login` varchar(50) NOT NULL,
6
+ `email` varchar(50) NULL,
7
+ PRIMARY KEY (`id`)
8
+ ) TYPE=InnoDB;
9
+
10
+ CREATE TABLE `groups` (
11
+ `id` int(11) NOT NULL auto_increment,
12
+ `name` int(11) NOT NULL,
13
+ `description` varchar(50) default NULL,
14
+ PRIMARY KEY (`id`)
15
+ ) TYPE=InnoDB;
16
+
17
+ CREATE TABLE `memberships` (
18
+ `id` int(11) NOT NULL auto_increment,
19
+ `user_id` int(11) NOT NULL,
20
+ `group_id` int(11) NOT NULL,
21
+ PRIMARY KEY (`id`)
22
+ ) TYPE=InnoDB;
23
+
24
+ CREATE TABLE `person` (
25
+ `id` int(11) NOT NULL auto_increment,
26
+ `firstname` varchar(50) NOT NULL,
27
+ `lastname` varchar(50) NOT NULL,
28
+ `login` varchar(50) NOT NULL,
29
+ `email` varchar(50) NULL,
30
+ PRIMARY KEY (`id`)
31
+ ) TYPE=InnoDB;
32
+
@@ -0,0 +1,7 @@
1
+ class ReferenceCode < ActiveRecord::Base
2
+ set_primary_keys :reference_type_id, :reference_code
3
+
4
+ belongs_to :reference_type, :foreign_key => "reference_type_id"
5
+
6
+ validates_presence_of :reference_code, :code_label, :abbreviation
7
+ end
@@ -0,0 +1,28 @@
1
+ name_prefix_mr:
2
+ reference_type_id: 1
3
+ reference_code: 1
4
+ code_label: MR
5
+ abbreviation: Mr
6
+ name_prefix_mrs:
7
+ reference_type_id: 1
8
+ reference_code: 2
9
+ code_label: MRS
10
+ abbreviation: Mrs
11
+ name_prefix_ms:
12
+ reference_type_id: 1
13
+ reference_code: 3
14
+ code_label: MS
15
+ abbreviation: Ms
16
+
17
+ gender_male:
18
+ reference_type_id: 2
19
+ reference_code: 1
20
+ code_label: MALE
21
+ abbreviation: Male
22
+ gender_female:
23
+ reference_type_id: 2
24
+ reference_code: 2
25
+ code_label: FEMALE
26
+ abbreviation: Female
27
+
28
+
@@ -0,0 +1,7 @@
1
+ class ReferenceType < ActiveRecord::Base
2
+ set_primary_key :reference_type_id
3
+ has_many :reference_codes, :foreign_key => "reference_type_id"
4
+
5
+ validates_presence_of :type_label, :abbreviation
6
+ validates_uniqueness_of :type_label
7
+ end
@@ -0,0 +1,9 @@
1
+ name_prefix:
2
+ reference_type_id: 1
3
+ type_label: NAME_PREFIX
4
+ abbreviation: Name Prefix
5
+
6
+ gender:
7
+ reference_type_id: 2
8
+ type_label: GENDER
9
+ abbreviation: Gender
@@ -0,0 +1,20 @@
1
+ require 'abstract_unit'
2
+
3
+ class InvisibleModelClassesTest < Test::Unit::TestCase
4
+
5
+ def test_available
6
+ assert_not_nil Group
7
+ assert_not_nil User
8
+ assert_not_nil Membership
9
+ assert_not_nil Person, "Could not find Person with singularized table name 'person'"
10
+ end
11
+
12
+ def test_table_names
13
+ assert_equal 'groups', Group.table_name
14
+ assert_equal 'users', User.table_name
15
+ assert_equal 'memberships', Membership.table_name
16
+ assert_equal 'person', Person.table_name
17
+ end
18
+
19
+
20
+ end
@@ -0,0 +1,45 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
6
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7
+ <title>
8
+ Dr Nic&#8217;s Magic Models
9
+ </title>
10
+ <script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
11
+ <style>
12
+
13
+ </style>
14
+ <script type="text/javascript">
15
+ window.onload = function() {
16
+ settings = {
17
+ tl: { radius: 10 },
18
+ tr: { radius: 10 },
19
+ bl: { radius: 10 },
20
+ br: { radius: 10 },
21
+ antiAlias: true,
22
+ autoPad: true,
23
+ validTags: ["div"]
24
+ }
25
+ var versionBox = new curvyCorners(settings, document.getElementById("version"));
26
+ versionBox.applyCornersToAll();
27
+ }
28
+ </script>
29
+ </head>
30
+ <body>
31
+ <div id="main">
32
+
33
+ <h1>Dr Nic&#8217;s Magic Models</h1>
34
+ <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/magicmodels"; return false'>
35
+ Get Version
36
+ <a href="http://rubyforge.org/projects/magicmodels" class="numbers">0.2.5</a>
37
+ </div>
38
+ <h2>Instant look-see</h2>
39
+ <p class="coda">
40
+ <a href="mailto:drnicwilliams@gmail.com">Dr Nic</a>, 28th July 2006<br>
41
+ Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
42
+ </p>
43
+ </div>
44
+ </body>
45
+ </html>
data/website/index.txt ADDED
@@ -0,0 +1,4 @@
1
+ h1. Dr Nic's Magic Models
2
+
3
+ h2. Instant look-see
4
+
@@ -0,0 +1,285 @@
1
+
2
+ /****************************************************************
3
+ * *
4
+ * curvyCorners *
5
+ * ------------ *
6
+ * *
7
+ * This script generates rounded corners for your divs. *
8
+ * *
9
+ * Version 1.2.9 *
10
+ * Copyright (c) 2006 Cameron Cooke *
11
+ * By: Cameron Cooke and Tim Hutchison. *
12
+ * *
13
+ * *
14
+ * Website: http://www.curvycorners.net *
15
+ * Email: info@totalinfinity.com *
16
+ * Forum: http://www.curvycorners.net/forum/ *
17
+ * *
18
+ * *
19
+ * This library is free software; you can redistribute *
20
+ * it and/or modify it under the terms of the GNU *
21
+ * Lesser General Public License as published by the *
22
+ * Free Software Foundation; either version 2.1 of the *
23
+ * License, or (at your option) any later version. *
24
+ * *
25
+ * This library is distributed in the hope that it will *
26
+ * be useful, but WITHOUT ANY WARRANTY; without even the *
27
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A *
28
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public *
29
+ * License for more details. *
30
+ * *
31
+ * You should have received a copy of the GNU Lesser *
32
+ * General Public License along with this library; *
33
+ * Inc., 59 Temple Place, Suite 330, Boston, *
34
+ * MA 02111-1307 USA *
35
+ * *
36
+ ****************************************************************/
37
+
38
+ var isIE = navigator.userAgent.toLowerCase().indexOf("msie") > -1; var isMoz = document.implementation && document.implementation.createDocument; var isSafari = ((navigator.userAgent.toLowerCase().indexOf('safari')!=-1)&&(navigator.userAgent.toLowerCase().indexOf('mac')!=-1))?true:false; function curvyCorners()
39
+ { if(typeof(arguments[0]) != "object") throw newCurvyError("First parameter of curvyCorners() must be an object."); if(typeof(arguments[1]) != "object" && typeof(arguments[1]) != "string") throw newCurvyError("Second parameter of curvyCorners() must be an object or a class name."); if(typeof(arguments[1]) == "string")
40
+ { var startIndex = 0; var boxCol = getElementsByClass(arguments[1]);}
41
+ else
42
+ { var startIndex = 1; var boxCol = arguments;}
43
+ var curvyCornersCol = new Array(); if(arguments[0].validTags)
44
+ var validElements = arguments[0].validTags; else
45
+ var validElements = ["div"]; for(var i = startIndex, j = boxCol.length; i < j; i++)
46
+ { var currentTag = boxCol[i].tagName.toLowerCase(); if(inArray(validElements, currentTag) !== false)
47
+ { curvyCornersCol[curvyCornersCol.length] = new curvyObject(arguments[0], boxCol[i]);}
48
+ }
49
+ this.objects = curvyCornersCol; this.applyCornersToAll = function()
50
+ { for(var x = 0, k = this.objects.length; x < k; x++)
51
+ { this.objects[x].applyCorners();}
52
+ }
53
+ }
54
+ function curvyObject()
55
+ { this.box = arguments[1]; this.settings = arguments[0]; this.topContainer = null; this.bottomContainer = null; this.masterCorners = new Array(); this.contentDIV = null; var boxHeight = get_style(this.box, "height", "height"); var boxWidth = get_style(this.box, "width", "width"); var borderWidth = get_style(this.box, "borderTopWidth", "border-top-width"); var borderColour = get_style(this.box, "borderTopColor", "border-top-color"); var boxColour = get_style(this.box, "backgroundColor", "background-color"); var backgroundImage = get_style(this.box, "backgroundImage", "background-image"); var boxPosition = get_style(this.box, "position", "position"); var boxPadding = get_style(this.box, "paddingTop", "padding-top"); this.boxHeight = parseInt(((boxHeight != "" && boxHeight != "auto" && boxHeight.indexOf("%") == -1)? boxHeight.substring(0, boxHeight.indexOf("px")) : this.box.scrollHeight)); this.boxWidth = parseInt(((boxWidth != "" && boxWidth != "auto" && boxWidth.indexOf("%") == -1)? boxWidth.substring(0, boxWidth.indexOf("px")) : this.box.scrollWidth)); this.borderWidth = parseInt(((borderWidth != "" && borderWidth.indexOf("px") !== -1)? borderWidth.slice(0, borderWidth.indexOf("px")) : 0)); this.boxColour = format_colour(boxColour); this.boxPadding = parseInt(((boxPadding != "" && boxPadding.indexOf("px") !== -1)? boxPadding.slice(0, boxPadding.indexOf("px")) : 0)); this.borderColour = format_colour(borderColour); this.borderString = this.borderWidth + "px" + " solid " + this.borderColour; this.backgroundImage = ((backgroundImage != "none")? backgroundImage : ""); this.boxContent = this.box.innerHTML; if(boxPosition != "absolute") this.box.style.position = "relative"; this.box.style.padding = "0px"; if(isIE && boxWidth == "auto" && boxHeight == "auto") this.box.style.width = "100%"; if(this.settings.autoPad == true && this.boxPadding > 0)
56
+ this.box.innerHTML = ""; this.applyCorners = function()
57
+ { for(var t = 0; t < 2; t++)
58
+ { switch(t)
59
+ { case 0:
60
+ if(this.settings.tl || this.settings.tr)
61
+ { var newMainContainer = document.createElement("DIV"); newMainContainer.style.width = "100%"; newMainContainer.style.fontSize = "1px"; newMainContainer.style.overflow = "hidden"; newMainContainer.style.position = "absolute"; newMainContainer.style.paddingLeft = this.borderWidth + "px"; newMainContainer.style.paddingRight = this.borderWidth + "px"; var topMaxRadius = Math.max(this.settings.tl ? this.settings.tl.radius : 0, this.settings.tr ? this.settings.tr.radius : 0); newMainContainer.style.height = topMaxRadius + "px"; newMainContainer.style.top = 0 - topMaxRadius + "px"; newMainContainer.style.left = 0 - this.borderWidth + "px"; this.topContainer = this.box.appendChild(newMainContainer);}
62
+ break; case 1:
63
+ if(this.settings.bl || this.settings.br)
64
+ { var newMainContainer = document.createElement("DIV"); newMainContainer.style.width = "100%"; newMainContainer.style.fontSize = "1px"; newMainContainer.style.overflow = "hidden"; newMainContainer.style.position = "absolute"; newMainContainer.style.paddingLeft = this.borderWidth + "px"; newMainContainer.style.paddingRight = this.borderWidth + "px"; var botMaxRadius = Math.max(this.settings.bl ? this.settings.bl.radius : 0, this.settings.br ? this.settings.br.radius : 0); newMainContainer.style.height = botMaxRadius + "px"; newMainContainer.style.bottom = 0 - botMaxRadius + "px"; newMainContainer.style.left = 0 - this.borderWidth + "px"; this.bottomContainer = this.box.appendChild(newMainContainer);}
65
+ break;}
66
+ }
67
+ if(this.topContainer) this.box.style.borderTopWidth = "0px"; if(this.bottomContainer) this.box.style.borderBottomWidth = "0px"; var corners = ["tr", "tl", "br", "bl"]; for(var i in corners)
68
+ { if(i > -1 < 4)
69
+ { var cc = corners[i]; if(!this.settings[cc])
70
+ { if(((cc == "tr" || cc == "tl") && this.topContainer != null) || ((cc == "br" || cc == "bl") && this.bottomContainer != null))
71
+ { var newCorner = document.createElement("DIV"); newCorner.style.position = "relative"; newCorner.style.fontSize = "1px"; newCorner.style.overflow = "hidden"; if(this.backgroundImage == "")
72
+ newCorner.style.backgroundColor = this.boxColour; else
73
+ newCorner.style.backgroundImage = this.backgroundImage; switch(cc)
74
+ { case "tl":
75
+ newCorner.style.height = topMaxRadius - this.borderWidth + "px"; newCorner.style.marginRight = this.settings.tr.radius - (this.borderWidth*2) + "px"; newCorner.style.borderLeft = this.borderString; newCorner.style.borderTop = this.borderString; newCorner.style.left = -this.borderWidth + "px"; break; case "tr":
76
+ newCorner.style.height = topMaxRadius - this.borderWidth + "px"; newCorner.style.marginLeft = this.settings.tl.radius - (this.borderWidth*2) + "px"; newCorner.style.borderRight = this.borderString; newCorner.style.borderTop = this.borderString; newCorner.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px"; newCorner.style.left = this.borderWidth + "px"; break; case "bl":
77
+ newCorner.style.height = botMaxRadius - this.borderWidth + "px"; newCorner.style.marginRight = this.settings.br.radius - (this.borderWidth*2) + "px"; newCorner.style.borderLeft = this.borderString; newCorner.style.borderBottom = this.borderString; newCorner.style.left = -this.borderWidth + "px"; newCorner.style.backgroundPosition = "-" + (this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px"; break; case "br":
78
+ newCorner.style.height = botMaxRadius - this.borderWidth + "px"; newCorner.style.marginLeft = this.settings.bl.radius - (this.borderWidth*2) + "px"; newCorner.style.borderRight = this.borderString; newCorner.style.borderBottom = this.borderString; newCorner.style.left = this.borderWidth + "px"
79
+ newCorner.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px"; break;}
80
+ }
81
+ }
82
+ else
83
+ { if(this.masterCorners[this.settings[cc].radius])
84
+ { var newCorner = this.masterCorners[this.settings[cc].radius].cloneNode(true);}
85
+ else
86
+ { var newCorner = document.createElement("DIV"); newCorner.style.height = this.settings[cc].radius + "px"; newCorner.style.width = this.settings[cc].radius + "px"; newCorner.style.position = "absolute"; newCorner.style.fontSize = "1px"; newCorner.style.overflow = "hidden"; var borderRadius = parseInt(this.settings[cc].radius - this.borderWidth); for(var intx = 0, j = this.settings[cc].radius; intx < j; intx++)
87
+ { if((intx +1) >= borderRadius)
88
+ var y1 = -1; else
89
+ var y1 = (Math.floor(Math.sqrt(Math.pow(borderRadius, 2) - Math.pow((intx+1), 2))) - 1); if(borderRadius != j)
90
+ { if((intx) >= borderRadius)
91
+ var y2 = -1; else
92
+ var y2 = Math.ceil(Math.sqrt(Math.pow(borderRadius,2) - Math.pow(intx, 2))); if((intx+1) >= j)
93
+ var y3 = -1; else
94
+ var y3 = (Math.floor(Math.sqrt(Math.pow(j ,2) - Math.pow((intx+1), 2))) - 1);}
95
+ if((intx) >= j)
96
+ var y4 = -1; else
97
+ var y4 = Math.ceil(Math.sqrt(Math.pow(j ,2) - Math.pow(intx, 2))); if(y1 > -1) this.drawPixel(intx, 0, this.boxColour, 100, (y1+1), newCorner, -1, this.settings[cc].radius); if(borderRadius != j)
98
+ { for(var inty = (y1 + 1); inty < y2; inty++)
99
+ { if(this.settings.antiAlias)
100
+ { if(this.backgroundImage != "")
101
+ { var borderFract = (pixelFraction(intx, inty, borderRadius) * 100); if(borderFract < 30)
102
+ { this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, 0, this.settings[cc].radius);}
103
+ else
104
+ { this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, -1, this.settings[cc].radius);}
105
+ }
106
+ else
107
+ { var pixelcolour = BlendColour(this.boxColour, this.borderColour, pixelFraction(intx, inty, borderRadius)); this.drawPixel(intx, inty, pixelcolour, 100, 1, newCorner, 0, this.settings[cc].radius, cc);}
108
+ }
109
+ }
110
+ if(this.settings.antiAlias)
111
+ { if(y3 >= y2)
112
+ { if (y2 == -1) y2 = 0; this.drawPixel(intx, y2, this.borderColour, 100, (y3 - y2 + 1), newCorner, 0, 0);}
113
+ }
114
+ else
115
+ { if(y3 >= y1)
116
+ { this.drawPixel(intx, (y1 + 1), this.borderColour, 100, (y3 - y1), newCorner, 0, 0);}
117
+ }
118
+ var outsideColour = this.borderColour;}
119
+ else
120
+ { var outsideColour = this.boxColour; var y3 = y1;}
121
+ if(this.settings.antiAlias)
122
+ { for(var inty = (y3 + 1); inty < y4; inty++)
123
+ { this.drawPixel(intx, inty, outsideColour, (pixelFraction(intx, inty , j) * 100), 1, newCorner, ((this.borderWidth > 0)? 0 : -1), this.settings[cc].radius);}
124
+ }
125
+ }
126
+ this.masterCorners[this.settings[cc].radius] = newCorner.cloneNode(true);}
127
+ if(cc != "br")
128
+ { for(var t = 0, k = newCorner.childNodes.length; t < k; t++)
129
+ { var pixelBar = newCorner.childNodes[t]; var pixelBarTop = parseInt(pixelBar.style.top.substring(0, pixelBar.style.top.indexOf("px"))); var pixelBarLeft = parseInt(pixelBar.style.left.substring(0, pixelBar.style.left.indexOf("px"))); var pixelBarHeight = parseInt(pixelBar.style.height.substring(0, pixelBar.style.height.indexOf("px"))); if(cc == "tl" || cc == "bl"){ pixelBar.style.left = this.settings[cc].radius -pixelBarLeft -1 + "px";}
130
+ if(cc == "tr" || cc == "tl"){ pixelBar.style.top = this.settings[cc].radius -pixelBarHeight -pixelBarTop + "px";}
131
+ switch(cc)
132
+ { case "tr":
133
+ pixelBar.style.backgroundPosition = "-" + Math.abs((this.boxWidth - this.settings[cc].radius + this.borderWidth) + pixelBarLeft) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px"; break; case "tl":
134
+ pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px"; break; case "bl":
135
+ pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs((this.boxHeight + this.settings[cc].radius + pixelBarTop) -this.borderWidth) + "px"; break;}
136
+ }
137
+ }
138
+ }
139
+ if(newCorner)
140
+ { switch(cc)
141
+ { case "tl":
142
+ if(newCorner.style.position == "absolute") newCorner.style.top = "0px"; if(newCorner.style.position == "absolute") newCorner.style.left = "0px"; if(this.topContainer) this.topContainer.appendChild(newCorner); break; case "tr":
143
+ if(newCorner.style.position == "absolute") newCorner.style.top = "0px"; if(newCorner.style.position == "absolute") newCorner.style.right = "0px"; if(this.topContainer) this.topContainer.appendChild(newCorner); break; case "bl":
144
+ if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px"; if(newCorner.style.position == "absolute") newCorner.style.left = "0px"; if(this.bottomContainer) this.bottomContainer.appendChild(newCorner); break; case "br":
145
+ if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px"; if(newCorner.style.position == "absolute") newCorner.style.right = "0px"; if(this.bottomContainer) this.bottomContainer.appendChild(newCorner); break;}
146
+ }
147
+ }
148
+ }
149
+ var radiusDiff = new Array(); radiusDiff["t"] = Math.abs(this.settings.tl.radius - this.settings.tr.radius)
150
+ radiusDiff["b"] = Math.abs(this.settings.bl.radius - this.settings.br.radius); for(z in radiusDiff)
151
+ { if(z == "t" || z == "b")
152
+ { if(radiusDiff[z])
153
+ { var smallerCornerType = ((this.settings[z + "l"].radius < this.settings[z + "r"].radius)? z +"l" : z +"r"); var newFiller = document.createElement("DIV"); newFiller.style.height = radiusDiff[z] + "px"; newFiller.style.width = this.settings[smallerCornerType].radius+ "px"
154
+ newFiller.style.position = "absolute"; newFiller.style.fontSize = "1px"; newFiller.style.overflow = "hidden"; newFiller.style.backgroundColor = this.boxColour; switch(smallerCornerType)
155
+ { case "tl":
156
+ newFiller.style.bottom = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.topContainer.appendChild(newFiller); break; case "tr":
157
+ newFiller.style.bottom = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.topContainer.appendChild(newFiller); break; case "bl":
158
+ newFiller.style.top = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.bottomContainer.appendChild(newFiller); break; case "br":
159
+ newFiller.style.top = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.bottomContainer.appendChild(newFiller); break;}
160
+ }
161
+ var newFillerBar = document.createElement("DIV"); newFillerBar.style.position = "relative"; newFillerBar.style.fontSize = "1px"; newFillerBar.style.overflow = "hidden"; newFillerBar.style.backgroundColor = this.boxColour; newFillerBar.style.backgroundImage = this.backgroundImage; switch(z)
162
+ { case "t":
163
+ if(this.topContainer)
164
+ { if(this.settings.tl.radius && this.settings.tr.radius)
165
+ { newFillerBar.style.height = topMaxRadius - this.borderWidth + "px"; newFillerBar.style.marginLeft = this.settings.tl.radius - this.borderWidth + "px"; newFillerBar.style.marginRight = this.settings.tr.radius - this.borderWidth + "px"; newFillerBar.style.borderTop = this.borderString; if(this.backgroundImage != "")
166
+ newFillerBar.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px"; this.topContainer.appendChild(newFillerBar);}
167
+ this.box.style.backgroundPosition = "0px -" + (topMaxRadius - this.borderWidth) + "px";}
168
+ break; case "b":
169
+ if(this.bottomContainer)
170
+ { if(this.settings.bl.radius && this.settings.br.radius)
171
+ { newFillerBar.style.height = botMaxRadius - this.borderWidth + "px"; newFillerBar.style.marginLeft = this.settings.bl.radius - this.borderWidth + "px"; newFillerBar.style.marginRight = this.settings.br.radius - this.borderWidth + "px"; newFillerBar.style.borderBottom = this.borderString; if(this.backgroundImage != "")
172
+ newFillerBar.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (topMaxRadius + this.borderWidth)) + "px"; this.bottomContainer.appendChild(newFillerBar);}
173
+ }
174
+ break;}
175
+ }
176
+ }
177
+ if(this.settings.autoPad == true && this.boxPadding > 0)
178
+ { var contentContainer = document.createElement("DIV"); contentContainer.style.position = "relative"; contentContainer.innerHTML = this.boxContent; contentContainer.className = "autoPadDiv"; var topPadding = Math.abs(topMaxRadius - this.boxPadding); var botPadding = Math.abs(botMaxRadius - this.boxPadding); if(topMaxRadius < this.boxPadding)
179
+ contentContainer.style.paddingTop = topPadding + "px"; if(botMaxRadius < this.boxPadding)
180
+ contentContainer.style.paddingBottom = botMaxRadius + "px"; contentContainer.style.paddingLeft = this.boxPadding + "px"; contentContainer.style.paddingRight = this.boxPadding + "px"; this.contentDIV = this.box.appendChild(contentContainer);}
181
+ }
182
+ this.drawPixel = function(intx, inty, colour, transAmount, height, newCorner, image, cornerRadius)
183
+ { var pixel = document.createElement("DIV"); pixel.style.height = height + "px"; pixel.style.width = "1px"; pixel.style.position = "absolute"; pixel.style.fontSize = "1px"; pixel.style.overflow = "hidden"; var topMaxRadius = Math.max(this.settings["tr"].radius, this.settings["tl"].radius); if(image == -1 && this.backgroundImage != "")
184
+ { pixel.style.backgroundImage = this.backgroundImage; pixel.style.backgroundPosition = "-" + (this.boxWidth - (cornerRadius - intx) + this.borderWidth) + "px -" + ((this.boxHeight + topMaxRadius + inty) -this.borderWidth) + "px";}
185
+ else
186
+ { pixel.style.backgroundColor = colour;}
187
+ if (transAmount != 100)
188
+ setOpacity(pixel, transAmount); pixel.style.top = inty + "px"; pixel.style.left = intx + "px"; newCorner.appendChild(pixel);}
189
+ }
190
+ function insertAfter(parent, node, referenceNode)
191
+ { parent.insertBefore(node, referenceNode.nextSibling);}
192
+ function BlendColour(Col1, Col2, Col1Fraction)
193
+ { var red1 = parseInt(Col1.substr(1,2),16); var green1 = parseInt(Col1.substr(3,2),16); var blue1 = parseInt(Col1.substr(5,2),16); var red2 = parseInt(Col2.substr(1,2),16); var green2 = parseInt(Col2.substr(3,2),16); var blue2 = parseInt(Col2.substr(5,2),16); if(Col1Fraction > 1 || Col1Fraction < 0) Col1Fraction = 1; var endRed = Math.round((red1 * Col1Fraction) + (red2 * (1 - Col1Fraction))); if(endRed > 255) endRed = 255; if(endRed < 0) endRed = 0; var endGreen = Math.round((green1 * Col1Fraction) + (green2 * (1 - Col1Fraction))); if(endGreen > 255) endGreen = 255; if(endGreen < 0) endGreen = 0; var endBlue = Math.round((blue1 * Col1Fraction) + (blue2 * (1 - Col1Fraction))); if(endBlue > 255) endBlue = 255; if(endBlue < 0) endBlue = 0; return "#" + IntToHex(endRed)+ IntToHex(endGreen)+ IntToHex(endBlue);}
194
+ function IntToHex(strNum)
195
+ { base = strNum / 16; rem = strNum % 16; base = base - (rem / 16); baseS = MakeHex(base); remS = MakeHex(rem); return baseS + '' + remS;}
196
+ function MakeHex(x)
197
+ { if((x >= 0) && (x <= 9))
198
+ { return x;}
199
+ else
200
+ { switch(x)
201
+ { case 10: return "A"; case 11: return "B"; case 12: return "C"; case 13: return "D"; case 14: return "E"; case 15: return "F";}
202
+ }
203
+ }
204
+ function pixelFraction(x, y, r)
205
+ { var pixelfraction = 0; var xvalues = new Array(1); var yvalues = new Array(1); var point = 0; var whatsides = ""; var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x,2))); if ((intersect >= y) && (intersect < (y+1)))
206
+ { whatsides = "Left"; xvalues[point] = 0; yvalues[point] = intersect - y; point = point + 1;}
207
+ var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y+1,2))); if ((intersect >= x) && (intersect < (x+1)))
208
+ { whatsides = whatsides + "Top"; xvalues[point] = intersect - x; yvalues[point] = 1; point = point + 1;}
209
+ var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x+1,2))); if ((intersect >= y) && (intersect < (y+1)))
210
+ { whatsides = whatsides + "Right"; xvalues[point] = 1; yvalues[point] = intersect - y; point = point + 1;}
211
+ var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y,2))); if ((intersect >= x) && (intersect < (x+1)))
212
+ { whatsides = whatsides + "Bottom"; xvalues[point] = intersect - x; yvalues[point] = 0;}
213
+ switch (whatsides)
214
+ { case "LeftRight":
215
+ pixelfraction = Math.min(yvalues[0],yvalues[1]) + ((Math.max(yvalues[0],yvalues[1]) - Math.min(yvalues[0],yvalues[1]))/2); break; case "TopRight":
216
+ pixelfraction = 1-(((1-xvalues[0])*(1-yvalues[1]))/2); break; case "TopBottom":
217
+ pixelfraction = Math.min(xvalues[0],xvalues[1]) + ((Math.max(xvalues[0],xvalues[1]) - Math.min(xvalues[0],xvalues[1]))/2); break; case "LeftBottom":
218
+ pixelfraction = (yvalues[0]*xvalues[1])/2; break; default:
219
+ pixelfraction = 1;}
220
+ return pixelfraction;}
221
+ function rgb2Hex(rgbColour)
222
+ { try{ var rgbArray = rgb2Array(rgbColour); var red = parseInt(rgbArray[0]); var green = parseInt(rgbArray[1]); var blue = parseInt(rgbArray[2]); var hexColour = "#" + IntToHex(red) + IntToHex(green) + IntToHex(blue);}
223
+ catch(e){ alert("There was an error converting the RGB value to Hexadecimal in function rgb2Hex");}
224
+ return hexColour;}
225
+ function rgb2Array(rgbColour)
226
+ { var rgbValues = rgbColour.substring(4, rgbColour.indexOf(")")); var rgbArray = rgbValues.split(", "); return rgbArray;}
227
+ function setOpacity(obj, opacity)
228
+ { opacity = (opacity == 100)?99.999:opacity; if(isSafari && obj.tagName != "IFRAME")
229
+ { var rgbArray = rgb2Array(obj.style.backgroundColor); var red = parseInt(rgbArray[0]); var green = parseInt(rgbArray[1]); var blue = parseInt(rgbArray[2]); obj.style.backgroundColor = "rgba(" + red + ", " + green + ", " + blue + ", " + opacity/100 + ")";}
230
+ else if(typeof(obj.style.opacity) != "undefined")
231
+ { obj.style.opacity = opacity/100;}
232
+ else if(typeof(obj.style.MozOpacity) != "undefined")
233
+ { obj.style.MozOpacity = opacity/100;}
234
+ else if(typeof(obj.style.filter) != "undefined")
235
+ { obj.style.filter = "alpha(opacity:" + opacity + ")";}
236
+ else if(typeof(obj.style.KHTMLOpacity) != "undefined")
237
+ { obj.style.KHTMLOpacity = opacity/100;}
238
+ }
239
+ function inArray(array, value)
240
+ { for(var i = 0; i < array.length; i++){ if (array[i] === value) return i;}
241
+ return false;}
242
+ function inArrayKey(array, value)
243
+ { for(key in array){ if(key === value) return true;}
244
+ return false;}
245
+ function addEvent(elm, evType, fn, useCapture) { if (elm.addEventListener) { elm.addEventListener(evType, fn, useCapture); return true;}
246
+ else if (elm.attachEvent) { var r = elm.attachEvent('on' + evType, fn); return r;}
247
+ else { elm['on' + evType] = fn;}
248
+ }
249
+ function removeEvent(obj, evType, fn, useCapture){ if (obj.removeEventListener){ obj.removeEventListener(evType, fn, useCapture); return true;} else if (obj.detachEvent){ var r = obj.detachEvent("on"+evType, fn); return r;} else { alert("Handler could not be removed");}
250
+ }
251
+ function format_colour(colour)
252
+ { var returnColour = "#ffffff"; if(colour != "" && colour != "transparent")
253
+ { if(colour.substr(0, 3) == "rgb")
254
+ { returnColour = rgb2Hex(colour);}
255
+ else if(colour.length == 4)
256
+ { returnColour = "#" + colour.substring(1, 2) + colour.substring(1, 2) + colour.substring(2, 3) + colour.substring(2, 3) + colour.substring(3, 4) + colour.substring(3, 4);}
257
+ else
258
+ { returnColour = colour;}
259
+ }
260
+ return returnColour;}
261
+ function get_style(obj, property, propertyNS)
262
+ { try
263
+ { if(obj.currentStyle)
264
+ { var returnVal = eval("obj.currentStyle." + property);}
265
+ else
266
+ { if(isSafari && obj.style.display == "none")
267
+ { obj.style.display = ""; var wasHidden = true;}
268
+ var returnVal = document.defaultView.getComputedStyle(obj, '').getPropertyValue(propertyNS); if(isSafari && wasHidden)
269
+ { obj.style.display = "none";}
270
+ }
271
+ }
272
+ catch(e)
273
+ { }
274
+ return returnVal;}
275
+ function getElementsByClass(searchClass, node, tag)
276
+ { var classElements = new Array(); if(node == null)
277
+ node = document; if(tag == null)
278
+ tag = '*'; var els = node.getElementsByTagName(tag); var elsLen = els.length; var pattern = new RegExp("(^|\s)"+searchClass+"(\s|$)"); for (i = 0, j = 0; i < elsLen; i++)
279
+ { if(pattern.test(els[i].className))
280
+ { classElements[j] = els[i]; j++;}
281
+ }
282
+ return classElements;}
283
+ function newCurvyError(errorMessage)
284
+ { return new Error("curvyCorners Error:\n" + errorMessage)
285
+ }
@@ -0,0 +1,96 @@
1
+ body {
2
+ background-color: #115;
3
+ font-family: "Georgia", sans-serif;
4
+ font-size: 16px;
5
+ line-height: 1.6em;
6
+ padding: 1.6em 0 0 0;
7
+ color: #eee;
8
+ }
9
+ h1, h2, h3, h4, h5, h6 {
10
+ color: #77f;
11
+ }
12
+ h1 {
13
+ font-family: sans-serif;
14
+ font-weight: normal;
15
+ font-size: 4em;
16
+ line-height: 0.8em;
17
+ letter-spacing: -0.1ex;
18
+ }
19
+ li {
20
+ padding: 0;
21
+ margin: 0;
22
+ list-style-type: square;
23
+ }
24
+ a {
25
+ color: #99f;
26
+ font-weight: normal;
27
+ text-decoration: underline;
28
+ }
29
+ blockquote {
30
+ font-size: 90%;
31
+ font-style: italic;
32
+ border-left: 1px solid #eee;
33
+ padding-left: 1em;
34
+ }
35
+ .caps {
36
+ font-size: 80%;
37
+ }
38
+
39
+ #main {
40
+ width: 40em;
41
+ padding: 0;
42
+ margin: 0 auto;
43
+ }
44
+ .coda {
45
+ text-align: right;
46
+ color: #77f;
47
+ font-size: smaller;
48
+ }
49
+
50
+ pre, code {
51
+ font-family: monospace;
52
+ font-size: 90%;
53
+ line-height: 1.4em;
54
+ color: #ff8;
55
+ background-color: #111;
56
+ padding: 2px 10px 2px 10px;
57
+ }
58
+ .comment { color: #aaa; font-style: italic; }
59
+ .keyword { color: #eff; font-weight: bold; }
60
+ .punct { color: #eee; font-weight: bold; }
61
+ .symbol { color: #0bb; }
62
+ .string { color: #6b4; }
63
+ .ident { color: #ff8; }
64
+ .constant { color: #66f; }
65
+ .regex { color: #ec6; }
66
+ .number { color: #F99; }
67
+ .expr { color: #227; }
68
+
69
+ #version {
70
+ float: right;
71
+ text-align: right;
72
+ font-family: sans-serif;
73
+ font-weight: normal;
74
+ background-color: #ff8;
75
+ color: #66f;
76
+ padding: 15px 20px 10px 20px;
77
+ margin: 0 auto;
78
+ border: 3px solid #66f;
79
+ }
80
+
81
+ #version .numbers {
82
+ display: block;
83
+ font-size: 4em;
84
+ line-height: 0.8em;
85
+ letter-spacing: -0.1ex;
86
+ }
87
+
88
+ #version a {
89
+ text-decoration: none;
90
+ }
91
+
92
+ .clickable {
93
+ cursor: pointer;
94
+ cursor: hand;
95
+ }
96
+
@@ -0,0 +1,45 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
6
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7
+ <title>
8
+ <%= title %>
9
+ </title>
10
+ <script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
11
+ <style>
12
+
13
+ </style>
14
+ <script type="text/javascript">
15
+ window.onload = function() {
16
+ settings = {
17
+ tl: { radius: 10 },
18
+ tr: { radius: 10 },
19
+ bl: { radius: 10 },
20
+ br: { radius: 10 },
21
+ antiAlias: true,
22
+ autoPad: true,
23
+ validTags: ["div"]
24
+ }
25
+ var versionBox = new curvyCorners(settings, document.getElementById("version"));
26
+ versionBox.applyCornersToAll();
27
+ }
28
+ </script>
29
+ </head>
30
+ <body>
31
+ <div id="main">
32
+
33
+ <h1><%= title %></h1>
34
+ <div id="version" class="clickable" onclick='document.location = "<%= download %>"; return false'>
35
+ Get Version
36
+ <a href="<%= download %>" class="numbers"><%= version %></a>
37
+ </div>
38
+ <%= body %>
39
+ <p class="coda">
40
+ <a href="mailto:drnicwilliams@gmail.com">Dr Nic</a>, <%= modified.pretty %><br>
41
+ Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
42
+ </p>
43
+ </div>
44
+ </body>
45
+ </html>
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: dr_nic_magic_models
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.2.5
7
+ date: 2006-07-28 00:00:00 +02:00
8
+ summary: Invisible validations, assocations and Active Record models themselves!
9
+ require_paths:
10
+ - lib
11
+ email: drnicwilliams@gmail.com
12
+ homepage: http://magicmodels.rubyforge.org
13
+ rubyforge_project: magicmodels
14
+ description: Associations and validations are automagically available to your ActiveRecord models. Model classes themselves are automagically generated if you haven't defined them already!
15
+ autorequire: dr_nic
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ authors:
29
+ - Dr Nic Williams
30
+ files:
31
+ - Rakefile
32
+ - install.rb
33
+ - README
34
+ - CHANGELOG
35
+ - lib/dr_nic
36
+ - lib/dr_nic.rb
37
+ - lib/module.rb
38
+ - lib/base.rb
39
+ - lib/dr_nic/magic_models
40
+ - lib/dr_nic/magic_models/validations.rb
41
+ - lib/dr_nic/magic_models/schema.rb
42
+ - lib/dr_nic/magic_models/version.rb
43
+ - test/connections
44
+ - test/fixtures
45
+ - test/abstract_unit.rb
46
+ - test/dummy_test.rb
47
+ - test/invisible_model_classes_test.rb
48
+ - test/env_test.rb
49
+ - test/connections/native_mysql
50
+ - test/connections/native_mysql/connection.rb
51
+ - test/fixtures/db_definitions
52
+ - test/fixtures/reference_type.rb
53
+ - test/fixtures/reference_types.yml
54
+ - test/fixtures/reference_code.rb
55
+ - test/fixtures/reference_codes.yml
56
+ - test/fixtures/db_definitions/mysql.sql
57
+ - test/fixtures/db_definitions/mysql.drop.sql
58
+ - website/index.txt
59
+ - website/index.html
60
+ - website/javascripts
61
+ - website/stylesheets
62
+ - website/template.rhtml
63
+ - website/javascripts/rounded_corners_lite.inc.js
64
+ - website/stylesheets/screen.css
65
+ test_files: []
66
+
67
+ rdoc_options:
68
+ - --main
69
+ - README
70
+ extra_rdoc_files:
71
+ - README
72
+ executables: []
73
+
74
+ extensions: []
75
+
76
+ requirements: []
77
+
78
+ dependencies:
79
+ - !ruby/object:Gem::Dependency
80
+ name: activerecord
81
+ version_requirement:
82
+ version_requirements: !ruby/object:Gem::Version::Requirement
83
+ requirements:
84
+ - - "="
85
+ - !ruby/object:Gem::Version
86
+ version: 1.14.3
87
+ version: