dr_nic_magic_models 0.8.1 → 0.9.0
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/History.txt +10 -0
- data/Manifest.txt +55 -0
- data/README +268 -0
- data/Rakefile +82 -107
- data/lib/base.rb +1 -5
- data/lib/dr_nic_magic_models.rb +4 -1
- data/lib/dr_nic_magic_models/inflector.rb +14 -0
- data/lib/dr_nic_magic_models/magic_model.rb +125 -0
- data/lib/dr_nic_magic_models/schema.rb +224 -196
- data/lib/dr_nic_magic_models/validations.rb +6 -6
- data/lib/dr_nic_magic_models/version.rb +2 -2
- data/lib/module.rb +33 -0
- data/scripts/txt2html +3 -2
- data/scripts/txt2js +3 -2
- data/test.db +0 -0
- data/test/abstract_unit.rb +4 -0
- data/test/connections/native_postgresql/connection.rb +0 -2
- data/test/connections/native_sqlite/connection.rb +10 -0
- data/test/fixtures/.DS_Store +0 -0
- data/test/fixtures/db_definitions/mysql.sql +0 -2
- data/test/fixtures/db_definitions/postgresql.sql +0 -1
- data/test/fixtures/db_definitions/sqlite.sql +49 -0
- data/test/invisible_model_access_test.rb +8 -2
- data/test/invisible_model_assoc_test.rb +17 -13
- data/test/magic_module_test.rb +20 -0
- data/website/index.html +283 -297
- data/website/index.txt +4 -16
- data/website/version-raw.js +1 -1
- data/website/version.js +1 -1
- metadata +53 -56
- data/scripts/http-access2-2.0.6.gem +0 -0
- data/scripts/rubyforge-orig +0 -217
- data/test/fixtures/db_definitions/postgresql.drop.sql +0 -4
@@ -12,14 +12,14 @@ module DrNicMagicModels
|
|
12
12
|
self.columns.reject { |column| column.name =~ /(?i)^(((created|updated)_(at|on))|position|type|id)$/ }.each do |column|
|
13
13
|
|
14
14
|
if column.type == :integer
|
15
|
-
logger.debug "validates_numericality_of #{column.name}, :allow_nil =>
|
16
|
-
self.validates_numericality_of column.name, :allow_nil =>
|
15
|
+
logger.debug "validates_numericality_of #{column.name}, :allow_nil => #{column.null.inspect}, :only_integer => true"
|
16
|
+
self.validates_numericality_of column.name, :allow_nil => column.null, :only_integer => true
|
17
17
|
elsif column.number?
|
18
|
-
logger.debug "validates_numericality_of #{column.name}, :allow_nil =>
|
19
|
-
self.validates_numericality_of column.name, :allow_nil =>
|
18
|
+
logger.debug "validates_numericality_of #{column.name}, :allow_nil => #{column.null.inspect}"
|
19
|
+
self.validates_numericality_of column.name, :allow_nil => column.null
|
20
20
|
elsif column.text? && column.limit
|
21
|
-
logger.debug "validates_length_of #{column.name}, :allow_nil =>
|
22
|
-
self.validates_length_of column.name, :allow_nil =>
|
21
|
+
logger.debug "validates_length_of #{column.name}, :allow_nil => #{column.null.inspect}, :maximum => #{column.limit}"
|
22
|
+
self.validates_length_of column.name, :allow_nil => column.null, :maximum => column.limit
|
23
23
|
end
|
24
24
|
|
25
25
|
# Active record seems to interpolate booleans anyway to either true, false or nil...
|
data/lib/module.rb
ADDED
@@ -0,0 +1,33 @@
|
|
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
|
+
@magic_schema ||= DrNicMagicModels::Schema.new self
|
10
|
+
unless table_name = @magic_schema.models[class_id]
|
11
|
+
raise NameError.new("uninitialized constant #{class_id}") if @magic_schema.models.enquired? class_id
|
12
|
+
end
|
13
|
+
superklass = @magic_schema.superklass || ActiveRecord::Base
|
14
|
+
klass = create_class(class_id, superklass) do
|
15
|
+
set_table_name table_name
|
16
|
+
include DrNicMagicModels::MagicModel
|
17
|
+
extend DrNicMagicModels::Validations
|
18
|
+
end
|
19
|
+
klass.generate_validations # need to call this AFTER the class name has been assigned
|
20
|
+
@magic_schema.inflector.post_class_creation klass
|
21
|
+
klass
|
22
|
+
end
|
23
|
+
|
24
|
+
def magic_module(table_name_prefix)
|
25
|
+
self.instance_variable_set "@table_name_prefix", table_name_prefix
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
def create_class(class_name, superclass, &block)
|
30
|
+
klass = Class.new superclass, &block
|
31
|
+
Object.const_set class_name, klass
|
32
|
+
end
|
33
|
+
end
|
data/scripts/txt2html
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
require 'rubygems'
|
3
4
|
require 'redcloth'
|
4
5
|
require 'syntax/convertors/html'
|
5
6
|
require 'erb'
|
6
|
-
require '
|
7
|
+
require File.dirname(__FILE__) + '/../lib/dr_nic_magic_models/version.rb'
|
7
8
|
|
8
9
|
version = DrNicMagicModels::VERSION::STRING
|
9
10
|
download = 'http://rubyforge.org/projects/magicmodels'
|
@@ -34,7 +35,7 @@ end
|
|
34
35
|
|
35
36
|
if ARGV.length >= 1
|
36
37
|
src, template = ARGV
|
37
|
-
template ||= 'template.rhtml'
|
38
|
+
template ||= File.dirname(__FILE__) + '/../website/template.rhtml'
|
38
39
|
else
|
39
40
|
puts("Usage: #{File.split($0).last} source.txt [template.rhtml] > output.html")
|
40
41
|
exit!
|
data/scripts/txt2js
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
require 'rubygems'
|
3
4
|
require 'redcloth'
|
4
5
|
require 'syntax/convertors/html'
|
5
6
|
require 'erb'
|
6
7
|
require 'active_support'
|
7
|
-
require '
|
8
|
+
require File.dirname(__FILE__) + '/../lib/dr_nic_magic_models/version.rb'
|
8
9
|
|
9
10
|
version = DrNicMagicModels::VERSION::STRING
|
10
11
|
download = 'http://rubyforge.org/projects/magicmodels'
|
@@ -35,7 +36,7 @@ end
|
|
35
36
|
|
36
37
|
if ARGV.length >= 1
|
37
38
|
src, template = ARGV
|
38
|
-
template ||= 'template.js'
|
39
|
+
template ||= File.dirname(__FILE__) + '/../website/template.js'
|
39
40
|
else
|
40
41
|
puts("Usage: #{File.split($0).last} source.txt [template.rhtml] > output.html")
|
41
42
|
exit!
|
data/test.db
ADDED
Binary file
|
data/test/abstract_unit.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
2
2
|
|
3
|
+
require 'rubygems'
|
3
4
|
require 'test/unit'
|
4
5
|
require 'active_record'
|
5
6
|
require 'active_record/fixtures'
|
@@ -8,6 +9,9 @@ require 'active_support/breakpoint'
|
|
8
9
|
require 'connection'
|
9
10
|
require 'dr_nic_magic_models'
|
10
11
|
|
12
|
+
ActiveSupport::Deprecation.debug = true
|
13
|
+
|
14
|
+
|
11
15
|
QUOTED_TYPE = ActiveRecord::Base.connection.quote_column_name('type') unless Object.const_defined?(:QUOTED_TYPE)
|
12
16
|
|
13
17
|
class Test::Unit::TestCase #:nodoc:
|
Binary file
|
@@ -0,0 +1,49 @@
|
|
1
|
+
CREATE TABLE `fun_users` (
|
2
|
+
`id` int(11) NOT NULL,
|
3
|
+
`type` varchar(255) NOT NULL,
|
4
|
+
`firstname` varchar(50) NOT NULL,
|
5
|
+
`lastname` varchar(50) NOT NULL,
|
6
|
+
`login` varchar(50) NOT NULL,
|
7
|
+
`email` varchar(50) NULL,
|
8
|
+
PRIMARY KEY (`id`)
|
9
|
+
);
|
10
|
+
|
11
|
+
CREATE TABLE `groups` (
|
12
|
+
`id` int(11) NOT NULL ,
|
13
|
+
`name` varchar(50) NOT NULL UNIQUE,
|
14
|
+
`description` varchar(50) default NULL,
|
15
|
+
`some_int` integer default NULL,
|
16
|
+
`some_float` float default NULL,
|
17
|
+
`some_bool` boolean default NULL,
|
18
|
+
PRIMARY KEY (`id`)
|
19
|
+
);
|
20
|
+
|
21
|
+
CREATE TABLE `group_memberships` (
|
22
|
+
`id` int(11) NOT NULL,
|
23
|
+
`fun_user_id` int(11) NOT NULL,
|
24
|
+
`group_id` int(11) NOT NULL,
|
25
|
+
PRIMARY KEY (`id`)
|
26
|
+
);
|
27
|
+
|
28
|
+
CREATE TABLE `adjectives` (
|
29
|
+
`id` int(11) NOT NULL,
|
30
|
+
`name` varchar(255),
|
31
|
+
PRIMARY KEY (`id`)
|
32
|
+
);
|
33
|
+
|
34
|
+
CREATE TABLE `adjectives_fun_users` (
|
35
|
+
`fun_user_id` int(11) NOT NULL,
|
36
|
+
`adjective_id` int(11) NOT NULL,
|
37
|
+
PRIMARY KEY (`fun_user_id`,`adjective_id`)
|
38
|
+
);
|
39
|
+
|
40
|
+
|
41
|
+
CREATE TABLE `group_tag` (
|
42
|
+
`id` int(11) NOT NULL,
|
43
|
+
`name` varchar(50) NOT NULL,
|
44
|
+
`group_id` int(11) NOT NULL,
|
45
|
+
`referenced_group_id` int(11) NULL UNIQUE,
|
46
|
+
PRIMARY KEY (`id`)
|
47
|
+
);
|
48
|
+
|
49
|
+
|
@@ -2,11 +2,16 @@ require 'abstract_unit'
|
|
2
2
|
require 'pp'
|
3
3
|
|
4
4
|
class InvisibleModelAccessTest < Test::Unit::TestCase
|
5
|
-
fixtures :fun_users, :groups, :group_memberships, :group_tag
|
5
|
+
# fixtures :fun_users, :groups, :group_memberships, :group_tag
|
6
6
|
|
7
7
|
def setup
|
8
|
+
create_fixtures :fun_users, :groups, :group_memberships, :group_tag
|
8
9
|
@classes = [FunUser, Group, GroupMembership, GroupTag]
|
9
|
-
@group =
|
10
|
+
@group = Group.find(:first)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_attributes
|
14
|
+
assert_not_nil @group.name
|
10
15
|
end
|
11
16
|
|
12
17
|
def test_find
|
@@ -17,6 +22,7 @@ class InvisibleModelAccessTest < Test::Unit::TestCase
|
|
17
22
|
end
|
18
23
|
|
19
24
|
def test_sti
|
25
|
+
require 'fun_user_plus'
|
20
26
|
x = FunUserPlus.find(:all)
|
21
27
|
assert x.inject {|n,v| n &= v.class == FunUserPlus}, "Wrong object class in FunUserPlus.find(:all)"
|
22
28
|
plus = x.first
|
@@ -1,17 +1,18 @@
|
|
1
1
|
require 'abstract_unit'
|
2
2
|
|
3
3
|
class InvisibleModelAssocTest < Test::Unit::TestCase
|
4
|
-
fixtures :fun_users, :groups, :group_memberships, :group_tag, :adjectives, :adjectives_fun_users
|
4
|
+
# fixtures :fun_users, :groups, :group_memberships, :group_tag, :adjectives, :adjectives_fun_users
|
5
5
|
|
6
6
|
def setup
|
7
|
-
|
8
|
-
@
|
9
|
-
@
|
10
|
-
@
|
7
|
+
create_fixtures :fun_users, :groups, :group_memberships, :group_tag, :adjectives, :adjectives_fun_users
|
8
|
+
@group = Group.find(1)
|
9
|
+
@group_tag = GroupTag.find(1)
|
10
|
+
@user = FunUser.find(1)
|
11
|
+
@membership = GroupMembership.find(1)
|
11
12
|
end
|
12
13
|
|
13
|
-
def test_hatbm
|
14
|
-
|
14
|
+
def test_hatbm
|
15
|
+
assert_equal([Adjective.find(1)], @user.adjectives)
|
15
16
|
end
|
16
17
|
|
17
18
|
def test_fk
|
@@ -24,10 +25,11 @@ class InvisibleModelAssocTest < Test::Unit::TestCase
|
|
24
25
|
assert g.id == 1
|
25
26
|
|
26
27
|
# Using FKs
|
27
|
-
g
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
if g.connection.supports_fetch_foreign_keys?
|
29
|
+
g = gt.referenced_group
|
30
|
+
assert g.class == Group
|
31
|
+
assert g.id == 1
|
32
|
+
end
|
31
33
|
end
|
32
34
|
|
33
35
|
def test_has_many
|
@@ -36,8 +38,10 @@ class InvisibleModelAssocTest < Test::Unit::TestCase
|
|
36
38
|
end
|
37
39
|
|
38
40
|
def test_has_one
|
39
|
-
|
40
|
-
|
41
|
+
if @group_tag.connection.supports_fetch_foreign_keys?
|
42
|
+
assert_equal @group, @group_tag.referenced_group
|
43
|
+
# assert_equal @group_tag, @group.group_tag_as_referenced_group
|
44
|
+
end
|
41
45
|
end
|
42
46
|
|
43
47
|
def test_belongs_to
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'abstract_unit'
|
2
|
+
|
3
|
+
module MagicGroup
|
4
|
+
magic_module 'group_'
|
5
|
+
end
|
6
|
+
|
7
|
+
class MagicModuleTest < Test::Unit::TestCase
|
8
|
+
|
9
|
+
def setup
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_table_prefix
|
14
|
+
assert_nothing_thrown { MagicGroup::Membership }
|
15
|
+
assert_equal('group_memberships', MagicGroup::Membership.table_name)
|
16
|
+
assert_nothing_thrown { MagicGroup::Tag }
|
17
|
+
assert_equal('group_tag', MagicGroup::Tag.table_name)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
data/website/index.html
CHANGED
@@ -1,60 +1,46 @@
|
|
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’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" src="version-raw.js"></script>
|
15
|
-
<script type="text/javascript">
|
16
|
-
window.onload = function() {
|
17
|
-
settings = {
|
18
|
-
tl: { radius: 10 },
|
19
|
-
tr: { radius: 10 },
|
20
|
-
bl: { radius: 10 },
|
21
|
-
br: { radius: 10 },
|
22
|
-
antiAlias: true,
|
23
|
-
autoPad: true,
|
24
|
-
validTags: ["div"]
|
25
|
-
}
|
26
|
-
var versionBox = new curvyCorners(settings, document.getElementById("version"));
|
27
|
-
versionBox.applyCornersToAll();
|
28
|
-
|
29
|
-
document.getElementById("version_num").innerHTML = version;
|
30
|
-
}
|
31
|
-
</script>
|
32
|
-
</head>
|
33
|
-
<body>
|
34
|
-
<div id="main">
|
35
|
-
|
36
|
-
<h1>Dr Nic’s Magic Models</h1>
|
37
|
-
<div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/magicmodels"; return false'>
|
38
|
-
Get Version
|
39
|
-
<a id="version_num" href="http://rubyforge.org/projects/magicmodels" class="numbers"></a>
|
40
|
-
</div>
|
41
|
-
<
|
42
|
-
|
43
|
-
|
44
|
-
<p>Assocations now generated using <a href="foreignkeys.html">Foreign Keys</a> too!</p>
|
45
|
-
|
46
|
-
|
47
|
-
<p>Now… on with the magic show!
|
48
|
-
<br />
|
49
|
-
<br /></p>
|
50
|
-
|
51
|
-
|
52
|
-
<blockquote>
|
53
|
-
<strong>conjure</strong> 1. To create events that appear to be magical<br />
|
54
|
-
- <a href="http://www.dcopperfield.com/">David Copperfield</a> website
|
55
|
-
</blockquote>
|
56
|
-
If you’ve used Ruby on Rails you’ll have written at least one model class like this:
|
57
|
-
|
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’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" src="version-raw.js"></script>
|
15
|
+
<script type="text/javascript">
|
16
|
+
window.onload = function() {
|
17
|
+
settings = {
|
18
|
+
tl: { radius: 10 },
|
19
|
+
tr: { radius: 10 },
|
20
|
+
bl: { radius: 10 },
|
21
|
+
br: { radius: 10 },
|
22
|
+
antiAlias: true,
|
23
|
+
autoPad: true,
|
24
|
+
validTags: ["div"]
|
25
|
+
}
|
26
|
+
var versionBox = new curvyCorners(settings, document.getElementById("version"));
|
27
|
+
versionBox.applyCornersToAll();
|
28
|
+
|
29
|
+
document.getElementById("version_num").innerHTML = version;
|
30
|
+
}
|
31
|
+
</script>
|
32
|
+
</head>
|
33
|
+
<body>
|
34
|
+
<div id="main">
|
35
|
+
|
36
|
+
<h1>Dr Nic’s Magic Models</h1>
|
37
|
+
<div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/magicmodels"; return false'>
|
38
|
+
Get Version
|
39
|
+
<a id="version_num" href="http://rubyforge.org/projects/magicmodels" class="numbers"></a>
|
40
|
+
</div>
|
41
|
+
<p>If you’ve used Ruby on Rails you’ll have written at least one model class like this:</p>
|
42
|
+
|
43
|
+
|
58
44
|
<p><pre class="syntax">
|
59
45
|
<span class="keyword">class </span><span class="class">Person</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span>
|
60
46
|
<span class="ident">has_many</span> <span class="symbol">:memberships</span>
|
@@ -62,91 +48,91 @@ If you’ve used Ruby on Rails you’ll have written at least one model
|
|
62
48
|
<span class="ident">belongs_to</span> <span class="symbol">:family</span>
|
63
49
|
<span class="ident">validates_presence_of</span> <span class="symbol">:firstname</span><span class="punct">,</span> <span class="symbol">:lastname</span><span class="punct">,</span> <span class="symbol">:email</span>
|
64
50
|
<span class="keyword">end</span>
|
65
|
-
</pre></p>
|
66
|
-
|
67
|
-
|
68
|
-
<p>A few minutes later you’ll have wondered to yourself,</p>
|
69
|
-
|
70
|
-
|
71
|
-
<blockquote>
|
72
|
-
Why do I have write my own <code>has_many</code>, <code>belongs_to</code>, and <code>validates_presence_of</code>
|
73
|
-
commands if all the data is in the database schema?
|
74
|
-
</blockquote>
|
75
|
-
|
76
|
-
<p>Now, for the very first time, your classes can look like this:</p>
|
77
|
-
|
78
|
-
|
51
|
+
</pre></p>
|
52
|
+
|
53
|
+
|
54
|
+
<p>A few minutes later you’ll have wondered to yourself,</p>
|
55
|
+
|
56
|
+
|
57
|
+
<blockquote>
|
58
|
+
Why do I have write my own <code>has_many</code>, <code>belongs_to</code>, and <code>validates_presence_of</code>
|
59
|
+
commands if all the data is in the database schema?
|
60
|
+
</blockquote>
|
61
|
+
|
62
|
+
<p>Now, for the very first time, your classes can look like this:</p>
|
63
|
+
|
64
|
+
|
79
65
|
<p><pre class="syntax">
|
80
66
|
<span class="keyword">class </span><span class="class">Person</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span>
|
81
67
|
<span class="keyword">end</span>
|
82
|
-
</pre></p>
|
83
|
-
|
84
|
-
|
85
|
-
<p>or, if you are lazy…</p>
|
86
|
-
|
87
|
-
|
68
|
+
</pre></p>
|
69
|
+
|
70
|
+
|
71
|
+
<p>or, if you are lazy…</p>
|
72
|
+
|
73
|
+
|
88
74
|
<p><pre class="syntax">
|
89
75
|
<span class="keyword">class </span><span class="class">Person</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span><span class="punct">;</span> <span class="keyword">end</span>
|
90
|
-
</pre></p>
|
91
|
-
|
92
|
-
|
93
|
-
<p>or, if you read right to the end of this page, this…</p>
|
94
|
-
|
95
|
-
|
76
|
+
</pre></p>
|
77
|
+
|
78
|
+
|
79
|
+
<p>or, if you read right to the end of this page, this…</p>
|
80
|
+
|
81
|
+
|
96
82
|
<p><pre class="syntax">
|
97
|
-
|
98
|
-
</pre></p>
|
99
|
-
|
100
|
-
|
101
|
-
<p>Magic and mystery abound. All for you. Impress your friends, amaze your mother.</p>
|
102
|
-
|
103
|
-
|
104
|
-
<p><span class="caps">NOTE</span>: The gratuitous use of <strong>Dr Nic’s</strong> in the name should only enhance the mystical
|
105
|
-
for magic needs a magician; and I love magic. I always wanted to create my own magic trick.
|
106
|
-
So I shall be the magician for the sake of magic itself. I look a bit like Harry Potter
|
107
|
-
if Harry were
|
108
|
-
|
109
|
-
|
110
|
-
<h2>Installation</h2>
|
111
|
-
|
112
|
-
|
113
|
-
To install the Dr Nic’s Magic Models gem you can run the following command to
|
114
|
-
fetch the gem remotely from RubyForge:
|
115
|
-
<pre>
|
116
|
-
gem install dr_nic_magic_models
|
117
|
-
</pre>
|
118
|
-
|
119
|
-
<p>or <a href="http://rubyforge.org/projects/magicmodels">download the gem manually</a> and
|
120
|
-
run the above command in the download directory.</p>
|
121
|
-
|
122
|
-
|
123
|
-
<p>Now you need to <code>require</code> the gem into your Ruby/Rails app. Insert the following
|
124
|
-
line into your script (use <code>config/environment.rb</code> for your Rails apps):</p>
|
125
|
-
|
126
|
-
|
127
|
-
<pre>
|
128
|
-
require 'dr_nic_magic_models'
|
129
|
-
</pre>
|
130
|
-
|
131
|
-
<p>Your application is now blessed with magical mystery.</p>
|
132
|
-
|
133
|
-
|
134
|
-
<h2>David Copperfield eat your Ruby-crusted heart out</h2>
|
135
|
-
|
136
|
-
|
137
|
-
<p>Let’s demonstrate the magical mystery in all its full-stage glory. Create a Ruby on Rails app:</p>
|
138
|
-
|
139
|
-
|
83
|
+
<span class="comment"># Go fish.</span>
|
84
|
+
</pre></p>
|
85
|
+
|
86
|
+
|
87
|
+
<p>Magic and mystery abound. All for you. Impress your friends, amaze your mother.</p>
|
88
|
+
|
89
|
+
|
90
|
+
<p><span class="caps">NOTE</span>: The gratuitous use of <strong>Dr Nic’s</strong> in the name should only enhance the mystical magikery,
|
91
|
+
for magic needs a magician; and I love magic. I always wanted to create my own magic trick.
|
92
|
+
So I shall be the magician for the sake of magic itself. I look a bit like Harry Potter too,
|
93
|
+
if Harry were 32 and better dressed.</p>
|
94
|
+
|
95
|
+
|
96
|
+
<h2>Installation</h2>
|
97
|
+
|
98
|
+
|
99
|
+
To install the Dr Nic’s Magic Models gem you can run the following command to
|
100
|
+
fetch the gem remotely from RubyForge:
|
101
|
+
<pre>
|
102
|
+
gem install dr_nic_magic_models
|
103
|
+
</pre>
|
104
|
+
|
105
|
+
<p>or <a href="http://rubyforge.org/projects/magicmodels">download the gem manually</a> and
|
106
|
+
run the above command in the download directory.</p>
|
107
|
+
|
108
|
+
|
109
|
+
<p>Now you need to <code>require</code> the gem into your Ruby/Rails app. Insert the following
|
110
|
+
line into your script (use <code>config/environment.rb</code> for your Rails apps):</p>
|
111
|
+
|
112
|
+
|
113
|
+
<pre>
|
114
|
+
require 'dr_nic_magic_models'
|
115
|
+
</pre>
|
116
|
+
|
117
|
+
<p>Your application is now blessed with magical mystery.</p>
|
118
|
+
|
119
|
+
|
120
|
+
<h2>David Copperfield eat your Ruby-crusted heart out</h2>
|
121
|
+
|
122
|
+
|
123
|
+
<p>Let’s demonstrate the magical mystery in all its full-stage glory. Create a Ruby on Rails app:</p>
|
124
|
+
|
125
|
+
|
140
126
|
<p><pre class="syntax">
|
141
127
|
<span class="ident">rails</span> <span class="ident">magic_show</span>
|
142
128
|
<span class="ident">cd</span> <span class="ident">magic_show</span>
|
143
129
|
<span class="ident">ruby</span> <span class="ident">script</span><span class="punct">/</span><span class="ident">generate</span> <span class="ident">model</span> <span class="constant">Person</span>
|
144
130
|
<span class="ident">ruby</span> <span class="ident">script</span><span class="punct">/</span><span class="ident">generate</span> <span class="ident">model</span> <span class="constant">Group</span>
|
145
131
|
<span class="ident">ruby</span> <span class="ident">script</span><span class="punct">/</span><span class="ident">generate</span> <span class="ident">model</span> <span class="constant">Membership</span>
|
146
|
-
</pre></p>
|
147
|
-
|
148
|
-
|
149
|
-
<p>Update the migration <code>001_create_people.rb</code> with:
|
132
|
+
</pre></p>
|
133
|
+
|
134
|
+
|
135
|
+
<p>Update the migration <code>001_create_people.rb</code> with:
|
150
136
|
<pre class="syntax">
|
151
137
|
<span class="keyword">class </span><span class="class">CreatePeople</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Migration</span>
|
152
138
|
<span class="keyword">def </span><span class="method">self.up</span>
|
@@ -161,52 +147,52 @@ require 'dr_nic_magic_models'
|
|
161
147
|
<span class="ident">drop_table</span> <span class="symbol">:people</span>
|
162
148
|
<span class="keyword">end</span>
|
163
149
|
<span class="keyword">end</span>
|
164
|
-
</pre></p>
|
165
|
-
|
166
|
-
|
167
|
-
<p>Similarly, update the <code>def self.up</code> method of <code>002_create_groups.rb</code>
|
168
|
-
with:
|
150
|
+
</pre></p>
|
151
|
+
|
152
|
+
|
153
|
+
<p>Similarly, update the <code>def self.up</code> method of <code>002_create_groups.rb</code>
|
154
|
+
with:
|
169
155
|
<pre class="syntax">
|
170
156
|
<span class="ident">create_table</span> <span class="symbol">:groups</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">t</span><span class="punct">|</span>
|
171
157
|
<span class="ident">t</span><span class="punct">.</span><span class="ident">column</span> <span class="symbol">:name</span><span class="punct">,</span> <span class="symbol">:string</span><span class="punct">,</span> <span class="symbol">:null</span> <span class="punct">=></span> <span class="constant">false</span>
|
172
158
|
<span class="ident">t</span><span class="punct">.</span><span class="ident">column</span> <span class="symbol">:description</span><span class="punct">,</span> <span class="symbol">:string</span>
|
173
159
|
<span class="keyword">end</span>
|
174
|
-
</pre></p>
|
175
|
-
|
176
|
-
|
177
|
-
<p>and <code>003_create_memberships.rb</code> with:
|
160
|
+
</pre></p>
|
161
|
+
|
162
|
+
|
163
|
+
<p>and <code>003_create_memberships.rb</code> with:
|
178
164
|
<pre class="syntax">
|
179
165
|
<span class="ident">create_table</span> <span class="symbol">:memberships</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">t</span><span class="punct">|</span>
|
180
166
|
<span class="ident">t</span><span class="punct">.</span><span class="ident">column</span> <span class="symbol">:person_id</span><span class="punct">,</span> <span class="symbol">:integer</span><span class="punct">,</span> <span class="symbol">:null</span> <span class="punct">=></span> <span class="constant">false</span>
|
181
167
|
<span class="ident">t</span><span class="punct">.</span><span class="ident">column</span> <span class="symbol">:group_id</span><span class="punct">,</span> <span class="symbol">:integer</span><span class="punct">,</span> <span class="symbol">:null</span> <span class="punct">=></span> <span class="constant">false</span>
|
182
168
|
<span class="keyword">end</span>
|
183
|
-
</pre></p>
|
184
|
-
|
185
|
-
|
186
|
-
Now create your database. For MySql:
|
187
|
-
<pre>
|
188
|
-
mysqladmin -u root create magic_show_development
|
189
|
-
mysqladmin -u root create magic_show_test
|
190
|
-
</pre>
|
191
|
-
|
192
|
-
And run your migrations to create the three tables:
|
193
|
-
<pre>
|
194
|
-
rake migrate
|
195
|
-
</pre>
|
196
|
-
|
197
|
-
<h2>And now for some <a href="http://en.wikipedia.org/wiki/List_of_conjuring_terms">woofle dust</a> ...</h2>
|
198
|
-
|
199
|
-
|
200
|
-
<p>At the end of <code>config/environment.rb</code> add the following line:</p>
|
201
|
-
|
202
|
-
|
203
|
-
<pre>
|
204
|
-
require 'dr_nic_magic_models'
|
205
|
-
</pre>
|
206
|
-
|
207
|
-
<p>Now, let’s do a magic trick. First, let’s check our model classes (<code>app/models/person.rb</code> etc):</p>
|
208
|
-
|
209
|
-
|
169
|
+
</pre></p>
|
170
|
+
|
171
|
+
|
172
|
+
Now create your database. For MySql:
|
173
|
+
<pre>
|
174
|
+
mysqladmin -u root create magic_show_development
|
175
|
+
mysqladmin -u root create magic_show_test
|
176
|
+
</pre>
|
177
|
+
|
178
|
+
And run your migrations to create the three tables:
|
179
|
+
<pre>
|
180
|
+
rake migrate
|
181
|
+
</pre>
|
182
|
+
|
183
|
+
<h2>And now for some <a href="http://en.wikipedia.org/wiki/List_of_conjuring_terms">woofle dust</a> ...</h2>
|
184
|
+
|
185
|
+
|
186
|
+
<p>At the end of <code>config/environment.rb</code> add the following line:</p>
|
187
|
+
|
188
|
+
|
189
|
+
<pre>
|
190
|
+
require 'dr_nic_magic_models'
|
191
|
+
</pre>
|
192
|
+
|
193
|
+
<p>Now, let’s do a magic trick. First, let’s check our model classes (<code>app/models/person.rb</code> etc):</p>
|
194
|
+
|
195
|
+
|
210
196
|
<p><pre class="syntax">
|
211
197
|
<span class="keyword">class </span><span class="class">Person</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span>
|
212
198
|
<span class="keyword">end</span>
|
@@ -214,23 +200,23 @@ require 'dr_nic_magic_models'
|
|
214
200
|
<span class="keyword">end</span>
|
215
201
|
<span class="keyword">class </span><span class="class">Membership</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span>
|
216
202
|
<span class="keyword">end</span>
|
217
|
-
</pre></p>
|
218
|
-
|
219
|
-
|
220
|
-
<p>Nothing suspicious here. We have no validations and no associations. Just some plain old model classes.</p>
|
221
|
-
|
222
|
-
|
223
|
-
<p>For this trick, we’ll need an ordinary console session. Any old one lying around the house will do.</p>
|
224
|
-
|
225
|
-
|
226
|
-
<pre>
|
227
|
-
ruby script/console
|
228
|
-
</pre>
|
229
|
-
|
230
|
-
<p>Now a normal model class is valid until you explicitly add <code>validates_xxx</code> commands.
|
231
|
-
With Dr Nic’s Magic Models:</p>
|
232
|
-
|
233
|
-
|
203
|
+
</pre></p>
|
204
|
+
|
205
|
+
|
206
|
+
<p>Nothing suspicious here. We have no validations and no associations. Just some plain old model classes.</p>
|
207
|
+
|
208
|
+
|
209
|
+
<p>For this trick, we’ll need an ordinary console session. Any old one lying around the house will do.</p>
|
210
|
+
|
211
|
+
|
212
|
+
<pre>
|
213
|
+
ruby script/console
|
214
|
+
</pre>
|
215
|
+
|
216
|
+
<p>Now a normal model class is valid until you explicitly add <code>validates_xxx</code> commands.
|
217
|
+
With Dr Nic’s Magic Models:</p>
|
218
|
+
|
219
|
+
|
234
220
|
<p><pre class="syntax">
|
235
221
|
<span class="punct">>></span> <span class="ident">person</span> <span class="punct">=</span> <span class="constant">Person</span><span class="punct">.</span><span class="ident">new</span>
|
236
222
|
<span class="punct">=></span> <span class="comment">#<Person:0x393e0f8 @attributes={"lastname"=>"", "firstname"=>"", "email"=>""}, @new_record=true></span>
|
@@ -241,27 +227,27 @@ With Dr Nic’s Magic Models:</p>
|
|
241
227
|
<span class="punct">"</span><span class="string">lastname</span><span class="punct">"=>["</span><span class="string">can't be blank</span><span class="punct">"],</span> <span class="punct">"</span><span class="string">email</span><span class="punct">"=>["</span><span class="string">can't be blank</span><span class="punct">"]},</span>
|
242
228
|
<span class="attribute">@base</span><span class="punct">=<</span><span class="constant">Person</span><span class="punct">:</span><span class="number">0x393e0f8</span> <span class="attribute">@errors</span><span class="punct">=<</span><span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Errors</span><span class="punct">:</span><span class="number">0x3938b18</span> <span class="punct">...>,</span>
|
243
229
|
<span class="attribute">@attributes</span><span class="punct">={"</span><span class="string">lastname</span><span class="punct">"=>"</span><span class="string"></span><span class="punct">",</span> <span class="punct">"</span><span class="string">firstname</span><span class="punct">"=>"</span><span class="string"></span><span class="punct">",</span> <span class="punct">"</span><span class="string">email</span><span class="punct">"=>"</span><span class="string"></span><span class="punct">"},</span> <span class="attribute">@new_record</span><span class="punct">=</span><span class="constant">true</span><span class="punct">>></span>
|
244
|
-
</pre></p>
|
245
|
-
|
246
|
-
|
247
|
-
<p><strong>Kapoow!</strong> Instant validation!</p>
|
248
|
-
|
249
|
-
|
250
|
-
<p>Because you specified the three columns as <code>:null => false</code>,
|
251
|
-
your ActiveRecord models will now automatically generated <code>validates_presence_of</code>
|
252
|
-
for each non-null field.</p>
|
253
|
-
|
254
|
-
|
255
|
-
<p>Ok, we’re just warming up.</p>
|
256
|
-
|
257
|
-
|
258
|
-
<p>Your models normally require association commands (<code>has_many</code>, <code>belongs_to</code>, etc, as
|
259
|
-
demonstrated above) to have the brilliantly simple support that Rails/ActiveRecords are known for.</p>
|
260
|
-
|
261
|
-
|
262
|
-
<p>Let’s just watch what Dr Nic’s Magic Models can do without any effort at all…</p>
|
263
|
-
|
264
|
-
|
230
|
+
</pre></p>
|
231
|
+
|
232
|
+
|
233
|
+
<p><strong>Kapoow!</strong> Instant validation!</p>
|
234
|
+
|
235
|
+
|
236
|
+
<p>Because you specified the three columns as <code>:null => false</code>,
|
237
|
+
your ActiveRecord models will now automatically generated <code>validates_presence_of</code>
|
238
|
+
for each non-null field.</p>
|
239
|
+
|
240
|
+
|
241
|
+
<p>Ok, we’re just warming up.</p>
|
242
|
+
|
243
|
+
|
244
|
+
<p>Your models normally require association commands (<code>has_many</code>, <code>belongs_to</code>, etc, as
|
245
|
+
demonstrated above) to have the brilliantly simple support that Rails/ActiveRecords are known for.</p>
|
246
|
+
|
247
|
+
|
248
|
+
<p>Let’s just watch what Dr Nic’s Magic Models can do without any effort at all…</p>
|
249
|
+
|
250
|
+
|
265
251
|
<p><pre class="syntax">
|
266
252
|
<span class="punct">>></span> <span class="ident">person</span> <span class="punct">=</span> <span class="constant">Person</span><span class="punct">.</span><span class="ident">create</span><span class="punct">(</span><span class="symbol">:firstname</span> <span class="punct">=></span> <span class="punct">"</span><span class="string">Nic</span><span class="punct">",</span> <span class="symbol">:lastname</span> <span class="punct">=></span> <span class="punct">"</span><span class="string">Williams</span><span class="punct">",</span> <span class="symbol">:email</span> <span class="punct">=></span> <span class="punct">"</span><span class="string">drnicwilliams@gmail.com</span><span class="punct">")</span>
|
267
253
|
<span class="punct">>></span> <span class="ident">group</span> <span class="punct">=</span> <span class="constant">Group</span><span class="punct">.</span><span class="ident">create</span><span class="punct">(</span><span class="symbol">:name</span> <span class="punct">=></span> <span class="punct">"</span><span class="string">Magic Models Forum</span><span class="punct">",</span> <span class="symbol">:description</span> <span class="punct">=></span> <span class="punct">"</span><span class="string">http://groups.google.com/magicmodels</span><span class="punct">")</span>
|
@@ -273,53 +259,53 @@ demonstrated above) to have the brilliantly simple support that Rails/ActiveReco
|
|
273
259
|
<span class="punct">"</span><span class="string">id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">",</span> <span class="punct">"</span><span class="string">email</span><span class="punct">"=>"</span><span class="string">drnicwilliams@gmail.com</span><span class="punct">"}></span>
|
274
260
|
<span class="punct">>></span> <span class="ident">group</span><span class="punct">.</span><span class="ident">memberships</span>
|
275
261
|
<span class="punct">=></span> <span class="punct">[<</span><span class="constant">Membership</span><span class="punct">:</span><span class="number">0x3c8cd70</span> <span class="attribute">@attributes</span><span class="punct">={"</span><span class="string">group_id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">",</span> <span class="punct">"</span><span class="string">id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">",</span> <span class="punct">"</span><span class="string">person_id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">"}>]</span>
|
276
|
-
</pre></p>
|
277
|
-
|
278
|
-
|
279
|
-
<p>The final association trick is a ripper. Automatic generation of <code>has_many :through</code> associations…</p>
|
280
|
-
|
281
|
-
|
262
|
+
</pre></p>
|
263
|
+
|
264
|
+
|
265
|
+
<p>The final association trick is a ripper. Automatic generation of <code>has_many :through</code> associations…</p>
|
266
|
+
|
267
|
+
|
282
268
|
<p><pre class="syntax">
|
283
269
|
<span class="punct">>></span> <span class="ident">person</span><span class="punct">.</span><span class="ident">groups</span>
|
284
270
|
<span class="punct">=></span> <span class="punct">[<</span><span class="constant">Group</span><span class="punct">:</span><span class="number">0x39047e0</span> <span class="attribute">@attributes</span><span class="punct">={"</span><span class="string">name</span><span class="punct">"=>"</span><span class="string">Magic Models Forum</span><span class="punct">",</span> <span class="punct">"</span><span class="string">id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">",</span> <span class="punct">"</span><span class="string">description</span><span class="punct">"=></span><span class="constant">nil</span><span class="punct">}>]</span>
|
285
271
|
<span class="punct">>></span> <span class="ident">group</span><span class="punct">.</span><span class="ident">people</span>
|
286
272
|
<span class="punct">=></span> <span class="punct">[<</span><span class="constant">Person</span><span class="punct">:</span><span class="number">0x3c33580</span> <span class="attribute">@attributes</span><span class="punct">={"</span><span class="string">lastname</span><span class="punct">"=>"</span><span class="string">Williams</span><span class="punct">",</span> <span class="punct">"</span><span class="string">firstname</span><span class="punct">"=>"</span><span class="string">Nic</span><span class="punct">",</span>
|
287
273
|
<span class="punct">"</span><span class="string">id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">",</span> <span class="punct">"</span><span class="string">email</span><span class="punct">"=>"</span><span class="string">drnicwilliams@gmail.com</span><span class="punct">"}>]</span>
|
288
|
-
</pre></p>
|
289
|
-
|
290
|
-
|
291
|
-
<h2>Drum roll…</h2>
|
292
|
-
|
293
|
-
|
294
|
-
<p>Ladies and gentlemen. For my final feat of magical mastery, I’ll ask you to do
|
295
|
-
something you’ve never done before. This illusion is akin to the <a href="http://www.toytent.com/Posters/985.html">floating lady</a>
|
296
|
-
illusion that has been passed down through generations of magicians.</p>
|
297
|
-
|
298
|
-
|
299
|
-
<p>Exit your console session.</p>
|
300
|
-
|
301
|
-
|
302
|
-
<span class="caps">DELETE</span> your three model classes: <code>person.rb, group.rb, and membership.rb</code> from the
|
303
|
-
<code>app/models</code> folder. (You can always get them back via the model generator… be fearless!)
|
304
|
-
|
305
|
-
<p>Re-launch your console.</p>
|
306
|
-
|
307
|
-
|
308
|
-
<p><strong>drums are still rolling…</strong></p>
|
309
|
-
|
310
|
-
|
311
|
-
<p>Be prepared to applaud loudly…</p>
|
312
|
-
|
313
|
-
|
274
|
+
</pre></p>
|
275
|
+
|
276
|
+
|
277
|
+
<h2>Drum roll…</h2>
|
278
|
+
|
279
|
+
|
280
|
+
<p>Ladies and gentlemen. For my final feat of magical mastery, I’ll ask you to do
|
281
|
+
something you’ve never done before. This illusion is akin to the <a href="http://www.toytent.com/Posters/985.html">floating lady</a>
|
282
|
+
illusion that has been passed down through generations of magicians.</p>
|
283
|
+
|
284
|
+
|
285
|
+
<p>Exit your console session.</p>
|
286
|
+
|
287
|
+
|
288
|
+
<span class="caps">DELETE</span> your three model classes: <code>person.rb, group.rb, and membership.rb</code> from the
|
289
|
+
<code>app/models</code> folder. (You can always get them back via the model generator… be fearless!)
|
290
|
+
|
291
|
+
<p>Re-launch your console.</p>
|
292
|
+
|
293
|
+
|
294
|
+
<p><strong>drums are still rolling…</strong></p>
|
295
|
+
|
296
|
+
|
297
|
+
<p>Be prepared to applaud loudly…</p>
|
298
|
+
|
299
|
+
|
314
300
|
<p><pre class="syntax">
|
315
301
|
<span class="punct">>></span> <span class="constant">Person</span>
|
316
302
|
<span class="punct">=></span> <span class="constant">Person</span>
|
317
|
-
</pre></p>
|
318
|
-
|
319
|
-
|
320
|
-
<p>You applaud loudly, but watch for more…</p>
|
321
|
-
|
322
|
-
|
303
|
+
</pre></p>
|
304
|
+
|
305
|
+
|
306
|
+
<p>You applaud loudly, but watch for more…</p>
|
307
|
+
|
308
|
+
|
323
309
|
<p><pre class="syntax">
|
324
310
|
<span class="punct">>></span> <span class="ident">person</span> <span class="punct">=</span> <span class="constant">Person</span><span class="punct">.</span><span class="ident">find</span><span class="punct">(</span><span class="number">1</span><span class="punct">)</span>
|
325
311
|
<span class="punct">=></span> <span class="punct"><</span><span class="constant">Person</span><span class="punct">:</span><span class="number">0x3958930</span> <span class="attribute">@attributes</span><span class="punct">={"</span><span class="string">lastname</span><span class="punct">"=>"</span><span class="string">Williams</span><span class="punct">",</span> <span class="punct">"</span><span class="string">firstname</span><span class="punct">"=>"</span><span class="string">Nic</span><span class="punct">",</span>
|
@@ -328,58 +314,58 @@ illusion that has been passed down through generations of magicians.</p>
|
|
328
314
|
<span class="punct">=></span> <span class="punct">[<</span><span class="constant">Membership</span><span class="punct">:</span><span class="number">0x393a000</span> <span class="attribute">@attributes</span><span class="punct">={"</span><span class="string">group_id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">",</span> <span class="punct">"</span><span class="string">id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">",</span> <span class="punct">"</span><span class="string">person_id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">"}>]</span>
|
329
315
|
<span class="punct">>></span> <span class="ident">person</span><span class="punct">.</span><span class="ident">groups</span>
|
330
316
|
<span class="punct">=></span> <span class="punct">[<</span><span class="constant">Group</span><span class="punct">:</span><span class="number">0x390df60</span> <span class="attribute">@attributes</span><span class="punct">={"</span><span class="string">name</span><span class="punct">"=>"</span><span class="string">Magic Models Forum</span><span class="punct">",</span> <span class="punct">"</span><span class="string">id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">",</span> <span class="punct">"</span><span class="string">description</span><span class="punct">"=></span><span class="constant">nil</span><span class="punct">}>]</span>
|
331
|
-
</pre></p>
|
332
|
-
|
333
|
-
|
334
|
-
<h2>Tada!</h2>
|
335
|
-
|
336
|
-
|
337
|
-
<p>The end.</p>
|
338
|
-
|
339
|
-
|
340
|
-
<h2>Dr Nic’s Blog</h2>
|
341
|
-
|
342
|
-
|
343
|
-
<p><a href="http://www.drnicwilliams.com">http://www.drnicwilliams.com</a> – for future announcements and
|
344
|
-
other stories and things.</p>
|
345
|
-
|
346
|
-
|
347
|
-
<h2>Articles about Magic Models</h2>
|
348
|
-
|
349
|
-
|
350
|
-
<ul>
|
351
|
-
<li><a href="http://drnicwilliams.com/2006/08/07/ann-dr-nics-magic-models/">Announcement</a></li>
|
352
|
-
<li><a href="http://drnicwilliams.com/2006/08/10/bts-magic-models-class-creation/"><span class="caps">BTS</span> – Class creation</a></li>
|
353
|
-
</ul>
|
354
|
-
|
355
|
-
|
356
|
-
<h2>Forum</h2>
|
357
|
-
|
358
|
-
|
359
|
-
<p><a href="http://groups.google.com/group/magicmodels">http://groups.google.com/group/magicmodels</a></p>
|
360
|
-
|
361
|
-
|
362
|
-
<h2>Licence</h2>
|
363
|
-
|
364
|
-
|
365
|
-
<p>This code is free to use under the terms of the <span class="caps">MIT</span> licence.</p>
|
366
|
-
|
367
|
-
|
368
|
-
<h2>Contact</h2>
|
369
|
-
|
370
|
-
|
371
|
-
<p>Comments are welcome. Send an email to <a href="mailto:drnicwilliams@gmail.com">Dr Nic Williams</a>
|
372
|
-
or via his blog at <a href="http://www.drnicwilliams.com">http://www.drnicwilliams.com</a></p>
|
373
|
-
<p class="coda">
|
374
|
-
<a href="mailto:drnicwilliams@gmail.com">Dr Nic</a>,
|
375
|
-
Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
|
376
|
-
</p>
|
377
|
-
</div>
|
378
|
-
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
|
379
|
-
</script>
|
380
|
-
<script type="text/javascript">
|
381
|
-
_uacct = "UA-567811-3";
|
382
|
-
urchinTracker();
|
383
|
-
</script>
|
384
|
-
</body>
|
385
|
-
</html>
|
317
|
+
</pre></p>
|
318
|
+
|
319
|
+
|
320
|
+
<h2>Tada!</h2>
|
321
|
+
|
322
|
+
|
323
|
+
<p>The end.</p>
|
324
|
+
|
325
|
+
|
326
|
+
<h2>Dr Nic’s Blog</h2>
|
327
|
+
|
328
|
+
|
329
|
+
<p><a href="http://www.drnicwilliams.com">http://www.drnicwilliams.com</a> – for future announcements and
|
330
|
+
other stories and things.</p>
|
331
|
+
|
332
|
+
|
333
|
+
<h2>Articles about Magic Models</h2>
|
334
|
+
|
335
|
+
|
336
|
+
<ul>
|
337
|
+
<li><a href="http://drnicwilliams.com/2006/08/07/ann-dr-nics-magic-models/">Announcement</a></li>
|
338
|
+
<li><a href="http://drnicwilliams.com/2006/08/10/bts-magic-models-class-creation/"><span class="caps">BTS</span> – Class creation</a></li>
|
339
|
+
</ul>
|
340
|
+
|
341
|
+
|
342
|
+
<h2>Forum</h2>
|
343
|
+
|
344
|
+
|
345
|
+
<p><a href="http://groups.google.com/group/magicmodels">http://groups.google.com/group/magicmodels</a></p>
|
346
|
+
|
347
|
+
|
348
|
+
<h2>Licence</h2>
|
349
|
+
|
350
|
+
|
351
|
+
<p>This code is free to use under the terms of the <span class="caps">MIT</span> licence.</p>
|
352
|
+
|
353
|
+
|
354
|
+
<h2>Contact</h2>
|
355
|
+
|
356
|
+
|
357
|
+
<p>Comments are welcome. Send an email to <a href="mailto:drnicwilliams@gmail.com">Dr Nic Williams</a>
|
358
|
+
or via his blog at <a href="http://www.drnicwilliams.com">http://www.drnicwilliams.com</a></p>
|
359
|
+
<p class="coda">
|
360
|
+
<a href="mailto:drnicwilliams@gmail.com">Dr Nic</a>, 9th April 2007<br>
|
361
|
+
Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
|
362
|
+
</p>
|
363
|
+
</div>
|
364
|
+
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
|
365
|
+
</script>
|
366
|
+
<script type="text/javascript">
|
367
|
+
_uacct = "UA-567811-3";
|
368
|
+
urchinTracker();
|
369
|
+
</script>
|
370
|
+
</body>
|
371
|
+
</html>
|