railties 3.0.0.rc → 3.0.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +80 -75
- data/README.rdoc +1 -1
- data/guides/assets/stylesheets/main.css +14 -14
- data/guides/rails_guides.rb +20 -1
- data/guides/rails_guides/generator.rb +7 -7
- data/guides/source/2_3_release_notes.textile +5 -5
- data/guides/source/3_0_release_notes.textile +4 -3
- data/guides/source/action_controller_overview.textile +32 -17
- data/guides/source/action_view_overview.textile +44 -44
- data/guides/source/active_record_basics.textile +2 -2
- data/guides/source/active_record_querying.textile +7 -7
- data/guides/source/active_record_validations_callbacks.textile +20 -20
- data/guides/source/active_support_core_extensions.textile +370 -198
- data/guides/source/ajax_on_rails.textile +17 -17
- data/guides/source/api_documentation_guidelines.textile +3 -3
- data/guides/source/association_basics.textile +2 -2
- data/guides/source/caching_with_rails.textile +5 -5
- data/guides/source/command_line.textile +8 -8
- data/guides/source/configuring.textile +6 -6
- data/guides/source/contributing_to_rails.textile +14 -11
- data/guides/source/debugging_rails_applications.textile +8 -6
- data/guides/source/form_helpers.textile +1 -1
- data/guides/source/generators.textile +34 -30
- data/guides/source/getting_started.textile +13 -13
- data/guides/source/i18n.textile +12 -1
- data/guides/source/index.html.erb +4 -0
- data/guides/source/initialization.textile +67 -72
- data/guides/source/layout.html.erb +1 -0
- data/guides/source/layouts_and_rendering.textile +9 -9
- data/guides/source/nested_model_forms.textile +7 -7
- data/guides/source/plugins.textile +1 -1
- data/guides/source/rails_application_templates.textile +2 -2
- data/guides/source/routing.textile +27 -5
- data/guides/source/security.textile +6 -6
- data/guides/w3c_validator.rb +9 -9
- data/lib/rails/application.rb +1 -0
- data/lib/rails/application/configuration.rb +1 -1
- data/lib/rails/code_statistics.rb +4 -4
- data/lib/rails/commands.rb +1 -1
- data/lib/rails/commands/dbconsole.rb +1 -1
- data/lib/rails/commands/plugin.rb +1 -1
- data/lib/rails/commands/runner.rb +1 -1
- data/lib/rails/deprecation.rb +31 -52
- data/lib/rails/engine.rb +1 -1
- data/lib/rails/engine/configuration.rb +28 -1
- data/lib/rails/generators.rb +2 -2
- data/lib/rails/generators/actions.rb +3 -3
- data/lib/rails/generators/active_model.rb +3 -3
- data/lib/rails/generators/base.rb +1 -1
- data/lib/rails/generators/rails/app/app_generator.rb +9 -3
- data/lib/rails/generators/rails/app/templates/Gemfile +2 -2
- data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml +4 -13
- data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml +1 -1
- data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +4 -0
- data/lib/rails/generators/rails/app/templates/config/routes.rb +4 -4
- data/lib/rails/generators/rails/app/templates/public/index.html +0 -23
- data/lib/rails/generators/rails/app/templates/public/javascripts/effects.js +1 -1
- data/lib/rails/generators/rails/generator/USAGE +3 -2
- data/lib/rails/generators/rails/migration/USAGE +4 -4
- data/lib/rails/generators/rails/plugin/USAGE +1 -1
- data/lib/rails/generators/rails/resource/resource_generator.rb +2 -2
- data/lib/rails/generators/test_case.rb +1 -1
- data/lib/rails/info_controller.rb +1 -1
- data/lib/rails/plugin.rb +1 -1
- data/lib/rails/rack/log_tailer.rb +2 -5
- data/lib/rails/railtie.rb +22 -22
- data/lib/rails/script_rails_loader.rb +2 -2
- data/lib/rails/tasks/documentation.rake +5 -5
- data/lib/rails/tasks/framework.rake +1 -1
- data/lib/rails/tasks/routes.rake +23 -9
- data/lib/rails/test_unit/testing.rake +3 -2
- data/lib/rails/version.rb +1 -1
- metadata +10 -10
@@ -22,7 +22,7 @@ ol { list-style-type: decimal; }
|
|
22
22
|
dl { margin: 0 0 1.5em 0; }
|
23
23
|
dl dt { font-weight: bold; }
|
24
24
|
dd { margin-left: 1.5em;}
|
25
|
-
|
25
|
+
|
26
26
|
pre,code { margin: 1.5em 0; white-space: pre; overflow: auto; }
|
27
27
|
pre,code,tt { font: 1em 'andale mono', 'lucida console', monospace; line-height: 1.5; }
|
28
28
|
|
@@ -53,7 +53,7 @@ table {
|
|
53
53
|
background: #FFF;
|
54
54
|
border-collapse: collapse;
|
55
55
|
}
|
56
|
-
|
56
|
+
|
57
57
|
table th, table td {
|
58
58
|
padding: 0.25em 1em;
|
59
59
|
border: 1px solid #CCC;
|
@@ -76,7 +76,7 @@ body {
|
|
76
76
|
font-family: Helvetica, Arial, sans-serif;
|
77
77
|
font-size: 87.5%;
|
78
78
|
line-height: 1.5em;
|
79
|
-
background: #222;
|
79
|
+
background: #222;
|
80
80
|
color: #999;
|
81
81
|
}
|
82
82
|
|
@@ -114,7 +114,7 @@ body {
|
|
114
114
|
#mainCol {
|
115
115
|
width: 45em;
|
116
116
|
margin-left: 2em;
|
117
|
-
}
|
117
|
+
}
|
118
118
|
|
119
119
|
#subCol {
|
120
120
|
position: absolute;
|
@@ -127,7 +127,7 @@ body {
|
|
127
127
|
font-size: 0.9285em;
|
128
128
|
line-height: 1.3846em;
|
129
129
|
}
|
130
|
-
|
130
|
+
|
131
131
|
#extraCol {display: none;}
|
132
132
|
|
133
133
|
#footer {
|
@@ -180,7 +180,7 @@ a, a:link, a:visited {
|
|
180
180
|
|
181
181
|
#header .nav .index a {
|
182
182
|
background: #980905 url(../images/nav_arrow.gif) no-repeat right top;
|
183
|
-
padding-right: 1em;
|
183
|
+
padding-right: 1em;
|
184
184
|
position: relative;
|
185
185
|
z-index: 15;
|
186
186
|
padding-bottom: 0.125em;
|
@@ -246,7 +246,7 @@ h3 {
|
|
246
246
|
margin: 0.875em 0 0.2916em;
|
247
247
|
font-weight: bold;
|
248
248
|
}
|
249
|
-
|
249
|
+
|
250
250
|
h4 {
|
251
251
|
font-size: 1.2857em;
|
252
252
|
line-height: 1.2em;
|
@@ -261,7 +261,7 @@ h5 {
|
|
261
261
|
font-weight: bold;
|
262
262
|
}
|
263
263
|
|
264
|
-
h6 {
|
264
|
+
h6 {
|
265
265
|
font-size: 1em;
|
266
266
|
line-height: 1.5em;
|
267
267
|
margin: 1em 0 .5em;
|
@@ -367,7 +367,7 @@ tt {
|
|
367
367
|
|
368
368
|
div.code_container {
|
369
369
|
background: #EEE url(../images/tab_grey.gif) no-repeat left top;
|
370
|
-
padding: 0.25em 1em 0.5em 48px;
|
370
|
+
padding: 0.25em 1em 0.5em 48px;
|
371
371
|
}
|
372
372
|
|
373
373
|
code {
|
@@ -411,15 +411,15 @@ code {
|
|
411
411
|
padding: 0 0 1em;
|
412
412
|
font-size: 1.1667em;
|
413
413
|
}
|
414
|
-
|
414
|
+
|
415
415
|
/* Clearing
|
416
416
|
--------------------------------------- */
|
417
417
|
|
418
418
|
.clearfix:after {
|
419
|
-
content: ".";
|
420
|
-
display: block;
|
421
|
-
height: 0;
|
422
|
-
clear: both;
|
419
|
+
content: ".";
|
420
|
+
display: block;
|
421
|
+
height: 0;
|
422
|
+
clear: both;
|
423
423
|
visibility: hidden;
|
424
424
|
}
|
425
425
|
|
data/guides/rails_guides.rb
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
pwd = File.dirname(__FILE__)
|
2
2
|
$:.unshift pwd
|
3
3
|
|
4
|
+
# This is a predicate useful for the doc:guides task of applications.
|
5
|
+
def bundler?
|
6
|
+
# Note that rake sets the cwd to the one that contains the Rakefile
|
7
|
+
# being executed.
|
8
|
+
File.exists?('Gemfile')
|
9
|
+
end
|
10
|
+
|
4
11
|
# Loading Action Pack requires rack and erubis.
|
5
12
|
require 'rubygems'
|
6
13
|
|
@@ -20,7 +27,19 @@ begin
|
|
20
27
|
gem 'RedCloth', '>= 4.1.1'
|
21
28
|
require 'redcloth'
|
22
29
|
rescue Gem::LoadError
|
23
|
-
$stderr.puts
|
30
|
+
$stderr.puts('Generating guides requires RedCloth 4.1.1+.')
|
31
|
+
$stderr.puts(<<ERROR) if bundler?
|
32
|
+
Please add
|
33
|
+
|
34
|
+
gem 'RedCloth', '>= 4.1.1'
|
35
|
+
|
36
|
+
to the Gemfile, run
|
37
|
+
|
38
|
+
bundle install
|
39
|
+
|
40
|
+
and try again.
|
41
|
+
ERROR
|
42
|
+
|
24
43
|
exit 1
|
25
44
|
end
|
26
45
|
|
@@ -32,7 +32,7 @@
|
|
32
32
|
#
|
33
33
|
# Separate many using commas:
|
34
34
|
#
|
35
|
-
# # generates only
|
35
|
+
# # generates only
|
36
36
|
# ONLY=assoc,migrations ruby rails_guides.rb
|
37
37
|
#
|
38
38
|
# Note that if you are working on a guide generation will by default process
|
@@ -77,7 +77,7 @@ module RailsGuides
|
|
77
77
|
def initialize_dirs(output)
|
78
78
|
@guides_dir = File.join(File.dirname(__FILE__), '..')
|
79
79
|
@source_dir = File.join(@guides_dir, "source")
|
80
|
-
@output_dir = output || File.join(@guides_dir, "output")
|
80
|
+
@output_dir = output || File.join(@guides_dir, "output")
|
81
81
|
end
|
82
82
|
|
83
83
|
def create_output_dir_if_needed
|
@@ -116,7 +116,7 @@ module RailsGuides
|
|
116
116
|
def output_file_for(guide)
|
117
117
|
guide.sub(GUIDES_RE, '.html')
|
118
118
|
end
|
119
|
-
|
119
|
+
|
120
120
|
def generate?(source_file, output_file)
|
121
121
|
fin = File.join(source_dir, source_file)
|
122
122
|
fout = File.join(output_dir, output_file)
|
@@ -213,9 +213,9 @@ module RailsGuides
|
|
213
213
|
code_blocks << %{<div class="code_container"><code class="#{css_class}">#{es}</code></div>}
|
214
214
|
"\ndirty_workaround_for_notextile_#{code_blocks.size - 1}\n"
|
215
215
|
end
|
216
|
-
|
216
|
+
|
217
217
|
body = yield body
|
218
|
-
|
218
|
+
|
219
219
|
body.gsub(%r{<p>dirty_workaround_for_notextile_(\d+)</p>}) do |_|
|
220
220
|
code_blocks[$1.to_i]
|
221
221
|
end
|
@@ -225,7 +225,7 @@ module RailsGuides
|
|
225
225
|
anchors = extract_anchors(html)
|
226
226
|
check_fragment_identifiers(html, anchors)
|
227
227
|
end
|
228
|
-
|
228
|
+
|
229
229
|
def extract_anchors(html)
|
230
230
|
# Textile generates headers with IDs computed from titles.
|
231
231
|
anchors = Set.new
|
@@ -241,7 +241,7 @@ module RailsGuides
|
|
241
241
|
anchors += Set.new(html.scan(/<p\s+class="footnote"\s+id="([^"]+)/).flatten)
|
242
242
|
return anchors
|
243
243
|
end
|
244
|
-
|
244
|
+
|
245
245
|
def check_fragment_identifiers(html, anchors)
|
246
246
|
html.scan(/<a\s+href="#([^"]+)/).flatten.each do |fragment_identifier|
|
247
247
|
next if fragment_identifier == 'mainCol' # in layout, jumps to some DIV
|
@@ -53,7 +53,7 @@ The "Ruby on Rails guides":http://guides.rubyonrails.org/ project has published
|
|
53
53
|
|
54
54
|
h3. Ruby 1.9.1 Support
|
55
55
|
|
56
|
-
Rails 2.3 should pass all of its own tests whether you are running on Ruby 1.8 or the now-released Ruby 1.9.1. You should be aware, though, that moving to 1.9.1 entails checking all of the data adapters, plugins, and other code that you depend on for Ruby 1.9.1 compatibility, as well as Rails core.
|
56
|
+
Rails 2.3 should pass all of its own tests whether you are running on Ruby 1.8 or the now-released Ruby 1.9.1. You should be aware, though, that moving to 1.9.1 entails checking all of the data adapters, plugins, and other code that you depend on for Ruby 1.9.1 compatibility, as well as Rails core.
|
57
57
|
|
58
58
|
h3. Active Record
|
59
59
|
|
@@ -77,7 +77,7 @@ Turning on nested attributes enables a number of things: automatic (and atomic)
|
|
77
77
|
You can also specify requirements for any new records that are added via nested attributes using the +:reject_if+ option:
|
78
78
|
|
79
79
|
<ruby>
|
80
|
-
accepts_nested_attributes_for :author,
|
80
|
+
accepts_nested_attributes_for :author,
|
81
81
|
:reject_if => proc { |attributes| attributes['name'].blank? }
|
82
82
|
</ruby>
|
83
83
|
|
@@ -149,7 +149,7 @@ end
|
|
149
149
|
|
150
150
|
Note that you should only use this method for batch processing: for small numbers of records (less than 1000), you should just use the regular find methods with your own loop.
|
151
151
|
|
152
|
-
* More Information (at that point the convenience method was called just +each+):
|
152
|
+
* More Information (at that point the convenience method was called just +each+):
|
153
153
|
** "Rails 2.3: Batch Finding":http://afreshcup.com/2009/02/23/rails-23-batch-finding/
|
154
154
|
** "What's New in Edge Rails: Batched Find":http://ryandaigle.com/articles/2009/2/23/what-s-new-in-edge-rails-batched-find
|
155
155
|
|
@@ -449,7 +449,7 @@ returns
|
|
449
449
|
<option>joke</option>
|
450
450
|
<option>poem</option>
|
451
451
|
<option disabled=“disabled“>private</option>
|
452
|
-
</select>
|
452
|
+
</select>
|
453
453
|
</ruby>
|
454
454
|
|
455
455
|
You can also use an anonymous function to determine at runtime which options from collections will be selected and/or disabled:
|
@@ -502,7 +502,7 @@ The support for XML parsing in ActiveSupport has been made more flexible by allo
|
|
502
502
|
XmlMini.backend = 'LibXML'
|
503
503
|
</ruby>
|
504
504
|
|
505
|
-
* Lead Contributor: "Bart ten Brinke":http://www.movesonrails.com/
|
505
|
+
* Lead Contributor: "Bart ten Brinke":http://www.movesonrails.com/
|
506
506
|
* Lead Contributor: "Aaron Patterson":http://tenderlovemaking.com/
|
507
507
|
|
508
508
|
h4. Fractional seconds for TimeWithZone
|
@@ -1,6 +1,6 @@
|
|
1
1
|
h2. Ruby on Rails 3.0 Release Notes
|
2
2
|
|
3
|
-
Rails 3.0 is ponies and rainbows! It's going to cook you dinner and fold your laundry. You're going to wonder how life was ever possible before it arrived. It's the Best Version of Rails We've Ever Done!
|
3
|
+
Rails 3.0 is ponies and rainbows! It's going to cook you dinner and fold your laundry. You're going to wonder how life was ever possible before it arrived. It's the Best Version of Rails We've Ever Done!
|
4
4
|
|
5
5
|
But seriously now, it's really good stuff. There are all the good ideas brought over from when the Merb team joined the party and brought a focus on framework agnosticism, slimmer and faster internals, and a handful of tasty APIs. If you're coming to Rails 3.0 from Merb 1.x, you should recognize lots. If you're coming from Rails 2.x, you're going to love it too.
|
6
6
|
|
@@ -12,7 +12,7 @@ Even if you don't give a hoot about any of our internal cleanups, Rails 3.0 is g
|
|
12
12
|
* Unobtrusive JavaScript helpers with drivers for Prototype, jQuery, and more coming (end of inline JS)
|
13
13
|
* Explicit dependency management with Bundler
|
14
14
|
|
15
|
-
On top of all that, we've tried our best to deprecate the old APIs with nice warnings. That means that you can move your existing application to Rails 3 without immediately rewriting all your old code to the latest best practices.
|
15
|
+
On top of all that, we've tried our best to deprecate the old APIs with nice warnings. That means that you can move your existing application to Rails 3 without immediately rewriting all your old code to the latest best practices.
|
16
16
|
|
17
17
|
These release notes cover the major upgrades, but don't include every little bug fix and change. Rails 3.0 consists of almost 4,000 commits by more than 250 authors! If you want to see everything, check out the "list of commits":http://github.com/rails/rails/commits/master in the main Rails repository on GitHub.
|
18
18
|
|
@@ -66,7 +66,7 @@ To help with the upgrade process, a plugin named "Rails Upgrade":http://github.c
|
|
66
66
|
Simply install the plugin, then run +rake rails:upgrade:check+ to check your app for pieces that need to be updated (with links to information on how to update them). It also offers a task to generate a +Gemfile+ based on your current +config.gem+ calls and a task to generate a new routes file from your current one. To get the plugin, simply run the following:
|
67
67
|
|
68
68
|
<shell>
|
69
|
-
|
69
|
+
ruby script/plugin install git://github.com/rails/rails_upgrade.git
|
70
70
|
</shell>
|
71
71
|
|
72
72
|
You can see an example of how that works at "Rails Upgrade is now an Official Plugin":http://omgbloglol.com/post/364624593/rails-upgrade-is-now-an-official-plugin
|
@@ -596,3 +596,4 @@ h3. Credits
|
|
596
596
|
See the "full list of contributors to Rails":http://contributors.rubyonrails.org/ for the many people who spent many hours making Rails 3. Kudos to all of them.
|
597
597
|
|
598
598
|
Rails 3.0 Release Notes were compiled by "Mikel Lindsaar":http://lindsaar.net.
|
599
|
+
|
@@ -115,7 +115,7 @@ h4. Routing Parameters
|
|
115
115
|
The +params+ hash will always contain the +:controller+ and +:action+ keys, but you should use the methods +controller_name+ and +action_name+ instead to access these values. Any other parameters defined by the routing, such as +:id+ will also be available. As an example, consider a listing of clients where the list can show either active or inactive clients. We can add a route which captures the +:status+ parameter in a "pretty" URL:
|
116
116
|
|
117
117
|
<ruby>
|
118
|
-
map.connect "/clients/:status",
|
118
|
+
map.connect "/clients/:status",
|
119
119
|
:controller => "clients",
|
120
120
|
:action => "index",
|
121
121
|
:foo => "bar"
|
@@ -162,23 +162,38 @@ If you need a different session storage mechanism, you can change it in the +con
|
|
162
162
|
# Use the database for sessions instead of the cookie-based default,
|
163
163
|
# which shouldn't be used to store highly confidential information
|
164
164
|
# (create the session table with "rake db:sessions:create")
|
165
|
-
#
|
165
|
+
# YourApp::Application.config.session_store :active_record_store
|
166
166
|
</ruby>
|
167
167
|
|
168
|
-
Rails sets up a session key (the name of the cookie)
|
168
|
+
Rails sets up a session key (the name of the cookie) when signing the session data. These can also be changed in +config/initializers/session_store.rb+:
|
169
169
|
|
170
170
|
<ruby>
|
171
|
-
#
|
172
|
-
|
173
|
-
|
171
|
+
# Be sure to restart your server when you modify this file.
|
172
|
+
|
173
|
+
YourApp::Application.config.session_store :cookie_store, :key => '_your_app_session'
|
174
|
+
</ruby>
|
175
|
+
|
176
|
+
You can also pass a +:domain+ key and specify the domain name for the cookie:
|
177
|
+
|
178
|
+
<ruby>
|
179
|
+
# Be sure to restart your server when you modify this file.
|
180
|
+
|
181
|
+
YourApp::Application.config.session_store :cookie_store, :key => '_your_app_session', :domain => ".example.com"
|
182
|
+
</ruby>
|
183
|
+
|
184
|
+
Rails sets up (for the CookieStore) a secret key used for signing the session data. This can be changed in +config/initializers/secret_token.rb+
|
185
|
+
|
186
|
+
<ruby>
|
187
|
+
# Be sure to restart your server when you modify this file.
|
188
|
+
|
189
|
+
# Your secret key for verifying the integrity of signed cookies.
|
190
|
+
# If you change this key, all old signed cookies will become invalid!
|
191
|
+
# Make sure the secret is at least 30 characters and all random,
|
174
192
|
# no regular words or you'll be exposed to dictionary attacks.
|
175
|
-
|
176
|
-
:key => '_yourappname_session',
|
177
|
-
:secret => '4f50711b8f0f49572...'
|
178
|
-
}
|
193
|
+
YourApp::Application.config.secret_token = '49d3f3de9ed86c74b94ad6bd0...'
|
179
194
|
</ruby>
|
180
195
|
|
181
|
-
NOTE: Changing the secret when using the CookieStore will invalidate all existing sessions.
|
196
|
+
NOTE: Changing the secret when using the +CookieStore+ will invalidate all existing sessions.
|
182
197
|
|
183
198
|
h4. Accessing the Session
|
184
199
|
|
@@ -281,7 +296,7 @@ class MainController < ApplicationController
|
|
281
296
|
# Will persist all flash values.
|
282
297
|
flash.keep
|
283
298
|
|
284
|
-
# You can also use a key to keep only some kind of value.
|
299
|
+
# You can also use a key to keep only some kind of value.
|
285
300
|
# flash.keep(:notice)
|
286
301
|
redirect_to users_url
|
287
302
|
end
|
@@ -354,14 +369,14 @@ class UsersController < ApplicationController
|
|
354
369
|
end
|
355
370
|
</ruby>
|
356
371
|
|
357
|
-
Notice that in the above case code is <tt>render :xml => @users</tt> and not <tt>render :xml => @users.to_xml</tt>. That is because if the input is not string then rails automatically invokes +to_xml+ .
|
372
|
+
Notice that in the above case code is <tt>render :xml => @users</tt> and not <tt>render :xml => @users.to_xml</tt>. That is because if the input is not string then rails automatically invokes +to_xml+ .
|
358
373
|
|
359
374
|
|
360
375
|
h3. Filters
|
361
376
|
|
362
|
-
Filters are methods that are run before, after or "around" a controller action.
|
377
|
+
Filters are methods that are run before, after or "around" a controller action.
|
363
378
|
|
364
|
-
Filters are inherited, so if you set a filter on +ApplicationController+, it will be run on every controller in your application.
|
379
|
+
Filters are inherited, so if you set a filter on +ApplicationController+, it will be run on every controller in your application.
|
365
380
|
|
366
381
|
Before filters may halt the request cycle. A common before filter is one which requires that a user is logged in for an action to be run. You can define the filter method this way:
|
367
382
|
|
@@ -521,7 +536,7 @@ You will see how the token gets added as a hidden field:
|
|
521
536
|
|
522
537
|
<html>
|
523
538
|
<form action="/users/1" method="post">
|
524
|
-
<input type="hidden"
|
539
|
+
<input type="hidden"
|
525
540
|
value="67250ab105eb5ad10851c00a5621854a23af5489"
|
526
541
|
name="authenticity_token"/>
|
527
542
|
<!-- fields -->
|
@@ -644,7 +659,7 @@ class ClientsController < ApplicationController
|
|
644
659
|
# returns it. The user will get the PDF as a file download.
|
645
660
|
def download_pdf
|
646
661
|
client = Client.find(params[:id])
|
647
|
-
send_data generate_pdf(client),
|
662
|
+
send_data generate_pdf(client),
|
648
663
|
:filename => "#{client.name}.pdf",
|
649
664
|
:type => "application/pdf"
|
650
665
|
end
|
@@ -12,9 +12,9 @@ endprologue.
|
|
12
12
|
|
13
13
|
h3. What is Action View?
|
14
14
|
|
15
|
-
Action View and Action Controller are the two major components of Action Pack. In Rails, web requests are handled by Action Pack, which splits the work into a controller part (performing the logic) and a view part (rendering a template). Typically, Action Controller will be concerned with communicating with the database and performing CRUD actions where necessary. Action View is then responsible for compiling the response.
|
15
|
+
Action View and Action Controller are the two major components of Action Pack. In Rails, web requests are handled by Action Pack, which splits the work into a controller part (performing the logic) and a view part (rendering a template). Typically, Action Controller will be concerned with communicating with the database and performing CRUD actions where necessary. Action View is then responsible for compiling the response.
|
16
16
|
|
17
|
-
Action View templates are written using embedded Ruby in tags mingled with HTML. To avoid cluttering the templates with boilerplate code, a number of helper classes provide common behavior for forms, dates, and strings. It's also easy to add new helpers to your application as it evolves.
|
17
|
+
Action View templates are written using embedded Ruby in tags mingled with HTML. To avoid cluttering the templates with boilerplate code, a number of helper classes provide common behavior for forms, dates, and strings. It's also easy to add new helpers to your application as it evolves.
|
18
18
|
|
19
19
|
Note: Some features of Action View are tied to Active Record, but that doesn't mean that Action View depends on Active Record. Action View is an independent package that can be used with any sort of backend.
|
20
20
|
|
@@ -24,7 +24,7 @@ TODO...
|
|
24
24
|
|
25
25
|
h3. Using Action View outside of Rails
|
26
26
|
|
27
|
-
Action View works well with Action Record, but it can also be used with other Ruby tools. We can demonstrate this by creating a small "Rack":http://rack.rubyforge.org/ application that includes Action View functionality. This may be useful, for example, if you'd like access to Action View's helpers in a Rack application.
|
27
|
+
Action View works well with Action Record, but it can also be used with other Ruby tools. We can demonstrate this by creating a small "Rack":http://rack.rubyforge.org/ application that includes Action View functionality. This may be useful, for example, if you'd like access to Action View's helpers in a Rack application.
|
28
28
|
|
29
29
|
Let's start by ensuring that you have the Action Pack and Rack gems installed:
|
30
30
|
|
@@ -55,11 +55,11 @@ We can see this all come together by starting up the application and then visiti
|
|
55
55
|
ruby hello_world.rb
|
56
56
|
</shell>
|
57
57
|
|
58
|
-
TODO needs a screenshot? I have one - not sure where to put it.
|
58
|
+
TODO needs a screenshot? I have one - not sure where to put it.
|
59
59
|
|
60
|
-
Notice how 'hello world' has been converted into 'Hello World' by the +titleize+ helper method.
|
60
|
+
Notice how 'hello world' has been converted into 'Hello World' by the +titleize+ helper method.
|
61
61
|
|
62
|
-
Action View can also be used with "Sinatra":http://www.sinatrarb.com/ in the same way.
|
62
|
+
Action View can also be used with "Sinatra":http://www.sinatrarb.com/ in the same way.
|
63
63
|
|
64
64
|
Let's start by ensuring that you have the Action Pack and Sinatra gems installed:
|
65
65
|
|
@@ -90,7 +90,7 @@ ruby hello_world.rb
|
|
90
90
|
|
91
91
|
Once the application is running, you can see Sinatra and Action View working together by visiting +http://localhost:4567/+
|
92
92
|
|
93
|
-
TODO needs a screenshot? I have one - not sure where to put it.
|
93
|
+
TODO needs a screenshot? I have one - not sure where to put it.
|
94
94
|
|
95
95
|
h3. Templates, Partials and Layouts
|
96
96
|
|
@@ -172,7 +172,7 @@ TODO...
|
|
172
172
|
|
173
173
|
h3. Overview of all the helpers provided by Action View
|
174
174
|
|
175
|
-
The following is only a brief overview summary of the helpers available in Action View. It's recommended that you review the API Documentation, which covers all of the helpers in more detail, but this should serve as a good starting point.
|
175
|
+
The following is only a brief overview summary of the helpers available in Action View. It's recommended that you review the API Documentation, which covers all of the helpers in more detail, but this should serve as a good starting point.
|
176
176
|
|
177
177
|
h4. ActiveRecordHelper
|
178
178
|
|
@@ -196,7 +196,7 @@ error_messages_for "post"
|
|
196
196
|
|
197
197
|
h5. form
|
198
198
|
|
199
|
-
Returns a form with inputs for all attributes of the specified Active Record object. For example, let's say we have a +@post+ with attributes named +title+ of type +String+ and +body+ of type +Text+. Calling +form+ would produce a form to creating a new post with inputs for those attributes.
|
199
|
+
Returns a form with inputs for all attributes of the specified Active Record object. For example, let's say we have a +@post+ with attributes named +title+ of type +String+ and +body+ of type +Text+. Calling +form+ would produce a form to creating a new post with inputs for those attributes.
|
200
200
|
|
201
201
|
<ruby>
|
202
202
|
form("post")
|
@@ -220,24 +220,24 @@ Typically, +form_for+ is used instead of +form+ because it doesn't automatically
|
|
220
220
|
|
221
221
|
h5. input
|
222
222
|
|
223
|
-
Returns a default input tag for the type of object returned by the method.
|
223
|
+
Returns a default input tag for the type of object returned by the method.
|
224
224
|
|
225
225
|
For example, if +@post+ has an attribute +title+ mapped to a +String+ column that holds "Hello World":
|
226
226
|
|
227
227
|
<ruby>
|
228
|
-
input("post", "title") # =>
|
228
|
+
input("post", "title") # =>
|
229
229
|
<input id="post_title" name="post[title]" size="30" type="text" value="Hello World" />
|
230
230
|
</ruby>
|
231
231
|
|
232
232
|
h4. AssetTagHelper
|
233
233
|
|
234
|
-
This module provides methods for generating HTML that links views to assets such as images, javascripts, stylesheets, and feeds.
|
234
|
+
This module provides methods for generating HTML that links views to assets such as images, javascripts, stylesheets, and feeds.
|
235
235
|
|
236
236
|
By default, Rails links to these assets on the current host in the public folder, but you can direct Rails to link to assets from a dedicated assets server by setting +ActionController::Base.asset_host+ in your +config/environment.rb+. For example, let's say your asset host is +assets.example.com+:
|
237
237
|
|
238
238
|
<ruby>
|
239
239
|
ActionController::Base.asset_host = "assets.example.com"
|
240
|
-
image_tag("rails.png") # => <img src="http://assets.example.com/images/rails.png" alt="Rails" />
|
240
|
+
image_tag("rails.png") # => <img src="http://assets.example.com/images/rails.png" alt="Rails" />
|
241
241
|
</ruby>
|
242
242
|
|
243
243
|
h5. register_javascript_expansion
|
@@ -301,10 +301,10 @@ Returns an html script tag for each of the sources provided. You can pass in the
|
|
301
301
|
|
302
302
|
<ruby>
|
303
303
|
javascript_include_tag "common" # =>
|
304
|
-
<script type="text/javascript" src="/javascripts/common.js"></script>
|
304
|
+
<script type="text/javascript" src="/javascripts/common.js"></script>
|
305
305
|
</ruby>
|
306
306
|
|
307
|
-
To include the Prototype and Scriptaculous javascript libraries in your application, pass +:defaults+ as the source. When using +:defaults+, if an +application.js+ file exists in your +public/javascripts+ directory, it will be included as well.
|
307
|
+
To include the Prototype and Scriptaculous javascript libraries in your application, pass +:defaults+ as the source. When using +:defaults+, if an +application.js+ file exists in your +public/javascripts+ directory, it will be included as well.
|
308
308
|
|
309
309
|
<ruby>
|
310
310
|
javascript_include_tag :defaults
|
@@ -319,8 +319,8 @@ javascript_include_tag :all
|
|
319
319
|
You can also cache multiple javascripts into one file, which requires less HTTP connections to download and can better be compressed by gzip (leading to faster transfers). Caching will only happen if +ActionController::Base.perform_caching+ is set to true (which is the case by default for the Rails production environment, but not for the development environment).
|
320
320
|
|
321
321
|
<ruby>
|
322
|
-
javascript_include_tag :all, :cache => true # =>
|
323
|
-
<script type="text/javascript" src="/javascripts/all.js"></script>
|
322
|
+
javascript_include_tag :all, :cache => true # =>
|
323
|
+
<script type="text/javascript" src="/javascripts/all.js"></script>
|
324
324
|
</ruby>
|
325
325
|
|
326
326
|
h5. javascript_path
|
@@ -333,7 +333,7 @@ javascript_path "common" # => /javascripts/common.js
|
|
333
333
|
|
334
334
|
h5. stylesheet_link_tag
|
335
335
|
|
336
|
-
Returns a stylesheet link tag for the sources specified as arguments. If you don't specify an extension, +.css+ will be appended automatically.
|
336
|
+
Returns a stylesheet link tag for the sources specified as arguments. If you don't specify an extension, +.css+ will be appended automatically.
|
337
337
|
|
338
338
|
<ruby>
|
339
339
|
stylesheet_link_tag "application" # =>
|
@@ -346,7 +346,7 @@ You can also include all styles in the stylesheet directory using :all as the so
|
|
346
346
|
stylesheet_link_tag :all
|
347
347
|
</ruby>
|
348
348
|
|
349
|
-
You can also cache multiple stylesheets into one file, which requires less HTTP connections and can better be compressed by gzip (leading to faster transfers). Caching will only happen if ActionController::Base.perform_caching is set to true (which is the case by default for the Rails production environment, but not for the development environment).
|
349
|
+
You can also cache multiple stylesheets into one file, which requires less HTTP connections and can better be compressed by gzip (leading to faster transfers). Caching will only happen if ActionController::Base.perform_caching is set to true (which is the case by default for the Rails production environment, but not for the development environment).
|
350
350
|
|
351
351
|
<ruby>
|
352
352
|
stylesheet_link_tag :all, :cache => true
|
@@ -415,7 +415,7 @@ Allows you to measure the execution time of a block in a template and records th
|
|
415
415
|
<ruby>
|
416
416
|
<% benchmark "Process data files" do %>
|
417
417
|
<%= expensive_files_operation %>
|
418
|
-
<% end %>
|
418
|
+
<% end %>
|
419
419
|
</ruby>
|
420
420
|
|
421
421
|
This would add something like "Process data files (0.34523)" to the log, which you can then use to compare timings when optimizing your code.
|
@@ -455,7 +455,7 @@ The captured variable can then be used anywhere else.
|
|
455
455
|
<%= @greeting %>
|
456
456
|
</body>
|
457
457
|
</html>
|
458
|
-
</ruby>
|
458
|
+
</ruby>
|
459
459
|
|
460
460
|
h5. content_for
|
461
461
|
|
@@ -484,7 +484,7 @@ For example, let's say we have a standard application layout, but also a special
|
|
484
484
|
|
485
485
|
<% content_for :special_script do %>
|
486
486
|
<script type="text/javascript">alert('Hello!')</script>
|
487
|
-
<% end %>
|
487
|
+
<% end %>
|
488
488
|
</ruby>
|
489
489
|
|
490
490
|
h4. DateHelper
|
@@ -523,7 +523,7 @@ Returns a set of html select-tags (one for year, month, and day) pre-selected wi
|
|
523
523
|
select_date(Time.today + 6.days)
|
524
524
|
|
525
525
|
# Generates a date select that defaults to today (no specified date)
|
526
|
-
select_date()
|
526
|
+
select_date()
|
527
527
|
</ruby>
|
528
528
|
|
529
529
|
h5. select_datetime
|
@@ -535,7 +535,7 @@ Returns a set of html select-tags (one for year, month, day, hour, and minute) p
|
|
535
535
|
select_datetime(Time.now + 4.days)
|
536
536
|
|
537
537
|
# Generates a datetime select that defaults to today (no specified datetime)
|
538
|
-
select_datetime()
|
538
|
+
select_datetime()
|
539
539
|
</ruby>
|
540
540
|
|
541
541
|
h5. select_day
|
@@ -583,7 +583,7 @@ Returns a select tag with options for each of the seconds 0 through 59 with the
|
|
583
583
|
|
584
584
|
<ruby>
|
585
585
|
# Generates a select field for seconds that defaults to the seconds for the time provided
|
586
|
-
select_second(Time.now + 16.minutes)
|
586
|
+
select_second(Time.now + 16.minutes)
|
587
587
|
</ruby>
|
588
588
|
|
589
589
|
h5. select_time
|
@@ -592,7 +592,7 @@ Returns a set of html select-tags (one for hour and minute).
|
|
592
592
|
|
593
593
|
<ruby>
|
594
594
|
# Generates a time select that defaults to the time provided
|
595
|
-
select_time(Time.now)
|
595
|
+
select_time(Time.now)
|
596
596
|
</ruby>
|
597
597
|
|
598
598
|
h5. select_year
|
@@ -621,7 +621,7 @@ Returns a set of select tags (one for hour, minute and optionally second) pre-se
|
|
621
621
|
|
622
622
|
<ruby>
|
623
623
|
# Creates a time select tag that, when POSTed, will be stored in the order variable in the submitted attribute
|
624
|
-
time_select("order", "submitted")
|
624
|
+
time_select("order", "submitted")
|
625
625
|
</ruby>
|
626
626
|
|
627
627
|
h4. DebugHelper
|
@@ -711,7 +711,7 @@ Returns an file upload input tag tailored for accessing a specified attribute.
|
|
711
711
|
|
712
712
|
<ruby>
|
713
713
|
file_field(:user, :avatar)
|
714
|
-
# => <input type="file" id="user_avatar" name="user[avatar]" />
|
714
|
+
# => <input type="file" id="user_avatar" name="user[avatar]" />
|
715
715
|
</ruby>
|
716
716
|
|
717
717
|
h5. form_for
|
@@ -733,7 +733,7 @@ Returns a hidden input tag tailored for accessing a specified attribute.
|
|
733
733
|
|
734
734
|
<ruby>
|
735
735
|
hidden_field(:user, :token)
|
736
|
-
# => <input type="hidden" id="user_token" name="user[token]" value="#{@user.token}" />
|
736
|
+
# => <input type="hidden" id="user_token" name="user[token]" value="#{@user.token}" />
|
737
737
|
</ruby>
|
738
738
|
|
739
739
|
h5. label
|
@@ -751,7 +751,7 @@ Returns an input tag of the "password" type tailored for accessing a specified a
|
|
751
751
|
|
752
752
|
<ruby>
|
753
753
|
password_field(:login, :pass)
|
754
|
-
# => <input type="text" id="login_pass" name="login[pass]" value="#{@login.pass}" />
|
754
|
+
# => <input type="text" id="login_pass" name="login[pass]" value="#{@login.pass}" />
|
755
755
|
</ruby>
|
756
756
|
|
757
757
|
h5. radio_button
|
@@ -854,7 +854,7 @@ end
|
|
854
854
|
|
855
855
|
Sample usage:
|
856
856
|
|
857
|
-
<ruby>
|
857
|
+
<ruby>
|
858
858
|
option_groups_from_collection_for_select(@continents, :countries, :name, :id, :name, 3)
|
859
859
|
</ruby>
|
860
860
|
|
@@ -880,7 +880,7 @@ Note: Only the +optgroup+ and +option+ tags are returned, so you still have to w
|
|
880
880
|
|
881
881
|
h5. options_for_select
|
882
882
|
|
883
|
-
Accepts a container (hash, array, enumerable, your type) and returns a string of option tags.
|
883
|
+
Accepts a container (hash, array, enumerable, your type) and returns a string of option tags.
|
884
884
|
|
885
885
|
<ruby>
|
886
886
|
options_for_select([ "VISA", "MasterCard" ])
|
@@ -902,7 +902,7 @@ For example, imagine a loop iterating over each person in @project.people to gen
|
|
902
902
|
<ruby>
|
903
903
|
options_from_collection_for_select(@project.people, "id", "name")
|
904
904
|
# => <option value="#{person.id}">#{person.name}</option>
|
905
|
-
</ruby>
|
905
|
+
</ruby>
|
906
906
|
|
907
907
|
Note: Only the +option+ tags are returned, you have to wrap this call in a regular HTML +select+ tag.
|
908
908
|
|
@@ -949,7 +949,7 @@ Creates a check box form input tag.
|
|
949
949
|
|
950
950
|
<ruby>
|
951
951
|
check_box_tag 'accept'
|
952
|
-
# => <input id="accept" name="accept" type="checkbox" value="1" />
|
952
|
+
# => <input id="accept" name="accept" type="checkbox" value="1" />
|
953
953
|
</ruby>
|
954
954
|
|
955
955
|
h5. field_set_tag
|
@@ -965,7 +965,7 @@ Creates a field set for grouping HTML form elements.
|
|
965
965
|
|
966
966
|
h5. file_field_tag
|
967
967
|
|
968
|
-
Creates a file upload field.
|
968
|
+
Creates a file upload field.
|
969
969
|
|
970
970
|
If you are using file uploads then you will also need to set the multipart option for the form tag:
|
971
971
|
|
@@ -1173,7 +1173,7 @@ number_with_delimiter(12345678) # => 12,345,678
|
|
1173
1173
|
|
1174
1174
|
h5. number_with_precision
|
1175
1175
|
|
1176
|
-
Formats a number with the specified level of +precision+, which defaults to 3.
|
1176
|
+
Formats a number with the specified level of +precision+, which defaults to 3.
|
1177
1177
|
|
1178
1178
|
<ruby>
|
1179
1179
|
number_with_precision(111.2345) # => 111.235
|
@@ -1207,7 +1207,7 @@ form_remote_tag :html => { :action => url_for(:controller => "some", :action =>
|
|
1207
1207
|
would generate the following:
|
1208
1208
|
|
1209
1209
|
<html>
|
1210
|
-
<form action="/some/place" method="post" onsubmit="new Ajax.Request('',
|
1210
|
+
<form action="/some/place" method="post" onsubmit="new Ajax.Request('',
|
1211
1211
|
{asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">
|
1212
1212
|
</html>
|
1213
1213
|
|
@@ -1293,7 +1293,7 @@ Yields a JavaScriptGenerator and returns the generated JavaScript code. Use this
|
|
1293
1293
|
<ruby>
|
1294
1294
|
update_page do |page|
|
1295
1295
|
page.hide 'spinner'
|
1296
|
-
end
|
1296
|
+
end
|
1297
1297
|
</ruby>
|
1298
1298
|
|
1299
1299
|
h5. update_page_tag
|
@@ -1395,7 +1395,7 @@ h5. remove
|
|
1395
1395
|
Removes the DOM elements with the given ids from the page.
|
1396
1396
|
|
1397
1397
|
<ruby>
|
1398
|
-
page.remove 'person_23', 'person_9', 'person_2'
|
1398
|
+
page.remove 'person_23', 'person_9', 'person_2'
|
1399
1399
|
</ruby>
|
1400
1400
|
|
1401
1401
|
h5. replace
|
@@ -1420,7 +1420,7 @@ Returns a collection reference by finding it through a CSS pattern in the DOM.
|
|
1420
1420
|
|
1421
1421
|
<ruby>
|
1422
1422
|
page.select('p.welcome b').first.hide # => $$('p.welcome b').first().hide();
|
1423
|
-
</ruby>
|
1423
|
+
</ruby>
|
1424
1424
|
|
1425
1425
|
h5. show
|
1426
1426
|
|
@@ -1440,7 +1440,7 @@ Toggles the visibility of the DOM elements with the given ids. Example:
|
|
1440
1440
|
|
1441
1441
|
<ruby>
|
1442
1442
|
page.toggle 'person_14', 'person_12', 'person_23' # Hides the elements
|
1443
|
-
page.toggle 'person_14', 'person_12', 'person_23' # Shows the previously hidden elements
|
1443
|
+
page.toggle 'person_14', 'person_12', 'person_23' # Shows the previously hidden elements
|
1444
1444
|
</ruby>
|
1445
1445
|
|
1446
1446
|
h5. visual_effect
|
@@ -1455,11 +1455,11 @@ h3. Localized Views
|
|
1455
1455
|
|
1456
1456
|
Action View has the ability render different templates depending on the current locale.
|
1457
1457
|
|
1458
|
-
For example, suppose you have a Posts controller with a show action. By default, calling this action will render +app/views/posts/show.html.erb+. But if you set +I18n.locale = :de+, then +app/views/posts/show.de.html.erb+ will be rendered instead. If the localized template isn't present, the undecorated version will be used. This means you're not required to provide localized views for all cases, but they will be preferred and used if available.
|
1458
|
+
For example, suppose you have a Posts controller with a show action. By default, calling this action will render +app/views/posts/show.html.erb+. But if you set +I18n.locale = :de+, then +app/views/posts/show.de.html.erb+ will be rendered instead. If the localized template isn't present, the undecorated version will be used. This means you're not required to provide localized views for all cases, but they will be preferred and used if available.
|
1459
1459
|
|
1460
1460
|
You can use the same technique to localize the rescue files in your public directory. For example, setting +I18n.locale = :de+ and creating +public/500.de.html+ and +public/404.de.html+ would allow you to have localized rescue pages.
|
1461
1461
|
|
1462
|
-
Since Rails doesn't restrict the symbols that you use to set I18n.locale, you can leverage this system to display different content depending on anything you like. For example, suppose you have some "expert" users that should see different pages from "normal" users. You could add the following to +app/controllers/application.rb+:
|
1462
|
+
Since Rails doesn't restrict the symbols that you use to set I18n.locale, you can leverage this system to display different content depending on anything you like. For example, suppose you have some "expert" users that should see different pages from "normal" users. You could add the following to +app/controllers/application.rb+:
|
1463
1463
|
|
1464
1464
|
<ruby>
|
1465
1465
|
before_filter :set_expert_locale
|
@@ -1471,7 +1471,7 @@ end
|
|
1471
1471
|
|
1472
1472
|
Then you could create special views like +app/views/posts/show.expert.html.erb+ that would only be displayed to expert users.
|
1473
1473
|
|
1474
|
-
You can read more about the Rails Internationalization (I18n) API "here":i18n.html.
|
1474
|
+
You can read more about the Rails Internationalization (I18n) API "here":i18n.html.
|
1475
1475
|
|
1476
1476
|
h3. Changelog
|
1477
1477
|
|