dr_nic_magic_models 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
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: