dr_nic_magic_models 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +10 -1
- data/Manifest.txt +1 -0
- data/README +55 -29
- data/lib/dr_nic_magic_models/magic_model.rb +4 -2
- data/lib/dr_nic_magic_models/version.rb +1 -1
- data/lib/dr_nic_magic_models.rb +4 -1
- data/lib/module.rb +5 -5
- data/test/magic_module_test.rb +1 -1
- data/test/test_existing_model.rb +20 -0
- data/test.db +0 -0
- data/website/index.html +66 -33
- data/website/index.txt +55 -28
- data/website/stylesheets/screen.css +1 -1
- data/website/template.rhtml +5 -4
- data/website/version-raw.js +1 -1
- data/website/version.js +1 -1
- metadata +5 -4
data/History.txt
CHANGED
@@ -1,10 +1,19 @@
|
|
1
|
+
*** 0.9.1 / 2007-4-11
|
2
|
+
|
3
|
+
+ 1 minor enhancement:
|
4
|
+
+ ActiveRecord::Base includes all the magic model functionality via the MagicModel module
|
5
|
+
+ Existing ARs can get magic validation via #generate_validations call
|
6
|
+
+ Website tutorial works :D
|
7
|
+
|
1
8
|
*** 0.9.0 / 2007-4-9
|
2
9
|
|
3
10
|
+ 1 major enhancement:
|
4
11
|
+ Support for dynamic loading of classes again
|
5
12
|
+ 2 new DB supported:
|
6
13
|
+ Tests run on sqlite (no fk support)
|
7
|
-
|
14
|
+
+ Tests run on postgresql (fk support)
|
15
|
+
+ Including FK bug fix
|
8
16
|
+ Many fixes that I've lost track of
|
9
17
|
+ History.txt to keep track of changes like these
|
10
18
|
+ Using Hoe for Rakefile
|
19
|
+
+ Use modules to specify common table prefixes
|
data/Manifest.txt
CHANGED
@@ -43,6 +43,7 @@ test/invisible_model_access_test.rb
|
|
43
43
|
test/invisible_model_assoc_test.rb
|
44
44
|
test/invisible_model_classes_test.rb
|
45
45
|
test/magic_module_test.rb
|
46
|
+
test/test_existing_model.rb
|
46
47
|
website/index.html
|
47
48
|
website/index.txt
|
48
49
|
website/javascripts/rounded_corners_lite.inc.js
|
data/README
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
See http://magicmodels.rubyforge.org/dr_nic_magic_models for pretty README
|
2
2
|
|
3
3
|
Ugly README (from website/index.txt in Textile format):
|
4
|
-
|
5
4
|
h1. Dr Nic's Magic Models
|
6
5
|
|
7
6
|
If you've used Ruby on Rails you'll have written at least one model class like this:
|
@@ -70,10 +69,10 @@ Your application is now blessed with magical mystery.
|
|
70
69
|
|
71
70
|
h2. David Copperfield eat your Ruby-crusted heart out
|
72
71
|
|
73
|
-
Let's demonstrate the magical mystery in all its full-stage glory. Create a Ruby on Rails app:
|
72
|
+
Let's demonstrate the magical mystery in all its full-stage glory. Create a Ruby on Rails app (example uses sqlite3, but use your favourite databas):
|
74
73
|
|
75
74
|
<pre syntax="ruby">
|
76
|
-
rails magic_show
|
75
|
+
rails magic_show -d sqlite3
|
77
76
|
cd magic_show
|
78
77
|
ruby script/generate model Person
|
79
78
|
ruby script/generate model Group
|
@@ -114,18 +113,12 @@ and <code>003_create_memberships.rb</code> with:
|
|
114
113
|
end
|
115
114
|
</pre>
|
116
115
|
|
117
|
-
Now create your database. For MySql:
|
118
|
-
<pre>
|
119
|
-
mysqladmin -u root create magic_show_development
|
120
|
-
mysqladmin -u root create magic_show_test
|
121
|
-
</pre>
|
122
|
-
|
123
116
|
And run your migrations to create the three tables:
|
124
117
|
<pre>
|
125
|
-
rake migrate
|
118
|
+
rake db:migrate
|
126
119
|
</pre>
|
127
120
|
|
128
|
-
|
121
|
+
h3. And now for some "woofle dust":http://en.wikipedia.org/wiki/List_of_conjuring_terms ...
|
129
122
|
|
130
123
|
At the end of <code>config/environment.rb</code> add the following line:
|
131
124
|
|
@@ -146,6 +139,20 @@ end
|
|
146
139
|
|
147
140
|
Nothing suspicious here. We have no validations and no associations. Just some plain old model classes.
|
148
141
|
|
142
|
+
UPDATE: To turn on magic validations, you now need to invoke <code>generate_validations</code> on defined classes. So, update your model classes:
|
143
|
+
|
144
|
+
<pre syntax="ruby">
|
145
|
+
class Person < ActiveRecord::Base
|
146
|
+
generate_validations
|
147
|
+
end
|
148
|
+
class Group < ActiveRecord::Base
|
149
|
+
generate_validations
|
150
|
+
end
|
151
|
+
class Membership < ActiveRecord::Base
|
152
|
+
generate_validations
|
153
|
+
end
|
154
|
+
</pre>
|
155
|
+
|
149
156
|
For this trick, we'll need an ordinary console session. Any old one lying around the house will do.
|
150
157
|
|
151
158
|
<pre>
|
@@ -156,22 +163,24 @@ Now a normal model class is valid until you explicitly add <code>validates_xxx</
|
|
156
163
|
With Dr Nic's Magic Models:
|
157
164
|
|
158
165
|
<pre syntax="ruby">
|
159
|
-
|
166
|
+
person = Person.new
|
160
167
|
=> #<Person:0x393e0f8 @attributes={"lastname"=>"", "firstname"=>"", "email"=>""}, @new_record=true>
|
161
|
-
|
168
|
+
person.valid?
|
162
169
|
=> false
|
163
|
-
|
164
|
-
=>
|
165
|
-
"
|
166
|
-
|
167
|
-
|
170
|
+
person.errors
|
171
|
+
=> #<ActiveRecord::Errors:0x3537b38 @errors={
|
172
|
+
"firstname"=>["can't be blank", "is too long (maximum is 255 characters)"],
|
173
|
+
"lastname"=>["can't be blank", "is too long (maximum is 255 characters)"],
|
174
|
+
"email"=>["can't be blank", "is too long (maximum is 255 characters)"]},
|
175
|
+
@base=#<Person:0x3538bf0 @errors=#<ActiveRecord::Errors:0x3537b38 ...>, @new_record=true,
|
176
|
+
@attributes={"lastname"=>nil, "firstname"=>nil, "email"=>nil}>>
|
168
177
|
</pre>
|
169
178
|
|
170
|
-
*Kapoow!* Instant validation!
|
179
|
+
*Kapoow!* Instant validation! (NOTE: not as instant as it used to be - remember - you need to call <code>generate_validations</code> on each class as required)
|
171
180
|
|
172
181
|
Because you specified the three columns as <code>:null => false</code>,
|
173
|
-
your ActiveRecord models will now
|
174
|
-
for each non-null field.
|
182
|
+
your ActiveRecord models will now automagically generated <code>validates_presence_of</code>
|
183
|
+
for each non-null field, plus several other validations (since version 0.8.0).
|
175
184
|
|
176
185
|
Ok, we're just warming up.
|
177
186
|
|
@@ -181,15 +190,15 @@ demonstrated above) to have the brilliantly simple support that Rails/ActiveReco
|
|
181
190
|
Let's just watch what Dr Nic's Magic Models can do without any effort at all...
|
182
191
|
|
183
192
|
<pre syntax="ruby">
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
193
|
+
person = Person.create(:firstname => "Nic", :lastname => "Williams", :email => "drnicwilliams@gmail.com")
|
194
|
+
group = Group.create(:name => "Magic Models Forum", :description => "http://groups.google.com/magicmodels")
|
195
|
+
membership = Membership.create(:person => person, :group => group)
|
196
|
+
person.memberships.length
|
188
197
|
=> 1
|
189
|
-
|
198
|
+
membership.person
|
190
199
|
=> <Person:0x38898e8 @attributes={"lastname"=>"Williams", "firstname"=>"Nic",
|
191
200
|
"id"=>"1", "email"=>"drnicwilliams@gmail.com"}>
|
192
|
-
|
201
|
+
group.memberships
|
193
202
|
=> [<Membership:0x3c8cd70 @attributes={"group_id"=>"1", "id"=>"1", "person_id"=>"1"}>]
|
194
203
|
</pre>
|
195
204
|
|
@@ -204,7 +213,7 @@ The final association trick is a ripper. Automatic generation of <code>has_many
|
|
204
213
|
"id"=>"1", "email"=>"drnicwilliams@gmail.com"}>]
|
205
214
|
</pre>
|
206
215
|
|
207
|
-
|
216
|
+
h3. Drum roll...
|
208
217
|
|
209
218
|
Ladies and gentlemen. For my final feat of magical mastery, I'll ask you to do
|
210
219
|
something you've never done before. This illusion is akin to the "floating lady":http://www.toytent.com/Posters/985.html
|
@@ -215,6 +224,8 @@ Exit your console session.
|
|
215
224
|
DELETE your three model classes: <code>person.rb, group.rb, and membership.rb</code> from the
|
216
225
|
<code>app/models</code> folder. (You can always get them back via the model generator... be fearless!)
|
217
226
|
|
227
|
+
<pre>rm app/models/*.rb</pre>
|
228
|
+
|
218
229
|
Re-launch your console.
|
219
230
|
|
220
231
|
*drums are still rolling...*
|
@@ -229,19 +240,34 @@ Be prepared to applaud loudly...
|
|
229
240
|
You applaud loudly, but watch for more...
|
230
241
|
|
231
242
|
<pre syntax="ruby">
|
243
|
+
>> Person.new.valid?
|
244
|
+
=> false
|
232
245
|
>> person = Person.find(1)
|
233
246
|
=> <Person:0x3958930 @attributes={"lastname"=>"Williams", "firstname"=>"Nic",
|
234
247
|
"id"=>"1", "email"=>"drnicwilliams@gmail.com"}>
|
248
|
+
>> person.valid?
|
249
|
+
=> true
|
235
250
|
>> person.memberships
|
236
251
|
=> [<Membership:0x393a000 @attributes={"group_id"=>"1", "id"=>"1", "person_id"=>"1"}>]
|
237
252
|
>> person.groups
|
238
253
|
=> [<Group:0x390df60 @attributes={"name"=>"Magic Models Forum", "id"=>"1", "description"=>nil}>]
|
239
254
|
</pre>
|
240
255
|
|
241
|
-
|
256
|
+
h3. Tada!
|
242
257
|
|
243
258
|
The end.
|
244
259
|
|
260
|
+
h3. Use modules to scope your magic
|
261
|
+
|
262
|
+
Only want to pick up tables starting with <code>blog_</code>?
|
263
|
+
|
264
|
+
<pre syntax="ruby">module Blog
|
265
|
+
magic_module :table_name_prefix => 'blog_'
|
266
|
+
end
|
267
|
+
|
268
|
+
Blog::Post.table_name # => 'blog_posts'
|
269
|
+
</pre>
|
270
|
+
|
245
271
|
h2. Dr Nic's Blog
|
246
272
|
|
247
273
|
"http://www.drnicwilliams.com":http://www.drnicwilliams.com - for future announcements and
|
@@ -53,9 +53,11 @@ module DrNicMagicModels::MagicModel
|
|
53
53
|
rescue NotImplementedError
|
54
54
|
nil
|
55
55
|
end
|
56
|
-
if
|
56
|
+
if !fkc.nil? && fkc.length > 0
|
57
57
|
foreign_key = fkc.first.foreign_key
|
58
|
-
options = {:dependent => :destroy,
|
58
|
+
options = {:dependent => :destroy,
|
59
|
+
:foreign_key => fkc.first.foreign_key,
|
60
|
+
:class_name => self.class.class_name(fkc.first.reference_table)}
|
59
61
|
else
|
60
62
|
foreign_key = self.class.columns.select {|column| column.name == method.to_s.foreign_key}.first
|
61
63
|
end
|
data/lib/dr_nic_magic_models.rb
CHANGED
@@ -28,4 +28,7 @@ require 'connection_adapters/postgresql_adapter'
|
|
28
28
|
# load the schema
|
29
29
|
# TODO - add this to README - DrNicMagicModels::Schema.load_schema(true)
|
30
30
|
|
31
|
-
|
31
|
+
class ActiveRecord::Base
|
32
|
+
include DrNicMagicModels::MagicModel
|
33
|
+
extend DrNicMagicModels::Validations
|
34
|
+
end
|
data/lib/module.rb
CHANGED
@@ -13,21 +13,21 @@ class Module
|
|
13
13
|
superklass = @magic_schema.superklass || ActiveRecord::Base
|
14
14
|
klass = create_class(class_id, superklass) do
|
15
15
|
set_table_name table_name
|
16
|
-
include DrNicMagicModels::MagicModel
|
17
|
-
extend DrNicMagicModels::Validations
|
16
|
+
# include DrNicMagicModels::MagicModel
|
17
|
+
# extend DrNicMagicModels::Validations
|
18
18
|
end
|
19
19
|
klass.generate_validations # need to call this AFTER the class name has been assigned
|
20
20
|
@magic_schema.inflector.post_class_creation klass
|
21
21
|
klass
|
22
22
|
end
|
23
23
|
|
24
|
-
def magic_module(
|
25
|
-
self.instance_variable_set "@table_name_prefix", table_name_prefix
|
24
|
+
def magic_module(options)
|
25
|
+
self.instance_variable_set "@table_name_prefix", options[:table_name_prefix] if options[:table_name_prefix]
|
26
26
|
end
|
27
27
|
|
28
28
|
private
|
29
29
|
def create_class(class_name, superclass, &block)
|
30
30
|
klass = Class.new superclass, &block
|
31
|
-
|
31
|
+
self.const_set class_name, klass
|
32
32
|
end
|
33
33
|
end
|
data/test/magic_module_test.rb
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'abstract_unit'
|
2
|
+
require 'pp'
|
3
|
+
|
4
|
+
module TestBed
|
5
|
+
class Group < ActiveRecord::Base
|
6
|
+
generate_validations
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class TestExistingModel < Test::Unit::TestCase
|
11
|
+
# fixtures :fun_users, :groups, :group_memberships, :group_tag
|
12
|
+
|
13
|
+
def setup
|
14
|
+
create_fixtures :fun_users, :groups, :group_memberships, :group_tag
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_valid
|
18
|
+
assert(!TestBed::Group.new.valid?)
|
19
|
+
end
|
20
|
+
end
|
data/test.db
CHANGED
Binary file
|
data/website/index.html
CHANGED
@@ -32,12 +32,13 @@
|
|
32
32
|
</head>
|
33
33
|
<body>
|
34
34
|
<div id="main">
|
35
|
+
<p><a href="/">↩ More Magic</a></p>
|
35
36
|
|
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>
|
36
41
|
<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
|
<p>If you’ve used Ruby on Rails you’ll have written at least one model class like this:</p>
|
42
43
|
|
43
44
|
|
@@ -120,11 +121,11 @@ require 'dr_nic_magic_models'
|
|
120
121
|
<h2>David Copperfield eat your Ruby-crusted heart out</h2>
|
121
122
|
|
122
123
|
|
123
|
-
<p>Let’s demonstrate the magical mystery in all its full-stage glory. Create a Ruby on Rails app:</p>
|
124
|
+
<p>Let’s demonstrate the magical mystery in all its full-stage glory. Create a Ruby on Rails app (example uses sqlite3, but use your favourite databas):</p>
|
124
125
|
|
125
126
|
|
126
127
|
<p><pre class="syntax">
|
127
|
-
<span class="ident">rails</span> <span class="ident">magic_show</span>
|
128
|
+
<span class="ident">rails</span> <span class="ident">magic_show</span> <span class="punct">-</span><span class="ident">d</span> <span class="ident">sqlite3</span>
|
128
129
|
<span class="ident">cd</span> <span class="ident">magic_show</span>
|
129
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">Person</span>
|
130
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">Group</span>
|
@@ -169,18 +170,12 @@ with:
|
|
169
170
|
</pre></p>
|
170
171
|
|
171
172
|
|
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
173
|
And run your migrations to create the three tables:
|
179
174
|
<pre>
|
180
|
-
rake migrate
|
175
|
+
rake db:migrate
|
181
176
|
</pre>
|
182
177
|
|
183
|
-
<
|
178
|
+
<h3>And now for some <a href="http://en.wikipedia.org/wiki/List_of_conjuring_terms">woofle dust</a> ...</h3>
|
184
179
|
|
185
180
|
|
186
181
|
<p>At the end of <code>config/environment.rb</code> add the following line:</p>
|
@@ -206,6 +201,22 @@ require 'dr_nic_magic_models'
|
|
206
201
|
<p>Nothing suspicious here. We have no validations and no associations. Just some plain old model classes.</p>
|
207
202
|
|
208
203
|
|
204
|
+
<p><span class="caps">UPDATE</span>: To turn on magic validations, you now need to invoke <code>generate_validations</code> on defined classes. So, update your model classes:</p>
|
205
|
+
|
206
|
+
|
207
|
+
<p><pre class="syntax">
|
208
|
+
<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>
|
209
|
+
<span class="ident">generate_validations</span>
|
210
|
+
<span class="keyword">end</span>
|
211
|
+
<span class="keyword">class </span><span class="class">Group</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span>
|
212
|
+
<span class="ident">generate_validations</span>
|
213
|
+
<span class="keyword">end</span>
|
214
|
+
<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>
|
215
|
+
<span class="ident">generate_validations</span>
|
216
|
+
<span class="keyword">end</span>
|
217
|
+
</pre></p>
|
218
|
+
|
219
|
+
|
209
220
|
<p>For this trick, we’ll need an ordinary console session. Any old one lying around the house will do.</p>
|
210
221
|
|
211
222
|
|
@@ -218,24 +229,26 @@ With Dr Nic’s Magic Models:</p>
|
|
218
229
|
|
219
230
|
|
220
231
|
<p><pre class="syntax">
|
221
|
-
<span class="
|
232
|
+
<span class="ident">person</span> <span class="punct">=</span> <span class="constant">Person</span><span class="punct">.</span><span class="ident">new</span>
|
222
233
|
<span class="punct">=></span> <span class="comment">#<Person:0x393e0f8 @attributes={"lastname"=>"", "firstname"=>"", "email"=>""}, @new_record=true></span>
|
223
|
-
<span class="
|
234
|
+
<span class="ident">person</span><span class="punct">.</span><span class="ident">valid?</span>
|
224
235
|
<span class="punct">=></span> <span class="constant">false</span>
|
225
|
-
<span class="
|
226
|
-
<span class="punct">=></span> <span class="
|
227
|
-
<span class="punct">"</span><span class="string">
|
228
|
-
<span class="
|
229
|
-
<span class="
|
236
|
+
<span class="ident">person</span><span class="punct">.</span><span class="ident">errors</span>
|
237
|
+
<span class="punct">=></span> <span class="comment">#<ActiveRecord::Errors:0x3537b38 @errors={</span>
|
238
|
+
<span class="punct">"</span><span class="string">firstname</span><span class="punct">"=>["</span><span class="string">can't be blank</span><span class="punct">",</span> <span class="punct">"</span><span class="string">is too long (maximum is 255 characters)</span><span class="punct">"],</span>
|
239
|
+
<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">is too long (maximum is 255 characters)</span><span class="punct">"],</span>
|
240
|
+
<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> <span class="punct">"</span><span class="string">is too long (maximum is 255 characters)</span><span class="punct">"]},</span>
|
241
|
+
<span class="attribute">@base</span><span class="punct">=</span><span class="comment">#<Person:0x3538bf0 @errors=#<ActiveRecord::Errors:0x3537b38 ...>, @new_record=true, </span>
|
242
|
+
<span class="attribute">@attributes</span><span class="punct">={"</span><span class="string">lastname</span><span class="punct">"=></span><span class="constant">nil</span><span class="punct">,</span> <span class="punct">"</span><span class="string">firstname</span><span class="punct">"=></span><span class="constant">nil</span><span class="punct">,</span> <span class="punct">"</span><span class="string">email</span><span class="punct">"=></span><span class="constant">nil</span><span class="punct">}>></span>
|
230
243
|
</pre></p>
|
231
244
|
|
232
245
|
|
233
|
-
<p><strong>Kapoow!</strong> Instant validation
|
246
|
+
<p><strong>Kapoow!</strong> Instant validation! (NOTE: not as instant as it used to be – remember – you need to call <code>generate_validations</code> on each class as required)</p>
|
234
247
|
|
235
248
|
|
236
249
|
<p>Because you specified the three columns as <code>:null => false</code>,
|
237
|
-
your ActiveRecord models will now
|
238
|
-
for each non-null field.</p>
|
250
|
+
your ActiveRecord models will now automagically generated <code>validates_presence_of</code>
|
251
|
+
for each non-null field, plus several other validations (since version 0.8.0).</p>
|
239
252
|
|
240
253
|
|
241
254
|
<p>Ok, we’re just warming up.</p>
|
@@ -249,15 +262,15 @@ demonstrated above) to have the brilliantly simple support that Rails/ActiveReco
|
|
249
262
|
|
250
263
|
|
251
264
|
<p><pre class="syntax">
|
252
|
-
<span class="
|
253
|
-
<span class="
|
254
|
-
<span class="
|
255
|
-
<span class="
|
265
|
+
<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>
|
266
|
+
<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>
|
267
|
+
<span class="ident">membership</span> <span class="punct">=</span> <span class="constant">Membership</span><span class="punct">.</span><span class="ident">create</span><span class="punct">(</span><span class="symbol">:person</span> <span class="punct">=></span> <span class="ident">person</span><span class="punct">,</span> <span class="symbol">:group</span> <span class="punct">=></span> <span class="ident">group</span><span class="punct">)</span>
|
268
|
+
<span class="ident">person</span><span class="punct">.</span><span class="ident">memberships</span><span class="punct">.</span><span class="ident">length</span>
|
256
269
|
<span class="punct">=></span> <span class="number">1</span>
|
257
|
-
<span class="
|
270
|
+
<span class="ident">membership</span><span class="punct">.</span><span class="ident">person</span>
|
258
271
|
<span class="punct">=></span> <span class="punct"><</span><span class="constant">Person</span><span class="punct">:</span><span class="number">0x38898e8</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>
|
259
272
|
<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>
|
260
|
-
<span class="
|
273
|
+
<span class="ident">group</span><span class="punct">.</span><span class="ident">memberships</span>
|
261
274
|
<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>
|
262
275
|
</pre></p>
|
263
276
|
|
@@ -274,7 +287,7 @@ demonstrated above) to have the brilliantly simple support that Rails/ActiveReco
|
|
274
287
|
</pre></p>
|
275
288
|
|
276
289
|
|
277
|
-
<
|
290
|
+
<h3>Drum roll…</h3>
|
278
291
|
|
279
292
|
|
280
293
|
<p>Ladies and gentlemen. For my final feat of magical mastery, I’ll ask you to do
|
@@ -288,6 +301,8 @@ illusion that has been passed down through generations of magicians.</p>
|
|
288
301
|
<span class="caps">DELETE</span> your three model classes: <code>person.rb, group.rb, and membership.rb</code> from the
|
289
302
|
<code>app/models</code> folder. (You can always get them back via the model generator… be fearless!)
|
290
303
|
|
304
|
+
<pre>rm app/models/*.rb</pre>
|
305
|
+
|
291
306
|
<p>Re-launch your console.</p>
|
292
307
|
|
293
308
|
|
@@ -307,9 +322,13 @@ illusion that has been passed down through generations of magicians.</p>
|
|
307
322
|
|
308
323
|
|
309
324
|
<p><pre class="syntax">
|
325
|
+
<span class="punct">>></span> <span class="constant">Person</span><span class="punct">.</span><span class="ident">new</span><span class="punct">.</span><span class="ident">valid?</span>
|
326
|
+
<span class="punct">=></span> <span class="constant">false</span>
|
310
327
|
<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>
|
311
328
|
<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>
|
312
329
|
<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>
|
330
|
+
<span class="punct">>></span> <span class="ident">person</span><span class="punct">.</span><span class="ident">valid?</span>
|
331
|
+
<span class="punct">=></span> <span class="constant">true</span>
|
313
332
|
<span class="punct">>></span> <span class="ident">person</span><span class="punct">.</span><span class="ident">memberships</span>
|
314
333
|
<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>
|
315
334
|
<span class="punct">>></span> <span class="ident">person</span><span class="punct">.</span><span class="ident">groups</span>
|
@@ -317,12 +336,26 @@ illusion that has been passed down through generations of magicians.</p>
|
|
317
336
|
</pre></p>
|
318
337
|
|
319
338
|
|
320
|
-
<
|
339
|
+
<h3>Tada!</h3>
|
321
340
|
|
322
341
|
|
323
342
|
<p>The end.</p>
|
324
343
|
|
325
344
|
|
345
|
+
<h3>Use modules to scope your magic</h3>
|
346
|
+
|
347
|
+
|
348
|
+
<p>Only want to pick up tables starting with <code>blog_</code>?</p>
|
349
|
+
|
350
|
+
|
351
|
+
<p><pre class="syntax"><span class="keyword">module </span><span class="module">Blog</span>
|
352
|
+
<span class="ident">magic_module</span> <span class="symbol">:table_name_prefix</span> <span class="punct">=></span> <span class="punct">'</span><span class="string">blog_</span><span class="punct">'</span>
|
353
|
+
<span class="keyword">end</span>
|
354
|
+
|
355
|
+
<span class="constant">Blog</span><span class="punct">::</span><span class="constant">Post</span><span class="punct">.</span><span class="ident">table_name</span> <span class="comment"># => 'blog_posts'</span>
|
356
|
+
</pre></p>
|
357
|
+
|
358
|
+
|
326
359
|
<h2>Dr Nic’s Blog</h2>
|
327
360
|
|
328
361
|
|
@@ -357,7 +390,7 @@ other stories and things.</p>
|
|
357
390
|
<p>Comments are welcome. Send an email to <a href="mailto:drnicwilliams@gmail.com">Dr Nic Williams</a>
|
358
391
|
or via his blog at <a href="http://www.drnicwilliams.com">http://www.drnicwilliams.com</a></p>
|
359
392
|
<p class="coda">
|
360
|
-
<a href="mailto:drnicwilliams@gmail.com">Dr Nic</a>,
|
393
|
+
<a href="mailto:drnicwilliams@gmail.com">Dr Nic</a>, 11th April 2007<br>
|
361
394
|
Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
|
362
395
|
</p>
|
363
396
|
</div>
|
data/website/index.txt
CHANGED
@@ -66,10 +66,10 @@ Your application is now blessed with magical mystery.
|
|
66
66
|
|
67
67
|
h2. David Copperfield eat your Ruby-crusted heart out
|
68
68
|
|
69
|
-
Let's demonstrate the magical mystery in all its full-stage glory. Create a Ruby on Rails app:
|
69
|
+
Let's demonstrate the magical mystery in all its full-stage glory. Create a Ruby on Rails app (example uses sqlite3, but use your favourite databas):
|
70
70
|
|
71
71
|
<pre syntax="ruby">
|
72
|
-
rails magic_show
|
72
|
+
rails magic_show -d sqlite3
|
73
73
|
cd magic_show
|
74
74
|
ruby script/generate model Person
|
75
75
|
ruby script/generate model Group
|
@@ -110,18 +110,12 @@ and <code>003_create_memberships.rb</code> with:
|
|
110
110
|
end
|
111
111
|
</pre>
|
112
112
|
|
113
|
-
Now create your database. For MySql:
|
114
|
-
<pre>
|
115
|
-
mysqladmin -u root create magic_show_development
|
116
|
-
mysqladmin -u root create magic_show_test
|
117
|
-
</pre>
|
118
|
-
|
119
113
|
And run your migrations to create the three tables:
|
120
114
|
<pre>
|
121
|
-
rake migrate
|
115
|
+
rake db:migrate
|
122
116
|
</pre>
|
123
117
|
|
124
|
-
|
118
|
+
h3. And now for some "woofle dust":http://en.wikipedia.org/wiki/List_of_conjuring_terms ...
|
125
119
|
|
126
120
|
At the end of <code>config/environment.rb</code> add the following line:
|
127
121
|
|
@@ -142,6 +136,20 @@ end
|
|
142
136
|
|
143
137
|
Nothing suspicious here. We have no validations and no associations. Just some plain old model classes.
|
144
138
|
|
139
|
+
UPDATE: To turn on magic validations, you now need to invoke <code>generate_validations</code> on defined classes. So, update your model classes:
|
140
|
+
|
141
|
+
<pre syntax="ruby">
|
142
|
+
class Person < ActiveRecord::Base
|
143
|
+
generate_validations
|
144
|
+
end
|
145
|
+
class Group < ActiveRecord::Base
|
146
|
+
generate_validations
|
147
|
+
end
|
148
|
+
class Membership < ActiveRecord::Base
|
149
|
+
generate_validations
|
150
|
+
end
|
151
|
+
</pre>
|
152
|
+
|
145
153
|
For this trick, we'll need an ordinary console session. Any old one lying around the house will do.
|
146
154
|
|
147
155
|
<pre>
|
@@ -152,22 +160,24 @@ Now a normal model class is valid until you explicitly add <code>validates_xxx</
|
|
152
160
|
With Dr Nic's Magic Models:
|
153
161
|
|
154
162
|
<pre syntax="ruby">
|
155
|
-
|
163
|
+
person = Person.new
|
156
164
|
=> #<Person:0x393e0f8 @attributes={"lastname"=>"", "firstname"=>"", "email"=>""}, @new_record=true>
|
157
|
-
|
165
|
+
person.valid?
|
158
166
|
=> false
|
159
|
-
|
160
|
-
=>
|
161
|
-
"
|
162
|
-
|
163
|
-
|
167
|
+
person.errors
|
168
|
+
=> #<ActiveRecord::Errors:0x3537b38 @errors={
|
169
|
+
"firstname"=>["can't be blank", "is too long (maximum is 255 characters)"],
|
170
|
+
"lastname"=>["can't be blank", "is too long (maximum is 255 characters)"],
|
171
|
+
"email"=>["can't be blank", "is too long (maximum is 255 characters)"]},
|
172
|
+
@base=#<Person:0x3538bf0 @errors=#<ActiveRecord::Errors:0x3537b38 ...>, @new_record=true,
|
173
|
+
@attributes={"lastname"=>nil, "firstname"=>nil, "email"=>nil}>>
|
164
174
|
</pre>
|
165
175
|
|
166
|
-
*Kapoow!* Instant validation!
|
176
|
+
*Kapoow!* Instant validation! (NOTE: not as instant as it used to be - remember - you need to call <code>generate_validations</code> on each class as required)
|
167
177
|
|
168
178
|
Because you specified the three columns as <code>:null => false</code>,
|
169
|
-
your ActiveRecord models will now
|
170
|
-
for each non-null field.
|
179
|
+
your ActiveRecord models will now automagically generated <code>validates_presence_of</code>
|
180
|
+
for each non-null field, plus several other validations (since version 0.8.0).
|
171
181
|
|
172
182
|
Ok, we're just warming up.
|
173
183
|
|
@@ -177,15 +187,15 @@ demonstrated above) to have the brilliantly simple support that Rails/ActiveReco
|
|
177
187
|
Let's just watch what Dr Nic's Magic Models can do without any effort at all...
|
178
188
|
|
179
189
|
<pre syntax="ruby">
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
190
|
+
person = Person.create(:firstname => "Nic", :lastname => "Williams", :email => "drnicwilliams@gmail.com")
|
191
|
+
group = Group.create(:name => "Magic Models Forum", :description => "http://groups.google.com/magicmodels")
|
192
|
+
membership = Membership.create(:person => person, :group => group)
|
193
|
+
person.memberships.length
|
184
194
|
=> 1
|
185
|
-
|
195
|
+
membership.person
|
186
196
|
=> <Person:0x38898e8 @attributes={"lastname"=>"Williams", "firstname"=>"Nic",
|
187
197
|
"id"=>"1", "email"=>"drnicwilliams@gmail.com"}>
|
188
|
-
|
198
|
+
group.memberships
|
189
199
|
=> [<Membership:0x3c8cd70 @attributes={"group_id"=>"1", "id"=>"1", "person_id"=>"1"}>]
|
190
200
|
</pre>
|
191
201
|
|
@@ -200,7 +210,7 @@ The final association trick is a ripper. Automatic generation of <code>has_many
|
|
200
210
|
"id"=>"1", "email"=>"drnicwilliams@gmail.com"}>]
|
201
211
|
</pre>
|
202
212
|
|
203
|
-
|
213
|
+
h3. Drum roll...
|
204
214
|
|
205
215
|
Ladies and gentlemen. For my final feat of magical mastery, I'll ask you to do
|
206
216
|
something you've never done before. This illusion is akin to the "floating lady":http://www.toytent.com/Posters/985.html
|
@@ -211,6 +221,8 @@ Exit your console session.
|
|
211
221
|
DELETE your three model classes: <code>person.rb, group.rb, and membership.rb</code> from the
|
212
222
|
<code>app/models</code> folder. (You can always get them back via the model generator... be fearless!)
|
213
223
|
|
224
|
+
<pre>rm app/models/*.rb</pre>
|
225
|
+
|
214
226
|
Re-launch your console.
|
215
227
|
|
216
228
|
*drums are still rolling...*
|
@@ -225,19 +237,34 @@ Be prepared to applaud loudly...
|
|
225
237
|
You applaud loudly, but watch for more...
|
226
238
|
|
227
239
|
<pre syntax="ruby">
|
240
|
+
>> Person.new.valid?
|
241
|
+
=> false
|
228
242
|
>> person = Person.find(1)
|
229
243
|
=> <Person:0x3958930 @attributes={"lastname"=>"Williams", "firstname"=>"Nic",
|
230
244
|
"id"=>"1", "email"=>"drnicwilliams@gmail.com"}>
|
245
|
+
>> person.valid?
|
246
|
+
=> true
|
231
247
|
>> person.memberships
|
232
248
|
=> [<Membership:0x393a000 @attributes={"group_id"=>"1", "id"=>"1", "person_id"=>"1"}>]
|
233
249
|
>> person.groups
|
234
250
|
=> [<Group:0x390df60 @attributes={"name"=>"Magic Models Forum", "id"=>"1", "description"=>nil}>]
|
235
251
|
</pre>
|
236
252
|
|
237
|
-
|
253
|
+
h3. Tada!
|
238
254
|
|
239
255
|
The end.
|
240
256
|
|
257
|
+
h3. Use modules to scope your magic
|
258
|
+
|
259
|
+
Only want to pick up tables starting with <code>blog_</code>?
|
260
|
+
|
261
|
+
<pre syntax="ruby">module Blog
|
262
|
+
magic_module :table_name_prefix => 'blog_'
|
263
|
+
end
|
264
|
+
|
265
|
+
Blog::Post.table_name # => 'blog_posts'
|
266
|
+
</pre>
|
267
|
+
|
241
268
|
h2. Dr Nic's Blog
|
242
269
|
|
243
270
|
"http://www.drnicwilliams.com":http://www.drnicwilliams.com - for future announcements and
|
data/website/template.rhtml
CHANGED
@@ -32,12 +32,13 @@
|
|
32
32
|
</head>
|
33
33
|
<body>
|
34
34
|
<div id="main">
|
35
|
+
<p><a href="/">↩ More Magic</a></p>
|
35
36
|
|
37
|
+
<div id="version" class="clickable" onclick='document.location = "<%= download %>"; return false'>
|
38
|
+
Get Version
|
39
|
+
<a id="version_num" href="<%= download %>" class="numbers"></a>
|
40
|
+
</div>
|
36
41
|
<h1><%= title %></h1>
|
37
|
-
<div id="version" class="clickable" onclick='document.location = "<%= download %>"; return false'>
|
38
|
-
Get Version
|
39
|
-
<a id="version_num" href="<%= download %>" class="numbers"></a>
|
40
|
-
</div>
|
41
42
|
<%= body %>
|
42
43
|
<p class="coda">
|
43
44
|
<a href="mailto:drnicwilliams@gmail.com">Dr Nic</a>, <%= modified.pretty %><br>
|
data/website/version-raw.js
CHANGED
data/website/version.js
CHANGED
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
|
|
3
3
|
specification_version: 1
|
4
4
|
name: dr_nic_magic_models
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.9.
|
7
|
-
date: 2007-04-
|
6
|
+
version: 0.9.1
|
7
|
+
date: 2007-04-11 00:00:00 +02:00
|
8
8
|
summary: Dr Nic's Magic Models - Invisible validations, assocations and Active Record models themselves!
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -74,6 +74,7 @@ files:
|
|
74
74
|
- test/invisible_model_assoc_test.rb
|
75
75
|
- test/invisible_model_classes_test.rb
|
76
76
|
- test/magic_module_test.rb
|
77
|
+
- test/test_existing_model.rb
|
77
78
|
- website/index.html
|
78
79
|
- website/index.txt
|
79
80
|
- website/javascripts/rounded_corners_lite.inc.js
|
@@ -84,8 +85,8 @@ files:
|
|
84
85
|
- website/version-raw.txt
|
85
86
|
- website/version.js
|
86
87
|
- website/version.txt
|
87
|
-
test_files:
|
88
|
-
|
88
|
+
test_files:
|
89
|
+
- test/test_existing_model.rb
|
89
90
|
rdoc_options: []
|
90
91
|
|
91
92
|
extra_rdoc_files: []
|