railties 3.1.0.rc4 → 3.1.0.rc5
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +7 -9
- data/bin/rails +2 -0
- data/guides/assets/images/rails_welcome.png +0 -0
- data/guides/rails_guides/generator.rb +1 -1
- data/guides/rails_guides/textile_extensions.rb +18 -17
- data/guides/source/3_0_release_notes.textile +21 -21
- data/guides/source/action_controller_overview.textile +1 -1
- data/guides/source/action_mailer_basics.textile +27 -6
- data/guides/source/action_view_overview.textile +6 -6
- data/guides/source/active_record_querying.textile +77 -7
- data/guides/source/active_record_validations_callbacks.textile +78 -81
- data/guides/source/active_support_core_extensions.textile +87 -31
- data/guides/source/ajax_on_rails.textile +1 -1
- data/guides/source/api_documentation_guidelines.textile +12 -8
- data/guides/source/asset_pipeline.textile +416 -0
- data/guides/source/association_basics.textile +2 -4
- data/guides/source/caching_with_rails.textile +7 -6
- data/guides/source/command_line.textile +78 -116
- data/guides/source/configuring.textile +34 -17
- data/guides/source/contribute.textile +1 -1
- data/guides/source/contributing_to_ruby_on_rails.textile +3 -3
- data/guides/source/debugging_rails_applications.textile +2 -2
- data/guides/source/form_helpers.textile +40 -51
- data/guides/source/getting_started.textile +641 -197
- data/guides/source/initialization.textile +4 -4
- data/guides/source/layouts_and_rendering.textile +2 -2
- data/guides/source/migrations.textile +114 -32
- data/guides/source/nested_model_forms.textile +6 -6
- data/guides/source/performance_testing.textile +6 -6
- data/guides/source/plugins.textile +23 -22
- data/guides/source/rails_application_templates.textile +8 -14
- data/guides/source/routing.textile +57 -51
- data/guides/source/ruby_on_rails_guides_guidelines.textile +3 -3
- data/guides/source/security.textile +10 -10
- data/guides/source/testing.textile +1 -1
- data/lib/rails.rb +27 -1
- data/lib/rails/all.rb +1 -0
- data/lib/rails/application.rb +4 -10
- data/lib/rails/application/configuration.rb +3 -12
- data/lib/rails/application/railties.rb +1 -1
- data/lib/rails/engine.rb +53 -42
- data/lib/rails/generators.rb +1 -1
- data/lib/rails/generators/app_base.rb +36 -15
- data/lib/rails/generators/generated_attribute.rb +1 -1
- data/lib/rails/generators/js/assets/assets_generator.rb +13 -0
- data/lib/rails/generators/js/assets/templates/javascript.js +2 -0
- data/lib/rails/generators/rails/app/app_generator.rb +3 -1
- data/lib/rails/generators/rails/app/templates/Gemfile +11 -7
- data/lib/rails/generators/rails/app/templates/config/application.rb +7 -3
- data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml +62 -0
- data/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml +3 -3
- data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml +3 -12
- data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml +3 -3
- data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +0 -3
- data/lib/rails/generators/rails/assets/assets_generator.rb +2 -9
- data/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +12 -10
- data/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec +5 -2
- data/lib/rails/generators/rails/plugin_new/templates/Gemfile +6 -3
- data/lib/rails/generators/rails/plugin_new/templates/Rakefile +5 -1
- data/lib/rails/generators/rails/plugin_new/templates/app/views/layouts/application.html.erb.tt +14 -0
- data/lib/rails/generators/rails/plugin_new/templates/rails/application.rb +5 -3
- data/lib/rails/info.rb +4 -0
- data/lib/rails/paths.rb +5 -5
- data/lib/rails/railtie.rb +4 -4
- data/lib/rails/tasks.rb +0 -1
- data/lib/rails/tasks/documentation.rake +3 -3
- data/lib/rails/tasks/engine.rake +2 -0
- data/lib/rails/tasks/framework.rake +3 -3
- data/lib/rails/tasks/tmp.rake +1 -1
- data/lib/rails/test_unit/testing.rake +2 -2
- data/lib/rails/version.rb +1 -1
- metadata +19 -33
- data/lib/rails/generators/rails/assets/templates/javascript.js.coffee +0 -3
- data/lib/rails/tasks/assets.rake +0 -21
@@ -14,7 +14,7 @@ h3. How to Contribute?
|
|
14
14
|
* Sample format : "Active Record Associations":https://github.com/lifo/docrails/blob/3e56a3832415476fdd1cb963980d0ae390ac1ed3/railties/guides/source/association_basics.textile.
|
15
15
|
* Sample output : "Active Record Associations":association_basics.html.
|
16
16
|
* You can build the Guides during testing by running +bundle exec rake generate_guides+ in the +railties+ directory.
|
17
|
-
* You're encouraged to validate XHTML for the generated guides before
|
17
|
+
* You're encouraged to validate XHTML for the generated guides before committing your changes by running +bundle exec rake validate_guides+ in the +railties+ directory.
|
18
18
|
* Edge guides "can be consulted online":http://edgeguides.rubyonrails.org/. That website is generated periodically from docrails.
|
19
19
|
|
20
20
|
h3. What to Contribute?
|
@@ -309,7 +309,7 @@ Rails follows a simple set of coding style conventions.
|
|
309
309
|
* a = b and not a=b.
|
310
310
|
* Follow the conventions you see used in the source already.
|
311
311
|
|
312
|
-
These are some guidelines and please use your best
|
312
|
+
These are some guidelines and please use your best judgment in using them.
|
313
313
|
|
314
314
|
h4. Sanity Check
|
315
315
|
|
@@ -350,7 +350,7 @@ Navigate to the Rails "GitHub repository":https://github.com/rails/rails and pre
|
|
350
350
|
Add the new remote to your local repository on your local machine:
|
351
351
|
|
352
352
|
<shell>
|
353
|
-
$ git remote add mine
|
353
|
+
$ git remote add mine git@github.com:<your user name>/rails.git
|
354
354
|
</shell>
|
355
355
|
|
356
356
|
Push to your remote:
|
@@ -361,7 +361,7 @@ $ git push mine my_new_branch
|
|
361
361
|
|
362
362
|
h4. Issue a Pull Request
|
363
363
|
|
364
|
-
Navigate to the Rails repository you just pushed to (e.g. https://github.com
|
364
|
+
Navigate to the Rails repository you just pushed to (e.g. https://github.com/your-user-name/rails) and press "Pull Request" in the upper right hand corner.
|
365
365
|
|
366
366
|
Write your branch name in branch field (is filled with master by default) and press "Update Commit Range"
|
367
367
|
|
@@ -127,7 +127,7 @@ When something is logged it's printed into the corresponding log if the log leve
|
|
127
127
|
The available log levels are: +:debug+, +:info+, +:warn+, +:error+, and +:fatal+, corresponding to the log level numbers from 0 up to 4 respectively. To change the default log level, use
|
128
128
|
|
129
129
|
<ruby>
|
130
|
-
config.log_level =
|
130
|
+
config.log_level = :warn # In any environment initializer, or
|
131
131
|
Rails.logger.level = 0 # at any time
|
132
132
|
</ruby>
|
133
133
|
|
@@ -493,7 +493,7 @@ TIP: You can use ruby-debug while using +rails console+. Just remember to +requi
|
|
493
493
|
|
494
494
|
<shell>
|
495
495
|
$ rails console
|
496
|
-
Loading development environment (Rails
|
496
|
+
Loading development environment (Rails 3.1.0)
|
497
497
|
>> require "ruby-debug"
|
498
498
|
=> []
|
499
499
|
>> author = Author.first
|
@@ -27,9 +27,7 @@ The most basic form helper is +form_tag+.
|
|
27
27
|
<% end %>
|
28
28
|
</erb>
|
29
29
|
|
30
|
-
When called without arguments like this, it creates a form
|
31
|
-
|
32
|
-
Sample output from +form_tag+:
|
30
|
+
When called without arguments like this, it creates a +<form>+ tag which, when submitted, will POST to the current page. For instance, assuming the current page is +/home/index+, the generated HTML will look like this (some line breaks added for readability):
|
33
31
|
|
34
32
|
<html>
|
35
33
|
<form accept-charset="UTF-8" action="/home/index" method="post">
|
@@ -41,36 +39,30 @@ Sample output from +form_tag+:
|
|
41
39
|
</form>
|
42
40
|
</html>
|
43
41
|
|
44
|
-
|
42
|
+
Now, you'll notice that the HTML contains something extra: a +div+ element with two hidden input elements inside. This div is important, because the form cannot be successfully submitted without it. The first input element with name +utf8+ enforces browsers to properly respect your form's character encoding and is generated for all forms whether their actions are "GET" or "POST". The second input element with name +authenticity_token+ is a security feature of Rails called *cross-site request forgery protection*, and form helpers generate it for every non-GET form (provided that this security feature is enabled). You can read more about this in the "Security Guide":./security.html#_cross_site_reference_forgery_csrf.
|
45
43
|
|
46
|
-
NOTE: Throughout this guide,
|
44
|
+
NOTE: Throughout this guide, the +div+ with the hidden input elements will be excluded from code samples for brevity.
|
47
45
|
|
48
46
|
h4. A Generic Search Form
|
49
47
|
|
50
|
-
|
48
|
+
One of the most basic forms you see on the web is a search form. This form contains:
|
51
49
|
|
52
50
|
# a form element with "GET" method,
|
53
51
|
# a label for the input,
|
54
52
|
# a text input element, and
|
55
53
|
# a submit element.
|
56
54
|
|
57
|
-
|
58
|
-
|
59
|
-
To create this form you will use +form_tag+, +label_tag+, +text_field_tag+, and +submit_tag+, respectively.
|
60
|
-
|
61
|
-
A basic search form
|
55
|
+
To create this form you will use +form_tag+, +label_tag+, +text_field_tag+, and +submit_tag+, respectively. Like this:
|
62
56
|
|
63
57
|
<erb>
|
64
|
-
<%= form_tag(
|
58
|
+
<%= form_tag("/search", :method => "get") do %>
|
65
59
|
<%= label_tag(:q, "Search for:") %>
|
66
60
|
<%= text_field_tag(:q) %>
|
67
61
|
<%= submit_tag("Search") %>
|
68
62
|
<% end %>
|
69
63
|
</erb>
|
70
64
|
|
71
|
-
|
72
|
-
|
73
|
-
The above view code will result in the following markup:
|
65
|
+
This will generate the following HTML:
|
74
66
|
|
75
67
|
<html>
|
76
68
|
<form accept-charset="UTF-8" action="/search" method="get">
|
@@ -80,47 +72,35 @@ The above view code will result in the following markup:
|
|
80
72
|
</form>
|
81
73
|
</html>
|
82
74
|
|
75
|
+
TIP: For every form input, an ID attribute is generated from its name ("q" in the example). These IDs can be very useful for CSS styling or manipulation of form controls with JavaScript.
|
76
|
+
|
83
77
|
Besides +text_field_tag+ and +submit_tag+, there is a similar helper for _every_ form control in HTML.
|
84
78
|
|
85
|
-
|
79
|
+
IMPORTANT: Always use "GET" as the method for search forms. This allows users to bookmark a specific search and get back to it. More generally Rails encourages you to use the right HTTP verb for an action.
|
86
80
|
|
87
81
|
h4. Multiple Hashes in Form Helper Calls
|
88
82
|
|
89
|
-
|
83
|
+
The +form_tag+ helper accepts 2 arguments: the path for the action and an options hash. This hash specifies the method of form submission and HTML options such as the form element's class.
|
90
84
|
|
91
|
-
As with the +link_to+ helper, the path argument doesn't have to be given a string
|
85
|
+
As with the +link_to+ helper, the path argument doesn't have to be given a string; it can be a hash of URL parameters recognizable by Rails' routing mechanism, which will turn the hash into a valid URL. However, since both arguments to +form_tag+ are hashes, you can easily run into a problem if you would like to specify both. For instance, let's say you write this:
|
92
86
|
|
93
87
|
<ruby>
|
94
88
|
form_tag(:controller => "people", :action => "search", :method => "get", :class => "nifty_form")
|
95
|
-
# => <form accept-charset="UTF-8" action="/people/search?method=get&class=nifty_form" method="post">
|
89
|
+
# => '<form accept-charset="UTF-8" action="/people/search?method=get&class=nifty_form" method="post">'
|
96
90
|
</ruby>
|
97
91
|
|
98
|
-
Here
|
92
|
+
Here, +method+ and +class+ are appended to the query string of the generated URL because you even though you mean to write two hashes, you really only specified one. So you need to tell Ruby which is which by delimiting the first hash (or both) with curly brackets. This will generate the HTML you expect:
|
99
93
|
|
100
94
|
<ruby>
|
101
95
|
form_tag({:controller => "people", :action => "search"}, :method => "get", :class => "nifty_form")
|
102
|
-
# => <form accept-charset="UTF-8" action="/people/search" method="get" class="nifty_form">
|
96
|
+
# => '<form accept-charset="UTF-8" action="/people/search" method="get" class="nifty_form">'
|
103
97
|
</ruby>
|
104
98
|
|
105
|
-
This is a common pitfall when using form helpers, since many of them accept multiple hashes. So in future, if a helper produces unexpected output, make sure that you have delimited the hash parameters properly.
|
106
|
-
|
107
|
-
WARNING: Do not delimit the second hash without doing so with the first hash, otherwise your method invocation will result in an +expecting tASSOC+ syntax error.
|
108
|
-
|
109
99
|
h4. Helpers for Generating Form Elements
|
110
100
|
|
111
|
-
Rails provides a series of helpers for generating form elements such as checkboxes, text fields and radio buttons. These basic helpers, with names ending in
|
101
|
+
Rails provides a series of helpers for generating form elements such as checkboxes, text fields, and radio buttons. These basic helpers, with names ending in "_tag" (such as +text_field_tag+ and +check_box_tag+), generate just a single +<input>+ element. The first parameter to these is always the name of the input. When the form is submitted, the name will be passed along with the form data, and will make its way to the +params+ hash in the controller with the value entered by the user for that field. For example, if the form contains +<%= text_field_tag(:query) %>+, then you would be able to get the value of this field in the controller with +params[:query]+.
|
112
102
|
|
113
|
-
|
114
|
-
<%= text_field_tag(:query) %>
|
115
|
-
</erb>
|
116
|
-
|
117
|
-
then the controller code should use
|
118
|
-
|
119
|
-
<ruby>
|
120
|
-
params[:query]
|
121
|
-
</ruby>
|
122
|
-
|
123
|
-
to retrieve the value entered by the user. When naming inputs, be aware that Rails uses certain conventions that control whether values are at the top level of the +params+ hash, inside an array or a nested hash and so on. You can read more about them in the parameter_names section. For details on the precise usage of these helpers, please refer to the "API documentation":http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html.
|
103
|
+
When naming inputs, Rails uses certain conventions that make it possible to submit parameters with non-scalar values such as arrays or hashes, which will also be accessible in +params+. You can read more about them in "chapter 7 of this guide":#understanding-parameter-naming-conventions. For details on the precise usage of these helpers, please refer to the "API documentation":http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html.
|
124
104
|
|
125
105
|
h5. Checkboxes
|
126
106
|
|
@@ -133,7 +113,7 @@ Checkboxes are form controls that give the user a set of options they can enable
|
|
133
113
|
<%= label_tag(:pet_cat, "I own a cat") %>
|
134
114
|
</erb>
|
135
115
|
|
136
|
-
|
116
|
+
This generates the following:
|
137
117
|
|
138
118
|
<html>
|
139
119
|
<input id="pet_dog" name="pet_dog" type="checkbox" value="1" />
|
@@ -142,11 +122,11 @@ output:
|
|
142
122
|
<label for="pet_cat">I own a cat</label>
|
143
123
|
</html>
|
144
124
|
|
145
|
-
The
|
125
|
+
The first parameter to +check_box_tag+, of course, is the name of the input. The second parameter, naturally, is the value of the input. This value will be included in the form data (and be present in +params+) when the checkbox is checked.
|
146
126
|
|
147
127
|
h5. Radio Buttons
|
148
128
|
|
149
|
-
Radio buttons, while similar to checkboxes, are controls that specify a set of options in which they are mutually exclusive (i.e
|
129
|
+
Radio buttons, while similar to checkboxes, are controls that specify a set of options in which they are mutually exclusive (i.e., the user can only pick one):
|
150
130
|
|
151
131
|
<erb>
|
152
132
|
<%= radio_button_tag(:age, "child") %>
|
@@ -155,7 +135,7 @@ Radio buttons, while similar to checkboxes, are controls that specify a set of o
|
|
155
135
|
<%= label_tag(:age_adult, "I'm over 21") %>
|
156
136
|
</erb>
|
157
137
|
|
158
|
-
|
138
|
+
Output:
|
159
139
|
|
160
140
|
<html>
|
161
141
|
<input id="age_child" name="age" type="radio" value="child" />
|
@@ -164,32 +144,41 @@ output:
|
|
164
144
|
<label for="age_adult">I'm over 21</label>
|
165
145
|
</html>
|
166
146
|
|
167
|
-
As with +check_box_tag
|
147
|
+
As with +check_box_tag+, the second parameter to +radio_button_tag+ is the value of the input. Because these two radio buttons share the same name (age) the user will only be able to select one, and +params[:age]+ will contain either "child" or "adult".
|
168
148
|
|
169
|
-
|
149
|
+
NOTE: Always use labels for checkbox and radio buttons. They associate text with a specific option and make it easier for users to click the inputs by expanding the clickable region.
|
170
150
|
|
171
151
|
h4. Other Helpers of Interest
|
172
152
|
|
173
|
-
Other form controls worth mentioning are
|
153
|
+
Other form controls worth mentioning are textareas, password fields, hidden fields, search fields, telephone fields, URL fields and email fields:
|
174
154
|
|
175
155
|
<erb>
|
176
156
|
<%= text_area_tag(:message, "Hi, nice site", :size => "24x6") %>
|
177
157
|
<%= password_field_tag(:password) %>
|
178
158
|
<%= hidden_field_tag(:parent_id, "5") %>
|
159
|
+
<%= search_field(:user, :name) %>
|
160
|
+
<%= telephone_field(:user, :phone) %>
|
161
|
+
<%= url_field(:user, :homepage) %>
|
162
|
+
<%= email_field(:user, :address) %>
|
179
163
|
</erb>
|
180
164
|
|
181
|
-
|
165
|
+
Output:
|
182
166
|
|
183
167
|
<html>
|
184
168
|
<textarea id="message" name="message" cols="24" rows="6">Hi, nice site</textarea>
|
185
169
|
<input id="password" name="password" type="password" />
|
186
170
|
<input id="parent_id" name="parent_id" type="hidden" value="5" />
|
171
|
+
<input id="user_name" name="user[name]" size="30" type="search" />
|
172
|
+
<input id="user_phone" name="user[phone]" size="30" type="tel" />
|
173
|
+
<input id="user_homepage" size="30" name="user[homepage]" type="url" />
|
174
|
+
<input id="user_address" size="30" name="user[address]" type="email" />
|
187
175
|
</html>
|
188
176
|
|
189
|
-
Hidden inputs are not shown to the user
|
177
|
+
Hidden inputs are not shown to the user but instead hold data like any textual input. Values inside them can be changed with JavaScript.
|
190
178
|
|
191
|
-
|
179
|
+
IMPORTANT: The search, telephone, URL, and email inputs are HTML5 controls. If you require your app to have a consistent experience in older browsers, you will need an HTML5 polyfill (provided by CSS and/or JavaScript). There is definitely "no shortage of solutions for this":https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills, although a couple of popular tools at the moment are "Modernizr":http://www.modernizr.com/ and "yepnope":http://yepnopejs.com/, which provide a simple way to add functionality based on the presence of detected HTML5 features.
|
192
180
|
|
181
|
+
TIP: If you're using password input fields (for any purpose), you might want to configure your application to prevent those parameters from being logged. You can learn about this in the "Security Guide":security.html#logging.
|
193
182
|
|
194
183
|
h3. Dealing with Model Objects
|
195
184
|
|
@@ -545,7 +534,7 @@ NOTE: In many cases the built-in date pickers are clumsy as they do not aid the
|
|
545
534
|
|
546
535
|
h4. Individual Components
|
547
536
|
|
548
|
-
Occasionally you need to display just a single date component such as a year or a month. Rails provides a series of helpers for this, one for each component +select_year+, +select_month+, +select_day+, +select_hour+, +select_minute+, +select_second+. These helpers are fairly straightforward. By default they will generate an input field named after the time component (for example "year" for +select_year+, "month" for +select_month+ etc.) although this can be
|
537
|
+
Occasionally you need to display just a single date component such as a year or a month. Rails provides a series of helpers for this, one for each component +select_year+, +select_month+, +select_day+, +select_hour+, +select_minute+, +select_second+. These helpers are fairly straightforward. By default they will generate an input field named after the time component (for example "year" for +select_year+, "month" for +select_month+ etc.) although this can be overridden with the +:field_name+ option. The +:prefix+ option works in the same way that it does for +select_date+ and +select_time+ and has the same default value.
|
549
538
|
|
550
539
|
The first parameter specifies which value should be selected and can either be an instance of a Date, Time or DateTime, in which case the relevant component will be extracted, or a numerical value. For example
|
551
540
|
|
@@ -589,7 +578,7 @@ def upload
|
|
589
578
|
end
|
590
579
|
</ruby>
|
591
580
|
|
592
|
-
Once a file has been uploaded, there are a multitude of potential tasks, ranging from where to store the files (on disk, Amazon S3, etc) and associating them with models to resizing image files and generating thumbnails. The intricacies of this are beyond the scope of this guide, but there are several
|
581
|
+
Once a file has been uploaded, there are a multitude of potential tasks, ranging from where to store the files (on disk, Amazon S3, etc) and associating them with models to resizing image files and generating thumbnails. The intricacies of this are beyond the scope of this guide, but there are several libraries designed to assist with these. Two of the better known ones are "CarrierWave":https://github.com/jnicklas/carrierwave and "Paperclip":http://www.thoughtbot.com/projects/paperclip.
|
593
582
|
|
594
583
|
NOTE: If the user has not selected a file the corresponding parameter will be an empty string.
|
595
584
|
|
@@ -712,7 +701,7 @@ You might want to render a form with a set of edit fields for each of a person's
|
|
712
701
|
<erb>
|
713
702
|
<%= form_for @person do |person_form| %>
|
714
703
|
<%= person_form.text_field :name %>
|
715
|
-
<%
|
704
|
+
<% @person.addresses.each do |address| %>
|
716
705
|
<%= person_form.fields_for address, :index => address do |address_form|%>
|
717
706
|
<%= address_form.text_field :city %>
|
718
707
|
<% end %>
|
@@ -777,7 +766,7 @@ If you need to post some data to an external resource it is still great to build
|
|
777
766
|
Sometimes when you submit data to an external resource, like payment gateway, fields you can use in your form are limited by an external API. So you may want not to generate an +authenticity_token+ hidden field at all. For doing this just pass +false+ to the +:authenticity_token+ option:
|
778
767
|
|
779
768
|
<erb>
|
780
|
-
<%= form_tag 'http://farfar.away/form', :authenticity_token =>
|
769
|
+
<%= form_tag 'http://farfar.away/form', :authenticity_token => false) do %>
|
781
770
|
Form contents
|
782
771
|
<% end %>
|
783
772
|
</erb>
|
@@ -1,28 +1,41 @@
|
|
1
1
|
h2. Getting Started with Rails
|
2
2
|
|
3
|
-
This guide covers getting up and running with Ruby on Rails. After reading it,
|
3
|
+
This guide covers getting up and running with Ruby on Rails. After reading it,
|
4
|
+
you should be familiar with:
|
4
5
|
|
5
6
|
* Installing Rails, creating a new Rails application, and connecting your application to a database
|
6
7
|
* The general layout of a Rails application
|
7
8
|
* The basic principles of MVC (Model, View Controller) and RESTful design
|
8
|
-
* How to quickly generate the starting pieces of a Rails application
|
9
|
+
* How to quickly generate the starting pieces of a Rails application
|
9
10
|
|
10
11
|
endprologue.
|
11
12
|
|
12
|
-
WARNING. This Guide is based on Rails 3.
|
13
|
+
WARNING. This Guide is based on Rails 3.1. Some of the code shown here will not
|
14
|
+
work in earlier versions of Rails.
|
13
15
|
|
14
16
|
h3. Guide Assumptions
|
15
17
|
|
16
|
-
This guide is designed for beginners who want to get started with a Rails
|
18
|
+
This guide is designed for beginners who want to get started with a Rails
|
19
|
+
application from scratch. It does not assume that you have any prior experience
|
20
|
+
with Rails. However, to get the most out of it, you need to have some
|
21
|
+
prerequisites installed:
|
17
22
|
|
18
23
|
* The "Ruby":http://www.ruby-lang.org/en/downloads language version 1.8.7 or higher
|
19
24
|
|
20
|
-
TIP: Note that Ruby 1.8.7 p248 and p249 have marshaling bugs that crash Rails
|
25
|
+
TIP: Note that Ruby 1.8.7 p248 and p249 have marshaling bugs that crash Rails
|
26
|
+
3.0. Ruby Enterprise Edition have these fixed since release 1.8.7-2010.02
|
27
|
+
though. On the 1.9 front, Ruby 1.9.1 is not usable because it outright segfaults
|
28
|
+
on Rails 3.0, so if you want to use Rails 3 with 1.9.x jump on 1.9.2 for smooth
|
29
|
+
sailing.
|
21
30
|
|
22
31
|
* The "RubyGems":http://rubyforge.org/frs/?group_id=126 packaging system
|
32
|
+
** If you want to learn more about RubyGems, please read the "RubyGems User Guide":http://docs.rubygems.org/read/book/1
|
23
33
|
* A working installation of the "SQLite3 Database":http://www.sqlite.org
|
24
34
|
|
25
|
-
Rails is a web application framework running on the Ruby programming language.
|
35
|
+
Rails is a web application framework running on the Ruby programming language.
|
36
|
+
If you have no prior experience with Ruby, you will find a very steep learning
|
37
|
+
curve diving straight into Rails. There are some good free resources on the
|
38
|
+
internet for learning Ruby, including:
|
26
39
|
|
27
40
|
* "Mr. Neighborly's Humble Little Ruby Book":http://www.humblelittlerubybook.com
|
28
41
|
* "Programming Ruby":http://www.ruby-doc.org/docs/ProgrammingRuby/
|
@@ -30,19 +43,32 @@ Rails is a web application framework running on the Ruby programming language. I
|
|
30
43
|
|
31
44
|
h3. What is Rails?
|
32
45
|
|
33
|
-
Rails is a web application development framework written in the Ruby language.
|
46
|
+
Rails is a web application development framework written in the Ruby language.
|
47
|
+
It is designed to make programming web applications easier by making assumptions
|
48
|
+
about what every developer needs to get started. It allows you to write less
|
49
|
+
code while accomplishing more than many other languages and frameworks.
|
50
|
+
Experienced Rails developers also report that it makes web application
|
51
|
+
development more fun.
|
34
52
|
|
35
|
-
Rails is opinionated software. It makes the assumption that there is a "best"
|
53
|
+
Rails is opinionated software. It makes the assumption that there is a "best"
|
54
|
+
way to do things, and it's designed to encourage that way - and in some cases to
|
55
|
+
discourage alternatives. If you learn "The Rails Way" you'll probably discover a
|
56
|
+
tremendous increase in productivity. If you persist in bringing old habits from
|
57
|
+
other languages to your Rails development, and trying to use patterns you
|
58
|
+
learned elsewhere, you may have a less happy experience.
|
36
59
|
|
37
60
|
The Rails philosophy includes several guiding principles:
|
38
61
|
|
39
62
|
* DRY - "Don't Repeat Yourself" - suggests that writing the same code over and over again is a bad thing.
|
40
|
-
* Convention Over Configuration - means that Rails makes assumptions about what you want to do and how you're going to
|
41
|
-
|
63
|
+
* Convention Over Configuration - means that Rails makes assumptions about what you want to do and how you're going to
|
64
|
+
d o it, rather than requiring you to specify every little thing through endless configuration files.
|
65
|
+
* REST is the best pattern for web applications - organizing your application around resources and standard HTTP verbs
|
66
|
+
i s the fastest way to go.
|
42
67
|
|
43
68
|
h4. The MVC Architecture
|
44
69
|
|
45
|
-
At the core of Rails is the Model, View, Controller architecture, usually just
|
70
|
+
At the core of Rails is the Model, View, Controller architecture, usually just
|
71
|
+
called MVC. MVC benefits include:
|
46
72
|
|
47
73
|
* Isolation of business logic from the user interface
|
48
74
|
* Ease of keeping code DRY
|
@@ -50,19 +76,34 @@ At the core of Rails is the Model, View, Controller architecture, usually just c
|
|
50
76
|
|
51
77
|
h5. Models
|
52
78
|
|
53
|
-
A model represents the information (data) of the application and the rules to
|
79
|
+
A model represents the information (data) of the application and the rules to
|
80
|
+
manipulate that data. In the case of Rails, models are primarily used for
|
81
|
+
managing the rules of interaction with a corresponding database table. In most
|
82
|
+
cases, each table in your database will correspond to one model in your
|
83
|
+
application. The bulk of your application's business logic will be concentrated
|
84
|
+
in the models.
|
54
85
|
|
55
86
|
h5. Views
|
56
87
|
|
57
|
-
Views represent the user interface of your application. In Rails, views are
|
88
|
+
Views represent the user interface of your application. In Rails, views are
|
89
|
+
often HTML files with embedded Ruby code that perform tasks related solely to
|
90
|
+
the presentation of the data. Views handle the job of providing data to the web
|
91
|
+
browser or other tool that is used to make requests from your application.
|
58
92
|
|
59
93
|
h5. Controllers
|
60
94
|
|
61
|
-
Controllers provide the "glue" between models and views. In Rails, controllers
|
95
|
+
Controllers provide the "glue" between models and views. In Rails, controllers
|
96
|
+
are responsible for processing the incoming requests from the web browser,
|
97
|
+
interrogating the models for data, and passing that data on to the views for
|
98
|
+
presentation.
|
62
99
|
|
63
100
|
h4. The Components of Rails
|
64
101
|
|
65
|
-
Rails ships as many individual components.
|
102
|
+
Rails ships as many individual components. Each of these components are briefly
|
103
|
+
explained below. If you are new to Rails, as you read this section, don't get
|
104
|
+
hung up on the details of each component, as they will be explained in further
|
105
|
+
detail later. For instance, we will bring up Rack applications, but you don't
|
106
|
+
need to know anything about them to continue with this guide.
|
66
107
|
|
67
108
|
* Action Pack
|
68
109
|
** Action Controller
|
@@ -78,67 +119,105 @@ Rails ships as many individual components.
|
|
78
119
|
|
79
120
|
h5. Action Pack
|
80
121
|
|
81
|
-
Action Pack is a single gem that contains Action Controller, Action View and
|
122
|
+
Action Pack is a single gem that contains Action Controller, Action View and
|
123
|
+
Action Dispatch. The "VC" part of "MVC".
|
82
124
|
|
83
|
-
|
125
|
+
h6. Action Controller
|
84
126
|
|
85
|
-
Action Controller is the component that manages the controllers in a Rails
|
127
|
+
Action Controller is the component that manages the controllers in a Rails
|
128
|
+
application. The Action Controller framework processes incoming requests to a
|
129
|
+
Rails application, extracts parameters, and dispatches them to the intended
|
130
|
+
action. Services provided by Action Controller include session management,
|
131
|
+
template rendering, and redirect management.
|
86
132
|
|
87
|
-
|
133
|
+
h6. Action View
|
88
134
|
|
89
|
-
Action View manages the views of your Rails application. It can create both HTML
|
135
|
+
Action View manages the views of your Rails application. It can create both HTML
|
136
|
+
and XML output by default. Action View manages rendering templates, including
|
137
|
+
nested and partial templates, and includes built-in AJAX support. View
|
138
|
+
templates are covered in more detail in another guide called "Layouts and
|
139
|
+
Rendering":layouts_and_rendering.html.
|
90
140
|
|
91
|
-
|
141
|
+
h6. Action Dispatch
|
92
142
|
|
93
|
-
Action Dispatch handles routing of web requests and dispatches them as you want,
|
143
|
+
Action Dispatch handles routing of web requests and dispatches them as you want,
|
144
|
+
either to your application or any other Rack application. Rack applications are
|
145
|
+
a more advanced topic and are covered in a separate guide called "Rails on
|
146
|
+
Rack":rails_on_rack.html.
|
94
147
|
|
95
148
|
h5. Action Mailer
|
96
149
|
|
97
|
-
Action Mailer is a framework for building e-mail services. You can use Action
|
150
|
+
Action Mailer is a framework for building e-mail services. You can use Action
|
151
|
+
Mailer to receive and process incoming email and send simple plain text or
|
152
|
+
complex multipart emails based on flexible templates.
|
98
153
|
|
99
154
|
h5. Active Model
|
100
155
|
|
101
|
-
Active Model provides a defined interface between the Action Pack gem services
|
156
|
+
Active Model provides a defined interface between the Action Pack gem services
|
157
|
+
and Object Relationship Mapping gems such as Active Record. Active Model allows
|
158
|
+
Rails to utilize other ORM frameworks in place of Active Record if your
|
159
|
+
application needs this.
|
102
160
|
|
103
161
|
h5. Active Record
|
104
162
|
|
105
|
-
Active Record is the base for the models in a Rails application. It provides
|
163
|
+
Active Record is the base for the models in a Rails application. It provides
|
164
|
+
database independence, basic CRUD functionality, advanced finding capabilities,
|
165
|
+
and the ability to relate models to one another, among other services.
|
106
166
|
|
107
167
|
h5. Active Resource
|
108
168
|
|
109
|
-
Active Resource provides a framework for managing the connection between
|
169
|
+
Active Resource provides a framework for managing the connection between
|
170
|
+
business objects and RESTful web services. It implements a way to map web-based
|
171
|
+
resources to local objects with CRUD semantics.
|
110
172
|
|
111
173
|
h5. Active Support
|
112
174
|
|
113
|
-
Active Support is an extensive collection of utility classes and standard Ruby
|
175
|
+
Active Support is an extensive collection of utility classes and standard Ruby
|
176
|
+
library extensions that are used in Rails, both by the core code and by your
|
177
|
+
applications.
|
114
178
|
|
115
179
|
h5. Railties
|
116
180
|
|
117
|
-
Railties is the core Rails code that builds new Rails applications and glues the
|
181
|
+
Railties is the core Rails code that builds new Rails applications and glues the
|
182
|
+
various frameworks and plugins together in any Rails application.
|
118
183
|
|
119
184
|
h4. REST
|
120
185
|
|
121
|
-
Rest stands for Representational State Transfer and is the foundation of the
|
186
|
+
Rest stands for Representational State Transfer and is the foundation of the
|
187
|
+
RESTful architecture. This is generally considered to be Roy Fielding's doctoral
|
188
|
+
thesis, "Architectural Styles and the Design of Network-based Software
|
189
|
+
Architectures":http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm. While
|
190
|
+
you can read through the thesis, REST in terms of Rails boils down to two main
|
191
|
+
principles:
|
122
192
|
|
123
193
|
* Using resource identifiers such as URLs to represent resources.
|
124
194
|
* Transferring representations of the state of that resource between system components.
|
125
195
|
|
126
|
-
For example,
|
196
|
+
For example, the following HTTP request:
|
127
197
|
|
128
198
|
<tt>DELETE /photos/17</tt>
|
129
199
|
|
130
|
-
would be understood to refer to a photo resource with the ID of 17, and to
|
200
|
+
would be understood to refer to a photo resource with the ID of 17, and to
|
201
|
+
indicate a desired action - deleting that resource. REST is a natural style for
|
202
|
+
the architecture of web applications, and Rails hooks into this shielding you
|
203
|
+
from many of the RESTful complexities and browser quirks.
|
131
204
|
|
132
|
-
If you'd like more details on REST as an architectural style, these resources
|
205
|
+
If you'd like more details on REST as an architectural style, these resources
|
206
|
+
are more approachable than Fielding's thesis:
|
133
207
|
|
134
208
|
* "A Brief Introduction to REST":http://www.infoq.com/articles/rest-introduction by Stefan Tilkov
|
135
209
|
* "An Introduction to REST":http://bitworking.org/news/373/An-Introduction-to-REST (video tutorial) by Joe Gregorio
|
136
210
|
* "Representational State Transfer":http://en.wikipedia.org/wiki/Representational_State_Transfer article in Wikipedia
|
137
|
-
* "How to GET a Cup of Coffee":http://www.infoq.com/articles/webber-rest-workflow by Jim Webber, Savas Parastatidis &
|
211
|
+
* "How to GET a Cup of Coffee":http://www.infoq.com/articles/webber-rest-workflow by Jim Webber, Savas Parastatidis &
|
212
|
+
Ian Robinson
|
138
213
|
|
139
214
|
h3. Creating a New Rails Project
|
140
215
|
|
141
|
-
If you follow this guide, you'll create a Rails project called <tt>blog</tt>, a
|
216
|
+
If you follow this guide, you'll create a Rails project called <tt>blog</tt>, a
|
217
|
+
(very) simple weblog. Before you can start building the application, you need to
|
218
|
+
make sure that you have Rails itself installed.
|
219
|
+
|
220
|
+
TIP: The examples below use # and $ to denote terminal prompts. If you are using Windows, your prompt will look something like c:\source_code>
|
142
221
|
|
143
222
|
h4. Installing Rails
|
144
223
|
|
@@ -149,13 +228,19 @@ Usually run this as the root user:
|
|
149
228
|
# gem install rails
|
150
229
|
</shell>
|
151
230
|
|
152
|
-
TIP. If you're working on Windows, you can quickly install Ruby and Rails with
|
231
|
+
TIP. If you're working on Windows, you can quickly install Ruby and Rails with
|
232
|
+
"Rails Installer":http://railsinstaller.org.
|
153
233
|
|
154
234
|
h4. Creating the Blog Application
|
155
235
|
|
156
|
-
The best way to use this guide is to follow each step as it happens, no code or
|
236
|
+
The best way to use this guide is to follow each step as it happens, no code or
|
237
|
+
step needed to make this example application has been left out, so you can
|
238
|
+
literally follow along step by step. If you need to see the completed code, you
|
239
|
+
can download it from "Getting Started
|
240
|
+
Code":https://github.com/mikel/getting-started-code.
|
157
241
|
|
158
|
-
To begin, open a terminal, navigate to a folder where you have rights to create
|
242
|
+
To begin, open a terminal, navigate to a folder where you have rights to create
|
243
|
+
files, and type:
|
159
244
|
|
160
245
|
<shell>
|
161
246
|
$ rails new blog
|
@@ -163,57 +248,63 @@ $ rails new blog
|
|
163
248
|
|
164
249
|
This will create a Rails application called Blog in a directory called blog.
|
165
250
|
|
166
|
-
TIP: You can see all of the switches that the Rails application builder accepts
|
251
|
+
TIP: You can see all of the switches that the Rails application builder accepts
|
252
|
+
by running
|
253
|
+
<tt>rails new -h</tt>.
|
167
254
|
|
168
|
-
After you create the blog application, switch to its folder to continue work
|
255
|
+
After you create the blog application, switch to its folder to continue work
|
256
|
+
directly in that application:
|
169
257
|
|
170
258
|
<shell>
|
171
259
|
$ cd blog
|
172
260
|
</shell>
|
173
261
|
|
174
|
-
In any case, Rails will create a folder in your working directory called
|
262
|
+
In any case, Rails will create a folder in your working directory called
|
263
|
+
<tt>blog</tt>. Open up that folder and explore its contents. Most of the work in
|
264
|
+
this tutorial will happen in the <tt>app/</tt> folder, but here's a basic
|
265
|
+
rundown on the function of each folder that Rails creates in a new application
|
266
|
+
by default:
|
175
267
|
|
176
268
|
|_.File/Folder|_.Purpose|
|
177
|
-
|Gemfile|This file allows you to specify what gem dependencies are needed for your Rails application.|
|
178
|
-
|README|This is a brief instruction manual for your application.
|
179
|
-
|Rakefile|This file
|
180
|
-
|app/|Contains the controllers, models, and
|
269
|
+
|Gemfile|This file allows you to specify what gem dependencies are needed for your Rails application. See section on Bundler, below.|
|
270
|
+
|README|This is a brief instruction manual for your application. You should edit this file to tell others what your application does, how to set it up, and so on.|
|
271
|
+
|Rakefile|This file locates and loads tasks that can be run from the command line. The task definitions are defined throughout the components of Rails. Rather than changing Rakefile, you should add your own tasks by adding files to the lib/tasks directory of your application.|
|
272
|
+
|app/|Contains the controllers, models, views and assets for your application. You'll focus on this folder for the remainder of this guide.|
|
181
273
|
|config/|Configure your application's runtime rules, routes, database, and more.|
|
182
274
|
|config.ru|Rack configuration for Rack based servers used to start the application.|
|
183
275
|
|db/|Shows your current database schema, as well as the database migrations. You'll learn about migrations shortly.|
|
184
276
|
|doc/|In-depth documentation for your application.|
|
185
277
|
|lib/|Extended modules for your application (not covered in this guide).|
|
186
278
|
|log/|Application log files.|
|
187
|
-
|public/|The only folder seen to the world as-is.
|
279
|
+
|public/|The only folder seen to the world as-is. Contains the static files and compiled assets.|
|
188
280
|
|script/|Contains the rails script that starts your app and can contain other scripts you use to deploy or run your application.|
|
189
281
|
|test/|Unit tests, fixtures, and other test apparatus. These are covered in "Testing Rails Applications":testing.html|
|
190
282
|
|tmp/|Temporary files|
|
191
283
|
|vendor/|A place for all third-party code. In a typical Rails application, this includes Ruby Gems, the Rails source code (if you install it into your project) and plugins containing additional prepackaged functionality.|
|
192
284
|
|
193
|
-
h4. Installing the Required Gems
|
194
|
-
|
195
|
-
Rails applications manage gem dependencies with "Bundler":http://gembundler.com/v1.0/index.html by default. As we don't need any other gems beyond the ones in the generated +Gemfile+ we can directly run
|
196
|
-
|
197
|
-
<shell>
|
198
|
-
$ bundle install
|
199
|
-
</shell>
|
200
|
-
|
201
|
-
to have them ready.
|
202
|
-
|
203
285
|
h4. Configuring a Database
|
204
286
|
|
205
|
-
Just about every Rails application will interact with a database. The database
|
206
|
-
|
287
|
+
Just about every Rails application will interact with a database. The database
|
288
|
+
to use is specified in a configuration file, +config/database.yml+. If you open
|
289
|
+
this file in a new Rails application, you'll see a default database
|
290
|
+
configuration using SQLite3. The file contains sections for three different
|
291
|
+
environments in which Rails can run by default:
|
207
292
|
|
208
|
-
* The +development+ environment is used on your development computer as you interact manually with the application
|
209
|
-
* The +test+ environment is used to run automated tests
|
293
|
+
* The +development+ environment is used on your development computer as you interact manually with the application.
|
294
|
+
* The +test+ environment is used to run automated tests.
|
210
295
|
* The +production+ environment is used when you deploy your application for the world to use.
|
211
296
|
|
212
297
|
h5. Configuring an SQLite3 Database
|
213
298
|
|
214
|
-
Rails comes with built-in support for "SQLite3":http://www.sqlite.org, which is
|
299
|
+
Rails comes with built-in support for "SQLite3":http://www.sqlite.org, which is
|
300
|
+
a lightweight serverless database application. While a busy production
|
301
|
+
environment may overload SQLite, it works well for development and testing.
|
302
|
+
Rails defaults to using an SQLite database when creating a new project, but you
|
303
|
+
can always change it later.
|
215
304
|
|
216
|
-
Here's the section of the default configuration file
|
305
|
+
Here's the section of the default configuration file
|
306
|
+
(<tt>config/database.yml</tt>) with connection information for the development
|
307
|
+
environment:
|
217
308
|
|
218
309
|
<yaml>
|
219
310
|
development:
|
@@ -223,11 +314,17 @@ development:
|
|
223
314
|
timeout: 5000
|
224
315
|
</yaml>
|
225
316
|
|
226
|
-
NOTE: In this guide we are using an SQLite3 database for data storage, because
|
317
|
+
NOTE: In this guide we are using an SQLite3 database for data storage, because
|
318
|
+
it is a zero configuration database that just works. Rails also supports MySQL
|
319
|
+
and PostgreSQL "out of the box", and has plugins for many database systems. If
|
320
|
+
you are using a database in a production environment Rails most likely has an
|
321
|
+
adapter for it.
|
227
322
|
|
228
323
|
h5. Configuring a MySQL Database
|
229
324
|
|
230
|
-
If you choose to use MySQL instead of the shipped SQLite3 database, your
|
325
|
+
If you choose to use MySQL instead of the shipped SQLite3 database, your
|
326
|
+
+config/database.yml+ will look a little different. Here's the development
|
327
|
+
section:
|
231
328
|
|
232
329
|
<yaml>
|
233
330
|
development:
|
@@ -240,11 +337,14 @@ development:
|
|
240
337
|
socket: /tmp/mysql.sock
|
241
338
|
</yaml>
|
242
339
|
|
243
|
-
If your development computer's MySQL installation includes a root user with an
|
340
|
+
If your development computer's MySQL installation includes a root user with an
|
341
|
+
empty password, this configuration should work for you. Otherwise, change the
|
342
|
+
username and password in the +development+ section as appropriate.
|
244
343
|
|
245
344
|
h5. Configuring a PostgreSQL Database
|
246
345
|
|
247
|
-
|
346
|
+
If you choose to use PostgreSQL, your +config/database.yml+ will be customized
|
347
|
+
to use PostgreSQL databases:
|
248
348
|
|
249
349
|
<yaml>
|
250
350
|
development:
|
@@ -256,53 +356,120 @@ development:
|
|
256
356
|
password:
|
257
357
|
</yaml>
|
258
358
|
|
359
|
+
h5. Configuring an SQLite3 Database for JRuby Platform
|
360
|
+
|
361
|
+
If you choose to use SQLite3 and using JRuby, your +config/database.yml+ will
|
362
|
+
look a little different. Here's the development section:
|
363
|
+
|
364
|
+
<yaml>
|
365
|
+
development:
|
366
|
+
adapter: jdbcsqlite3
|
367
|
+
database: db/development.sqlite3
|
368
|
+
</yaml>
|
369
|
+
|
370
|
+
h5. Configuring a MySQL Database for JRuby Platform
|
371
|
+
|
372
|
+
If you choose to use MySQL and using JRuby, your +config/database.yml+ will look
|
373
|
+
a little different. Here's the development section:
|
374
|
+
|
375
|
+
<yaml>
|
376
|
+
development:
|
377
|
+
adapter: jdbcmysql
|
378
|
+
database: blog_development
|
379
|
+
username: root
|
380
|
+
password:
|
381
|
+
</yaml>
|
382
|
+
|
383
|
+
h5. Configuring a PostgreSQL Database for JRuby Platform
|
384
|
+
|
385
|
+
Finally if you choose to use PostgreSQL and using JRuby, your
|
386
|
+
+config/database.yml+ will look a little different. Here's the development
|
387
|
+
section:
|
388
|
+
|
389
|
+
<yaml>
|
390
|
+
development:
|
391
|
+
adapter: jdbcpostgresql
|
392
|
+
encoding: unicode
|
393
|
+
database: blog_development
|
394
|
+
username: blog
|
395
|
+
password:
|
396
|
+
</yaml>
|
397
|
+
|
259
398
|
Change the username and password in the +development+ section as appropriate.
|
260
399
|
|
261
|
-
TIP: You don't have to update the database configurations manually. If you
|
400
|
+
TIP: You don't have to update the database configurations manually. If you look at the
|
401
|
+
options of the application generator, you will see that one of the options
|
402
|
+
is named <tt>--database</tt>. This option allows you to choose an adapter from a
|
403
|
+
list of the most used relational databases. You can even run the generator
|
404
|
+
repeatedly: <tt>cd .. && rails new blog --database=mysql</tt>. When you confirm the overwriting
|
405
|
+
of the +config/database.yml+ file, your application will be configured for MySQL
|
406
|
+
instead of SQLite.
|
262
407
|
|
263
408
|
h4. Creating the Database
|
264
409
|
|
265
|
-
Now that you have your database configured, it's time to have Rails create an
|
410
|
+
Now that you have your database configured, it's time to have Rails create an
|
411
|
+
empty database for you. You can do this by running a rake command:
|
266
412
|
|
267
413
|
<shell>
|
268
414
|
$ rake db:create
|
269
415
|
</shell>
|
270
416
|
|
271
|
-
This will create your development and test SQLite3 databases inside the
|
417
|
+
This will create your development and test SQLite3 databases inside the
|
418
|
+
<tt>db/</tt> folder.
|
272
419
|
|
273
|
-
TIP: Rake is a general-purpose command-runner that Rails uses for many things.
|
420
|
+
TIP: Rake is a general-purpose command-runner that Rails uses for many things.
|
421
|
+
You can see the list of available rake commands in your application by running
|
422
|
+
+rake -T+.
|
274
423
|
|
275
424
|
h3. Hello, Rails!
|
276
425
|
|
277
|
-
One of the traditional places to start with a new language is by getting some
|
426
|
+
One of the traditional places to start with a new language is by getting some
|
427
|
+
text up on screen quickly. To do this, you need to get your Rails application
|
428
|
+
server running.
|
278
429
|
|
279
430
|
h4. Starting up the Web Server
|
280
431
|
|
281
|
-
You actually have a functional Rails application already. To see it, you need to
|
432
|
+
You actually have a functional Rails application already. To see it, you need to
|
433
|
+
start a web server on your development machine. You can do this by running:
|
282
434
|
|
283
435
|
<shell>
|
284
436
|
$ rails server
|
285
437
|
</shell>
|
286
438
|
|
287
|
-
This will fire up an instance of the WEBrick web server by default (Rails can
|
439
|
+
This will fire up an instance of the WEBrick web server by default (Rails can
|
440
|
+
also use several other web servers). To see your application in action, open a
|
441
|
+
browser window and navigate to "http://localhost:3000":http://localhost:3000.
|
442
|
+
You should see Rails' default information page:
|
288
443
|
|
289
444
|
!images/rails_welcome.png(Welcome Aboard screenshot)!
|
290
445
|
|
291
|
-
TIP: To stop the web server, hit Ctrl+C in the terminal window where it's
|
446
|
+
TIP: To stop the web server, hit Ctrl+C in the terminal window where it's
|
447
|
+
running. In development mode, Rails does not generally require you to stop the
|
448
|
+
server; changes you make in files will be automatically picked up by the server.
|
292
449
|
|
293
|
-
The "Welcome Aboard" page is the _smoke test_ for a new Rails application: it
|
450
|
+
The "Welcome Aboard" page is the _smoke test_ for a new Rails application: it
|
451
|
+
makes sure that you have your software configured correctly enough to serve a
|
452
|
+
page. You can also click on the _About your application’s environment_ link to
|
453
|
+
see a summary of your application's environment.
|
294
454
|
|
295
455
|
h4. Say "Hello", Rails
|
296
456
|
|
297
|
-
To get Rails saying "Hello", you need to create at minimum a controller and a
|
457
|
+
To get Rails saying "Hello", you need to create at minimum a controller and a
|
458
|
+
view. Fortunately, you can do that in a single command. Enter this command in
|
459
|
+
your terminal:
|
298
460
|
|
299
461
|
<shell>
|
300
462
|
$ rails generate controller home index
|
301
463
|
</shell>
|
302
464
|
|
303
|
-
TIP: If you
|
465
|
+
TIP: If you get a command not found error when running this command, you
|
466
|
+
need to explicitly pass Rails +rails+ commands to Ruby: <tt>ruby
|
467
|
+
\path\to\your\application\script\rails generate controller home index</tt>.
|
304
468
|
|
305
|
-
Rails will create several files for you, including
|
469
|
+
Rails will create several files for you, including
|
470
|
+
+app/views/home/index.html.erb+. This is the template that will be used to
|
471
|
+
display the results of the +index+ action (method) in the +home+ controller.
|
472
|
+
Open this file in your text editor and edit it to contain a single line of code:
|
306
473
|
|
307
474
|
<code class="html">
|
308
475
|
<h1>Hello, Rails!</h1>
|
@@ -310,17 +477,30 @@ Rails will create several files for you, including +app/views/home/index.html.er
|
|
310
477
|
|
311
478
|
h4. Setting the Application Home Page
|
312
479
|
|
313
|
-
Now that we have made the controller and view, we need to tell Rails when we
|
480
|
+
Now that we have made the controller and view, we need to tell Rails when we
|
481
|
+
want "Hello Rails" to show up. In our case, we want it to show up when we
|
482
|
+
navigate to the root URL of our site,
|
483
|
+
"http://localhost:3000":http://localhost:3000, instead of the "Welcome Aboard"
|
484
|
+
smoke test.
|
314
485
|
|
315
|
-
The first step to doing this is to delete the default page from your
|
486
|
+
The first step to doing this is to delete the default page from your
|
487
|
+
application:
|
316
488
|
|
317
489
|
<shell>
|
318
490
|
$ rm public/index.html
|
319
491
|
</shell>
|
320
492
|
|
321
|
-
We need to do this as Rails will deliver any static file in the +public+
|
493
|
+
We need to do this as Rails will deliver any static file in the +public+
|
494
|
+
directory in preference to any dynamic content we generate from the controllers.
|
322
495
|
|
323
|
-
Now, you have to tell Rails where your actual home page is located. Open the
|
496
|
+
Now, you have to tell Rails where your actual home page is located. Open the
|
497
|
+
file +config/routes.rb+ in your editor. This is your application's _routing
|
498
|
+
file_ which holds entries in a special DSL (domain-specific language) that tells
|
499
|
+
Rails how to connect incoming requests to controllers and actions. This file
|
500
|
+
contains many sample routes on commented lines, and one of them actually shows
|
501
|
+
you how to connect the root of your site to a specific controller and action.
|
502
|
+
Find the line beginning with +root :to+, uncomment it and change it like the
|
503
|
+
following:
|
324
504
|
|
325
505
|
<ruby>
|
326
506
|
Blog::Application.routes.draw do
|
@@ -331,27 +511,46 @@ Blog::Application.routes.draw do
|
|
331
511
|
root :to => "home#index"
|
332
512
|
</ruby>
|
333
513
|
|
334
|
-
The +root :to => "home#index"+ tells Rails to map the root action to the home
|
514
|
+
The +root :to => "home#index"+ tells Rails to map the root action to the home
|
515
|
+
controller's index action.
|
335
516
|
|
336
|
-
Now if you navigate to "http://localhost:3000":http://localhost:3000 in your
|
517
|
+
Now if you navigate to "http://localhost:3000":http://localhost:3000 in your
|
518
|
+
browser, you'll see +Hello, Rails!+.
|
337
519
|
|
338
|
-
NOTE. For more information about routing, refer to "Rails Routing from the
|
520
|
+
NOTE. For more information about routing, refer to "Rails Routing from the
|
521
|
+
Outside In":routing.html.
|
339
522
|
|
340
523
|
h3. Getting Up and Running Quickly with Scaffolding
|
341
524
|
|
342
|
-
Rails _scaffolding_ is a quick way to generate some of the major pieces of an
|
525
|
+
Rails _scaffolding_ is a quick way to generate some of the major pieces of an
|
526
|
+
application. If you want to create the models, views, and controllers for a new
|
527
|
+
resource in a single operation, scaffolding is the tool for the job.
|
343
528
|
|
344
529
|
h3. Creating a Resource
|
345
530
|
|
346
|
-
In the case of the blog application, you can start by generating a scaffolded
|
531
|
+
In the case of the blog application, you can start by generating a scaffolded
|
532
|
+
Post resource: this will represent a single blog posting. To do this, enter this
|
533
|
+
command in your terminal:
|
347
534
|
|
348
535
|
<shell>
|
349
536
|
$ rails generate scaffold Post name:string title:string content:text
|
350
537
|
</shell>
|
351
538
|
|
352
|
-
|
539
|
+
This will create a new database table called posts (plural of Post). The table
|
540
|
+
will have three columns, name (type string), title (type string) and content
|
541
|
+
(type text). It will also hook this new database up to Rails (details below).
|
542
|
+
|
543
|
+
NOTE. While scaffolding will get you up and running quickly, the code it
|
544
|
+
generates is unlikely to be a perfect fit for your application. You'll most
|
545
|
+
probably want to customize the generated code. Many experienced Rails developers
|
546
|
+
avoid scaffolding entirely, preferring to write all or most of their source code
|
547
|
+
from scratch. Rails, however, makes it really simple to customize templates for
|
548
|
+
generated models, controllers, views and other source files. You'll find more
|
549
|
+
information in the "Creating and Customizing Rails Generators &
|
550
|
+
Templates":generators.html guide.
|
353
551
|
|
354
|
-
The scaffold generator will build
|
552
|
+
The scaffold generator will build 17 files in your application, along with some
|
553
|
+
folders, and edit one more. Here's a quick overview of what it creates:
|
355
554
|
|
356
555
|
|_.File |_.Purpose|
|
357
556
|
|db/migrate/20100207214725_create_posts.rb |Migration to create the posts table in your database (your name will include a different timestamp)|
|
@@ -364,17 +563,25 @@ The scaffold generator will build 15 files in your application, along with some
|
|
364
563
|
|app/views/posts/new.html.erb |A view to create a new post|
|
365
564
|
|app/views/posts/_form.html.erb |A partial to control the overall look and feel of the form used in edit and new views|
|
366
565
|
|app/helpers/posts_helper.rb |Helper functions to be used from the post views|
|
566
|
+
|app/assets/stylesheets/scaffold.css.scss |Cascading style sheet to make the scaffolded views look better|
|
567
|
+
|app/assets/stylesheets/post.css.scss |Cascading style sheet for the posts controller|
|
568
|
+
|app/assets/javascripts/post.js.coffee |CoffeeScript for the posts controller|
|
367
569
|
|test/unit/post_test.rb |Unit testing harness for the posts model|
|
368
570
|
|test/functional/posts_controller_test.rb |Functional testing harness for the posts controller|
|
369
571
|
|test/unit/helpers/posts_helper_test.rb |Unit testing harness for the posts helper|
|
370
572
|
|config/routes.rb |Edited to include routing information for posts|
|
371
|
-
|app/assets/stylesheets/scaffold.css.scss |Cascading style sheet to make the scaffolded views look better|
|
372
573
|
|
373
574
|
h4. Running a Migration
|
374
575
|
|
375
|
-
One of the products of the +rails generate scaffold+ command is a _database
|
576
|
+
One of the products of the +rails generate scaffold+ command is a _database
|
577
|
+
migration_. Migrations are Ruby classes that are designed to make it simple to
|
578
|
+
create and modify database tables. Rails uses rake commands to run migrations,
|
579
|
+
and it's possible to undo a migration after it's been applied to your database.
|
580
|
+
Migration filenames include a timestamp to ensure that they're processed in the
|
581
|
+
order that they were created.
|
376
582
|
|
377
|
-
If you look in the +db/migrate/20100207214725_create_posts.rb+ file (remember,
|
583
|
+
If you look in the +db/migrate/20100207214725_create_posts.rb+ file (remember,
|
584
|
+
yours will have a slightly different name), here's what you'll find:
|
378
585
|
|
379
586
|
<ruby>
|
380
587
|
class CreatePosts < ActiveRecord::Migration
|
@@ -390,7 +597,14 @@ class CreatePosts < ActiveRecord::Migration
|
|
390
597
|
end
|
391
598
|
</ruby>
|
392
599
|
|
393
|
-
The above migration creates a method name +change+ which will be called when you
|
600
|
+
The above migration creates a method name +change+ which will be called when you
|
601
|
+
run this migration. The action defined in that method is also reversible, which
|
602
|
+
means Rails knows how to reverse the change made by this migration, in case you
|
603
|
+
want to reverse it at later date. By default, when you run this migration it
|
604
|
+
will creates a +posts+ table with two string columns and a text column. It also
|
605
|
+
creates two timestamp fields to track record creation and updating. More
|
606
|
+
information about Rails migrations can be found in the "Rails Database
|
607
|
+
Migrations":migrations.html guide.
|
394
608
|
|
395
609
|
At this point, you can use a rake command to run the migration:
|
396
610
|
|
@@ -398,7 +612,8 @@ At this point, you can use a rake command to run the migration:
|
|
398
612
|
$ rake db:migrate
|
399
613
|
</shell>
|
400
614
|
|
401
|
-
Rails will execute this migration command and tell you it created the Posts
|
615
|
+
Rails will execute this migration command and tell you it created the Posts
|
616
|
+
table.
|
402
617
|
|
403
618
|
<shell>
|
404
619
|
== CreatePosts: migrating ====================================================
|
@@ -407,28 +622,43 @@ Rails will execute this migration command and tell you it created the Posts tabl
|
|
407
622
|
== CreatePosts: migrated (0.0020s) ===========================================
|
408
623
|
</shell>
|
409
624
|
|
410
|
-
NOTE. Because you're working in the development environment by default, this
|
625
|
+
NOTE. Because you're working in the development environment by default, this
|
626
|
+
command will apply to the database defined in the +development+ section of your
|
627
|
+
+config/database.yml+ file. If you would like to execute migrations in other
|
628
|
+
environment, for instance in production, you must explicitly pass it when
|
629
|
+
invoking the command: <tt>rake db:migrate RAILS_ENV=production</tt>.
|
411
630
|
|
412
631
|
h4. Adding a Link
|
413
632
|
|
414
|
-
To hook the posts up to the home page you've already created, you can add a link
|
633
|
+
To hook the posts up to the home page you've already created, you can add a link
|
634
|
+
to the home page. Open +app/views/home/index.html.erb+ and modify it as follows:
|
415
635
|
|
416
|
-
<
|
636
|
+
<ruby>
|
417
637
|
<h1>Hello, Rails!</h1>
|
418
638
|
<%= link_to "My Blog", posts_path %>
|
419
|
-
</
|
639
|
+
</ruby>
|
420
640
|
|
421
|
-
The +link_to+ method is one of Rails' built-in view helpers. It creates a
|
641
|
+
The +link_to+ method is one of Rails' built-in view helpers. It creates a
|
642
|
+
hyperlink based on text to display and where to go - in this case, to the path
|
643
|
+
for posts.
|
422
644
|
|
423
645
|
h4. Working with Posts in the Browser
|
424
646
|
|
425
|
-
Now you're ready to start working with posts. To do that, navigate to
|
647
|
+
Now you're ready to start working with posts. To do that, navigate to
|
648
|
+
"http://localhost:3000":http://localhost:3000/ and then click the "My Blog"
|
649
|
+
link:
|
426
650
|
|
427
651
|
!images/posts_index.png(Posts Index screenshot)!
|
428
652
|
|
429
|
-
This is the result of Rails rendering the +index+ view of your posts. There
|
653
|
+
This is the result of Rails rendering the +index+ view of your posts. There
|
654
|
+
aren't currently any posts in the database, but if you click the +New Post+ link
|
655
|
+
you can create one. After that, you'll find that you can edit posts, look at
|
656
|
+
their details, or destroy them. All of the logic and HTML to handle this was
|
657
|
+
built by the single +rails generate scaffold+ command.
|
430
658
|
|
431
|
-
TIP: In development mode (which is what you're working in by default), Rails
|
659
|
+
TIP: In development mode (which is what you're working in by default), Rails
|
660
|
+
reloads your application with every browser request, so there's no need to stop
|
661
|
+
and restart the web server.
|
432
662
|
|
433
663
|
Congratulations, you're riding the rails! Now it's time to see how it all works.
|
434
664
|
|
@@ -441,11 +671,16 @@ class Post < ActiveRecord::Base
|
|
441
671
|
end
|
442
672
|
</ruby>
|
443
673
|
|
444
|
-
There isn't much to this file - but note that the +Post+ class inherits from
|
674
|
+
There isn't much to this file - but note that the +Post+ class inherits from
|
675
|
+
+ActiveRecord::Base+. Active Record supplies a great deal of functionality to
|
676
|
+
your Rails models for free, including basic database CRUD (Create, Read, Update,
|
677
|
+
Destroy) operations, data validation, as well as sophisticated search support
|
678
|
+
and the ability to relate multiple models to one another.
|
445
679
|
|
446
680
|
h4. Adding Some Validation
|
447
681
|
|
448
|
-
Rails includes methods to help you validate the data that you send to models.
|
682
|
+
Rails includes methods to help you validate the data that you send to models.
|
683
|
+
Open the +app/models/post.rb+ file and edit it:
|
449
684
|
|
450
685
|
<ruby>
|
451
686
|
class Post < ActiveRecord::Base
|
@@ -455,17 +690,24 @@ class Post < ActiveRecord::Base
|
|
455
690
|
end
|
456
691
|
</ruby>
|
457
692
|
|
458
|
-
These changes will ensure that all posts have a name and a title, and that the
|
693
|
+
These changes will ensure that all posts have a name and a title, and that the
|
694
|
+
title is at least five characters long. Rails can validate a variety of
|
695
|
+
conditions in a model, including the presence or uniqueness of columns, their
|
696
|
+
format, and the existence of associated objects.
|
459
697
|
|
460
698
|
h4. Using the Console
|
461
699
|
|
462
|
-
To see your validations in action, you can use the console. The console is a
|
700
|
+
To see your validations in action, you can use the console. The console is a
|
701
|
+
command-line tool that lets you execute Ruby code in the context of your
|
702
|
+
application:
|
463
703
|
|
464
704
|
<shell>
|
465
705
|
$ rails console
|
466
706
|
</shell>
|
467
707
|
|
468
|
-
TIP: The default console will make changes to your database. You can instead
|
708
|
+
TIP: The default console will make changes to your database. You can instead
|
709
|
+
open a console that will roll back any changes you make by using +rails console
|
710
|
+
--sandbox+.
|
469
711
|
|
470
712
|
After the console loads, you can use it to work with your application's models:
|
471
713
|
|
@@ -482,15 +724,21 @@ After the console loads, you can use it to work with your application's models:
|
|
482
724
|
:name=>["can't be blank"] }>
|
483
725
|
</shell>
|
484
726
|
|
485
|
-
This code shows creating a new +Post+ instance, attempting to save it and
|
727
|
+
This code shows creating a new +Post+ instance, attempting to save it and
|
728
|
+
getting +false+ for a return value (indicating that the save failed), and
|
729
|
+
inspecting the +errors+ of the post.
|
486
730
|
|
487
731
|
When you're finished, type +exit+ and hit +return+ to exit the console.
|
488
732
|
|
489
|
-
TIP: Unlike the development web server, the console does not automatically load
|
733
|
+
TIP: Unlike the development web server, the console does not automatically load
|
734
|
+
your code afresh for each line. If you make changes to your models while the
|
735
|
+
console is open, type +reload!+ at the console prompt to load them.
|
490
736
|
|
491
737
|
h4. Listing All Posts
|
492
738
|
|
493
|
-
The easiest place to start looking at functionality is with the code that lists
|
739
|
+
The easiest place to start looking at functionality is with the code that lists
|
740
|
+
all posts. Open the file +app/controllers/posts_controller.rb+ and look at the
|
741
|
+
+index+ action:
|
494
742
|
|
495
743
|
<ruby>
|
496
744
|
def index
|
@@ -503,11 +751,19 @@ def index
|
|
503
751
|
end
|
504
752
|
</ruby>
|
505
753
|
|
506
|
-
+Post.all+ calls the +Post+ model to return all of the posts currently in the
|
754
|
+
+Post.all+ calls the +Post+ model to return all of the posts currently in the
|
755
|
+
database. The result of this call is an array of posts that we store in an
|
756
|
+
instance variable called +@posts+.
|
507
757
|
|
508
|
-
TIP: For more information on finding records with Active Record, see "Active
|
758
|
+
TIP: For more information on finding records with Active Record, see "Active
|
759
|
+
Record Query Interface":active_record_querying.html.
|
509
760
|
|
510
|
-
The +respond_to+ block handles both HTML and JSON calls to this action. If you
|
761
|
+
The +respond_to+ block handles both HTML and JSON calls to this action. If you
|
762
|
+
browse to "http://localhost:3000/posts.json":http://localhost:3000/posts.json,
|
763
|
+
you'll see a JSON containing all of the posts. The HTML format looks for a view
|
764
|
+
in +app/views/posts/+ with a name that corresponds to the action name. Rails
|
765
|
+
makes all of the instance variables from the action available to the view.
|
766
|
+
Here's +app/views/posts/index.html.erb+:
|
511
767
|
|
512
768
|
<erb>
|
513
769
|
<h1>Listing posts</h1>
|
@@ -539,18 +795,31 @@ The +respond_to+ block handles both HTML and JSON calls to this action. If you b
|
|
539
795
|
<%= link_to 'New post', new_post_path %>
|
540
796
|
</erb>
|
541
797
|
|
542
|
-
This view iterates over the contents of the +@posts+ array to display content
|
798
|
+
This view iterates over the contents of the +@posts+ array to display content
|
799
|
+
and links. A few things to note in the view:
|
543
800
|
|
544
801
|
* +link_to+ builds a hyperlink to a particular destination
|
545
802
|
* +edit_post_path+ and +new_post_path+ are helpers that Rails provides as part of RESTful routing. You'll see a variety of these helpers for the different actions that the controller includes.
|
546
803
|
|
547
|
-
NOTE. In previous versions of Rails, you had to use +<%=h post.name %>+ so
|
804
|
+
NOTE. In previous versions of Rails, you had to use +<%=h post.name %>+ so
|
805
|
+
that any HTML would be escaped before being inserted into the page. In Rails
|
806
|
+
3.0, this is now the default. To get unescaped HTML, you now use +<%= raw
|
807
|
+
post.name %>+.
|
548
808
|
|
549
|
-
TIP: For more details on the rendering process, see "Layouts and Rendering in
|
809
|
+
TIP: For more details on the rendering process, see "Layouts and Rendering in
|
810
|
+
Rails":layouts_and_rendering.html.
|
550
811
|
|
551
812
|
h4. Customizing the Layout
|
552
813
|
|
553
|
-
The view is only part of the story of how HTML is displayed in your web browser.
|
814
|
+
The view is only part of the story of how HTML is displayed in your web browser.
|
815
|
+
Rails also has the concept of +layouts+, which are containers for views. When
|
816
|
+
Rails renders a view to the browser, it does so by putting the view's HTML into
|
817
|
+
a layout's HTML. In previous versions of Rails, the +rails generate scaffold+
|
818
|
+
command would automatically create a controller specific layout, like
|
819
|
+
+app/views/layouts/posts.html.erb+, for the posts controller. However this has
|
820
|
+
been changed in Rails 3.0. An application specific +layout+ is used for all the
|
821
|
+
controllers and can be found in +app/views/layouts/application.html.erb+. Open
|
822
|
+
this layout in your editor and modify the +body+ tag:
|
554
823
|
|
555
824
|
<erb>
|
556
825
|
<!DOCTYPE html>
|
@@ -569,11 +838,13 @@ The view is only part of the story of how HTML is displayed in your web browser.
|
|
569
838
|
</html>
|
570
839
|
</erb>
|
571
840
|
|
572
|
-
Now when you refresh the +/posts+ page, you'll see a gray background to the
|
841
|
+
Now when you refresh the +/posts+ page, you'll see a gray background to the
|
842
|
+
page. This same gray background will be used throughout all the views for posts.
|
573
843
|
|
574
844
|
h4. Creating New Posts
|
575
845
|
|
576
|
-
Creating a new post involves two actions. The first is the +new+ action, which
|
846
|
+
Creating a new post involves two actions. The first is the +new+ action, which
|
847
|
+
instantiates an empty +Post+ object:
|
577
848
|
|
578
849
|
<ruby>
|
579
850
|
def new
|
@@ -596,9 +867,15 @@ The +new.html.erb+ view displays this empty Post to the user:
|
|
596
867
|
<%= link_to 'Back', posts_path %>
|
597
868
|
</erb>
|
598
869
|
|
599
|
-
The +<%= render 'form' %>+ line is our first introduction to _partials_ in
|
870
|
+
The +<%= render 'form' %>+ line is our first introduction to _partials_ in
|
871
|
+
Rails. A partial is a snippet of HTML and Ruby code that can be reused in
|
872
|
+
multiple locations. In this case, the form used to make a new post, is basically
|
873
|
+
identical to a form used to edit a post, both have text fields for the name and
|
874
|
+
title and a text area for the content with a button to make a new post or update
|
875
|
+
the existing post.
|
600
876
|
|
601
|
-
If you take a look at +views/posts/_form.html.erb+ file, you will see the
|
877
|
+
If you take a look at +views/posts/_form.html.erb+ file, you will see the
|
878
|
+
following:
|
602
879
|
|
603
880
|
<erb>
|
604
881
|
<%= form_for(@post) do |f| %>
|
@@ -631,17 +908,34 @@ If you take a look at +views/posts/_form.html.erb+ file, you will see the follow
|
|
631
908
|
<% end %>
|
632
909
|
</erb>
|
633
910
|
|
634
|
-
This partial receives all the instance variables defined in the calling view
|
911
|
+
This partial receives all the instance variables defined in the calling view
|
912
|
+
file, so in this case, the controller assigned the new Post object to +@post+
|
913
|
+
and so, this is available in both the view and partial as +@post+.
|
635
914
|
|
636
|
-
For more information on partials, refer to the "Layouts and Rendering in
|
915
|
+
For more information on partials, refer to the "Layouts and Rendering in
|
916
|
+
Rails":layouts_and_rendering.html#using-partials guide.
|
637
917
|
|
638
|
-
The +form_for+ block is used to create an HTML form. Within this block, you have
|
918
|
+
The +form_for+ block is used to create an HTML form. Within this block, you have
|
919
|
+
access to methods to build various controls on the form. For example,
|
920
|
+
+f.text_field :name+ tells Rails to create a text input on the form, and to hook
|
921
|
+
it up to the +name+ attribute of the instance being displayed. You can only use
|
922
|
+
these methods with attributes of the model that the form is based on (in this
|
923
|
+
case +name+, +title+, and +content+). Rails uses +form_for+ in preference to
|
924
|
+
having you write raw HTML because the code is more succinct, and because it
|
925
|
+
explicitly ties the form to a particular model instance.
|
639
926
|
|
640
|
-
The +form_for+ block is also smart enough to work out if you are doing a _New
|
927
|
+
The +form_for+ block is also smart enough to work out if you are doing a _New
|
928
|
+
Post_ or an _Edit Post_ action, and will set the form +action+ tags and submit
|
929
|
+
button names appropriately in the HTML output.
|
641
930
|
|
642
|
-
TIP: If you need to create an HTML form that displays arbitrary fields, not tied
|
931
|
+
TIP: If you need to create an HTML form that displays arbitrary fields, not tied
|
932
|
+
to a model, you should use the +form_tag+ method, which provides shortcuts for
|
933
|
+
building forms that are not necessarily tied to a model instance.
|
643
934
|
|
644
|
-
When the user clicks the +Create Post+ button on this form, the browser will
|
935
|
+
When the user clicks the +Create Post+ button on this form, the browser will
|
936
|
+
send information back to the +create+ method of the controller (Rails knows to
|
937
|
+
call the +create+ method because the form is sent with an HTTP POST request;
|
938
|
+
that's one of the conventions that I mentioned earlier):
|
645
939
|
|
646
940
|
<ruby>
|
647
941
|
def create
|
@@ -662,15 +956,32 @@ def create
|
|
662
956
|
end
|
663
957
|
</ruby>
|
664
958
|
|
665
|
-
The +create+ action instantiates a new Post object from the data supplied by the
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
959
|
+
The +create+ action instantiates a new Post object from the data supplied by the
|
960
|
+
user on the form, which Rails makes available in the +params+ hash. After
|
961
|
+
successfully saving the new post, +create+ returns the appropriate format that
|
962
|
+
the user has requested (HTML in our case). It then redirects the user to the
|
963
|
+
resulting post +show+ action and sets a notice to the user that the Post was
|
964
|
+
successfully created.
|
965
|
+
|
966
|
+
If the post was not successfully saved, due to a validation error, then the
|
967
|
+
controller returns the user back to the +new+ action with any error messages so
|
968
|
+
that the user has the chance to fix the error and try again.
|
969
|
+
|
970
|
+
The "Post was successfully created." message is stored inside of the Rails
|
971
|
+
+flash+ hash, (usually just called _the flash_) so that messages can be carried
|
972
|
+
over to another action, providing the user with useful information on the status
|
973
|
+
of their request. In the case of +create+, the user never actually sees any page
|
974
|
+
rendered during the Post creation process, because it immediately redirects to
|
975
|
+
the new Post as soon Rails saves the record. The Flash carries over a message to
|
976
|
+
the next action, so that when the user is redirected back to the +show+ action,
|
977
|
+
they are presented with a message saying "Post was successfully created."
|
670
978
|
|
671
979
|
h4. Showing an Individual Post
|
672
980
|
|
673
|
-
When you click the +show+ link for a post on the index page, it will bring you
|
981
|
+
When you click the +show+ link for a post on the index page, it will bring you
|
982
|
+
to a URL like +http://localhost:3000/posts/1+. Rails interprets this as a call
|
983
|
+
to the +show+ action for the resource, and passes in +1+ as the +:id+ parameter.
|
984
|
+
Here's the +show+ action:
|
674
985
|
|
675
986
|
<ruby>
|
676
987
|
def show
|
@@ -683,7 +994,9 @@ def show
|
|
683
994
|
end
|
684
995
|
</ruby>
|
685
996
|
|
686
|
-
The +show+ action uses +Post.find+ to search for a single record in the database
|
997
|
+
The +show+ action uses +Post.find+ to search for a single record in the database
|
998
|
+
by its id value. After finding the record, Rails displays it by using
|
999
|
+
+show.html.erb+:
|
687
1000
|
|
688
1001
|
<erb>
|
689
1002
|
<p class="notice"><%= notice %></p>
|
@@ -710,7 +1023,9 @@ The +show+ action uses +Post.find+ to search for a single record in the database
|
|
710
1023
|
|
711
1024
|
h4. Editing Posts
|
712
1025
|
|
713
|
-
Like creating a new post, editing a post is a two-part process. The first step
|
1026
|
+
Like creating a new post, editing a post is a two-part process. The first step
|
1027
|
+
is a request to +edit_post_path(@post)+ with a particular post. This calls the
|
1028
|
+
+edit+ action in the controller:
|
714
1029
|
|
715
1030
|
<ruby>
|
716
1031
|
def edit
|
@@ -718,7 +1033,8 @@ def edit
|
|
718
1033
|
end
|
719
1034
|
</ruby>
|
720
1035
|
|
721
|
-
After finding the requested post, Rails uses the +edit.html.erb+ view to display
|
1036
|
+
After finding the requested post, Rails uses the +edit.html.erb+ view to display
|
1037
|
+
it:
|
722
1038
|
|
723
1039
|
<erb>
|
724
1040
|
<h1>Editing post</h1>
|
@@ -729,9 +1045,12 @@ After finding the requested post, Rails uses the +edit.html.erb+ view to display
|
|
729
1045
|
<%= link_to 'Back', posts_path %>
|
730
1046
|
</erb>
|
731
1047
|
|
732
|
-
Again, as with the +new+ action, the +edit+ action is using the +form+ partial,
|
1048
|
+
Again, as with the +new+ action, the +edit+ action is using the +form+ partial,
|
1049
|
+
this time however, the form will do a PUT action to the PostsController and the
|
1050
|
+
submit button will display "Update Post"
|
733
1051
|
|
734
|
-
Submitting the form created by this view will invoke the +update+ action within
|
1052
|
+
Submitting the form created by this view will invoke the +update+ action within
|
1053
|
+
the controller:
|
735
1054
|
|
736
1055
|
<ruby>
|
737
1056
|
def update
|
@@ -751,11 +1070,17 @@ def update
|
|
751
1070
|
end
|
752
1071
|
</ruby>
|
753
1072
|
|
754
|
-
In the +update+ action, Rails first uses the +:id+ parameter passed back from
|
1073
|
+
In the +update+ action, Rails first uses the +:id+ parameter passed back from
|
1074
|
+
the edit view to locate the database record that's being edited. The
|
1075
|
+
+update_attributes+ call then takes the rest of the parameters from the request
|
1076
|
+
and applies them to this record. If all goes well, the user is redirected to the
|
1077
|
+
post's +show+ view. If there are any problems, it's back to the +edit+ view to
|
1078
|
+
correct them.
|
755
1079
|
|
756
1080
|
h4. Destroying a Post
|
757
1081
|
|
758
|
-
Finally, clicking one of the +destroy+ links sends the associated id to the
|
1082
|
+
Finally, clicking one of the +destroy+ links sends the associated id to the
|
1083
|
+
+destroy+ action:
|
759
1084
|
|
760
1085
|
<ruby>
|
761
1086
|
def destroy
|
@@ -769,15 +1094,25 @@ def destroy
|
|
769
1094
|
end
|
770
1095
|
</ruby>
|
771
1096
|
|
772
|
-
The +destroy+ method of an Active Record model instance removes the
|
1097
|
+
The +destroy+ method of an Active Record model instance removes the
|
1098
|
+
corresponding record from the database. After that's done, there isn't any
|
1099
|
+
record to display, so Rails redirects the user's browser to the index view for
|
1100
|
+
the model.
|
773
1101
|
|
774
1102
|
h3. Adding a Second Model
|
775
1103
|
|
776
|
-
Now that you've seen how a model built with scaffolding looks like, it's time to
|
1104
|
+
Now that you've seen how a model built with scaffolding looks like, it's time to
|
1105
|
+
add a second model to the application. The second model will handle comments on
|
1106
|
+
blog posts.
|
777
1107
|
|
778
1108
|
h4. Generating a Model
|
779
1109
|
|
780
|
-
Models in Rails use a singular name, and their corresponding database tables use
|
1110
|
+
Models in Rails use a singular name, and their corresponding database tables use
|
1111
|
+
a plural name. For the model to hold comments, the convention is to use the name
|
1112
|
+
Comment. Even if you don't want to use the entire apparatus set up by
|
1113
|
+
scaffolding, most Rails developers still use generators to make things like
|
1114
|
+
models and controllers. To create the new model, run this command in your
|
1115
|
+
terminal:
|
781
1116
|
|
782
1117
|
<shell>
|
783
1118
|
$ rails generate model Comment commenter:string body:text post:references
|
@@ -797,9 +1132,12 @@ class Comment < ActiveRecord::Base
|
|
797
1132
|
end
|
798
1133
|
</ruby>
|
799
1134
|
|
800
|
-
This is very similar to the +post.rb+ model that you saw earlier. The difference
|
1135
|
+
This is very similar to the +post.rb+ model that you saw earlier. The difference
|
1136
|
+
is the line +belongs_to :post+, which sets up an Active Record _association_.
|
1137
|
+
You'll learn a little about associations in the next section of this guide.
|
801
1138
|
|
802
|
-
In addition to the model, Rails has also made a migration to create the
|
1139
|
+
In addition to the model, Rails has also made a migration to create the
|
1140
|
+
corresponding database table:
|
803
1141
|
|
804
1142
|
<ruby>
|
805
1143
|
class CreateComments < ActiveRecord::Migration
|
@@ -817,13 +1155,16 @@ class CreateComments < ActiveRecord::Migration
|
|
817
1155
|
end
|
818
1156
|
</ruby>
|
819
1157
|
|
820
|
-
The +t.references+ line sets up a foreign key column for the association between
|
1158
|
+
The +t.references+ line sets up a foreign key column for the association between
|
1159
|
+
the two models. And the +add_index+ line sets up an index for this association
|
1160
|
+
column. Go ahead and run the migration:
|
821
1161
|
|
822
1162
|
<shell>
|
823
1163
|
$ rake db:migrate
|
824
1164
|
</shell>
|
825
1165
|
|
826
|
-
Rails is smart enough to only execute the migrations that have not already been
|
1166
|
+
Rails is smart enough to only execute the migrations that have not already been
|
1167
|
+
run against the current database, so in this case you will just see:
|
827
1168
|
|
828
1169
|
<shell>
|
829
1170
|
== CreateComments: migrating =================================================
|
@@ -834,12 +1175,16 @@ Rails is smart enough to only execute the migrations that have not already been
|
|
834
1175
|
|
835
1176
|
h4. Associating Models
|
836
1177
|
|
837
|
-
Active Record associations let you easily declare the relationship between two
|
1178
|
+
Active Record associations let you easily declare the relationship between two
|
1179
|
+
models. In the case of comments and posts, you could write out the relationships
|
1180
|
+
this way:
|
838
1181
|
|
839
1182
|
* Each comment belongs to one post
|
840
1183
|
* One post can have many comments
|
841
1184
|
|
842
|
-
In fact, this is very close to the syntax that Rails uses to declare this
|
1185
|
+
In fact, this is very close to the syntax that Rails uses to declare this
|
1186
|
+
association. You've already seen the line of code inside the Comment model that
|
1187
|
+
makes each comment belong to a Post:
|
843
1188
|
|
844
1189
|
<ruby>
|
845
1190
|
class Comment < ActiveRecord::Base
|
@@ -859,13 +1204,20 @@ class Post < ActiveRecord::Base
|
|
859
1204
|
end
|
860
1205
|
</ruby>
|
861
1206
|
|
862
|
-
These two declarations enable a good bit of automatic behavior. For example, if
|
1207
|
+
These two declarations enable a good bit of automatic behavior. For example, if
|
1208
|
+
you have an instance variable +@post+ containing a post, you can retrieve all
|
1209
|
+
the comments belonging to that post as the array +@post.comments+.
|
863
1210
|
|
864
|
-
TIP: For more information on Active Record associations, see the "Active Record
|
1211
|
+
TIP: For more information on Active Record associations, see the "Active Record
|
1212
|
+
Associations":association_basics.html guide.
|
865
1213
|
|
866
1214
|
h4. Adding a Route for Comments
|
867
1215
|
|
868
|
-
As with the +home+ controller, we will need to add a route so that Rails knows
|
1216
|
+
As with the +home+ controller, we will need to add a route so that Rails knows
|
1217
|
+
where we would like to navigate to see +comments+. Open up the
|
1218
|
+
+config/routes.rb+ file again, you will see an entry that was added
|
1219
|
+
automatically for +posts+ near the top by the scaffold generator, +resources
|
1220
|
+
:posts+, edit it as follows:
|
869
1221
|
|
870
1222
|
<ruby>
|
871
1223
|
resources :posts do
|
@@ -873,29 +1225,40 @@ resources :posts do
|
|
873
1225
|
end
|
874
1226
|
</ruby>
|
875
1227
|
|
876
|
-
This creates +comments+ as a _nested resource_ within +posts+. This is another
|
1228
|
+
This creates +comments+ as a _nested resource_ within +posts+. This is another
|
1229
|
+
part of capturing the hierarchical relationship that exists between posts and
|
1230
|
+
comments.
|
877
1231
|
|
878
|
-
TIP: For more information on routing, see the "Rails Routing from the Outside
|
1232
|
+
TIP: For more information on routing, see the "Rails Routing from the Outside
|
1233
|
+
In":routing.html guide.
|
879
1234
|
|
880
1235
|
h4. Generating a Controller
|
881
1236
|
|
882
|
-
With the model in hand, you can turn your attention to creating a matching
|
1237
|
+
With the model in hand, you can turn your attention to creating a matching
|
1238
|
+
controller. Again, there's a generator for this:
|
883
1239
|
|
884
1240
|
<shell>
|
885
1241
|
$ rails generate controller Comments
|
886
1242
|
</shell>
|
887
1243
|
|
888
|
-
This creates
|
1244
|
+
This creates six files and one empty directory:
|
889
1245
|
|
890
1246
|
* +app/controllers/comments_controller.rb+ - The controller
|
891
1247
|
* +app/helpers/comments_helper.rb+ - A view helper file
|
892
1248
|
* +test/functional/comments_controller_test.rb+ - The functional tests for the controller
|
893
1249
|
* +test/unit/helpers/comments_helper_test.rb+ - The unit tests for the helper
|
894
1250
|
* +app/views/comments/+ - Views of the controller are stored here
|
1251
|
+
* +app/assets/stylesheets/comment.css.scss+ - Cascading style sheet for the controller
|
1252
|
+
* +app/assets/javascripts/comment.js.coffee+ - CoffeeScript for the controller
|
895
1253
|
|
896
|
-
Like with any blog, our readers will create their comments directly after
|
1254
|
+
Like with any blog, our readers will create their comments directly after
|
1255
|
+
reading the post, and once they have added their comment, will be sent back to
|
1256
|
+
the post show page to see their comment now listed. Due to this, our
|
1257
|
+
+CommentsController+ is there to provide a method to create comments and delete
|
1258
|
+
SPAM comments when they arrive.
|
897
1259
|
|
898
|
-
So first, we'll wire up the Post show template
|
1260
|
+
So first, we'll wire up the Post show template
|
1261
|
+
(+/app/views/posts/show.html.erb+) to let us make a new comment:
|
899
1262
|
|
900
1263
|
<erb>
|
901
1264
|
<p class="notice"><%= notice %></p>
|
@@ -934,7 +1297,8 @@ So first, we'll wire up the Post show template (+/app/views/posts/show.html.erb+
|
|
934
1297
|
<%= link_to 'Back to Posts', posts_path %> |
|
935
1298
|
</erb>
|
936
1299
|
|
937
|
-
This adds a form on the Post show page that creates a new comment, which will
|
1300
|
+
This adds a form on the Post show page that creates a new comment, which will
|
1301
|
+
call the +CommentsController+ +create+ action, so let's wire that up:
|
938
1302
|
|
939
1303
|
<ruby>
|
940
1304
|
class CommentsController < ApplicationController
|
@@ -946,11 +1310,21 @@ class CommentsController < ApplicationController
|
|
946
1310
|
end
|
947
1311
|
</ruby>
|
948
1312
|
|
949
|
-
You'll see a bit more complexity here than you did in the controller for posts.
|
1313
|
+
You'll see a bit more complexity here than you did in the controller for posts.
|
1314
|
+
That's a side-effect of the nesting that you've set up; each request for a
|
1315
|
+
comment has to keep track of the post to which the comment is attached, thus the
|
1316
|
+
initial find action to the Post model to get the post in question.
|
950
1317
|
|
951
|
-
In addition, the code takes advantage of some of the methods available for an
|
1318
|
+
In addition, the code takes advantage of some of the methods available for an
|
1319
|
+
association. We use the +create+ method on +@post.comments+ to create and save
|
1320
|
+
the comment. This will automatically link the comment so that it belongs to that
|
1321
|
+
particular post.
|
952
1322
|
|
953
|
-
Once we have made the new comment, we send the user back to the original post
|
1323
|
+
Once we have made the new comment, we send the user back to the original post
|
1324
|
+
using the +post_path(@post)+ helper. As we have already seen, this calls the
|
1325
|
+
+show+ action of the +PostsController+ which in turn renders the +show.html.erb+
|
1326
|
+
template. This is where we want the comment to show, so let's add that to the
|
1327
|
+
+app/views/posts/show.html.erb+.
|
954
1328
|
|
955
1329
|
<erb>
|
956
1330
|
<p class="notice"><%= notice %></p>
|
@@ -1004,15 +1378,20 @@ Once we have made the new comment, we send the user back to the original post us
|
|
1004
1378
|
<%= link_to 'Back to Posts', posts_path %> |
|
1005
1379
|
</erb>
|
1006
1380
|
|
1007
|
-
Now you can add posts and comments to your blog and have them show up in the
|
1381
|
+
Now you can add posts and comments to your blog and have them show up in the
|
1382
|
+
right places.
|
1008
1383
|
|
1009
1384
|
h3. Refactoring
|
1010
1385
|
|
1011
|
-
Now that we have Posts and Comments working, if we take a look at the
|
1386
|
+
Now that we have Posts and Comments working, if we take a look at the
|
1387
|
+
+app/views/posts/show.html.erb+ template, it's getting long and awkward. We can
|
1388
|
+
use partials to clean this up.
|
1012
1389
|
|
1013
1390
|
h4. Rendering Partial Collections
|
1014
1391
|
|
1015
|
-
First we will make a comment partial to extract showing all the comments for the
|
1392
|
+
First we will make a comment partial to extract showing all the comments for the
|
1393
|
+
post. Create the file +app/views/comments/_comment.html.erb+ and put the
|
1394
|
+
following into it:
|
1016
1395
|
|
1017
1396
|
<erb>
|
1018
1397
|
<p>
|
@@ -1026,7 +1405,8 @@ First we will make a comment partial to extract showing all the comments for the
|
|
1026
1405
|
</p>
|
1027
1406
|
</erb>
|
1028
1407
|
|
1029
|
-
Then in the +app/views/posts/show.html.erb+ you can change it to look like the
|
1408
|
+
Then in the +app/views/posts/show.html.erb+ you can change it to look like the
|
1409
|
+
following:
|
1030
1410
|
|
1031
1411
|
<erb>
|
1032
1412
|
<p class="notice"><%= notice %></p>
|
@@ -1070,11 +1450,16 @@ Then in the +app/views/posts/show.html.erb+ you can change it to look like the f
|
|
1070
1450
|
<%= link_to 'Back to Posts', posts_path %> |
|
1071
1451
|
</erb>
|
1072
1452
|
|
1073
|
-
This will now render the partial in +app/views/comments/_comment.html.erb+ once
|
1453
|
+
This will now render the partial in +app/views/comments/_comment.html.erb+ once
|
1454
|
+
for each comment that is in the +@post.comments+ collection. As the +render+
|
1455
|
+
method iterates over the <tt>@post.comments</tt> collection, it assigns each
|
1456
|
+
comment to a local variable named the same as the partial, in this case
|
1457
|
+
+comment+ which is then available in the partial for us to show.
|
1074
1458
|
|
1075
1459
|
h4. Rendering a Partial Form
|
1076
1460
|
|
1077
|
-
Lets also move that new comment section out to it's own partial, again, you
|
1461
|
+
Lets also move that new comment section out to it's own partial, again, you
|
1462
|
+
create a file +app/views/comments/_form.html.erb+ and in it you put:
|
1078
1463
|
|
1079
1464
|
<erb>
|
1080
1465
|
<%= form_for([@post, @post.comments.build]) do |f| %>
|
@@ -1124,15 +1509,22 @@ Then you make the +app/views/posts/show.html.erb+ look like the following:
|
|
1124
1509
|
<%= link_to 'Back to Posts', posts_path %> |
|
1125
1510
|
</erb>
|
1126
1511
|
|
1127
|
-
The second render just defines the partial template we want to render,
|
1512
|
+
The second render just defines the partial template we want to render,
|
1513
|
+
<tt>comments/form</tt>, Rails is smart enough to spot the forward slash in that
|
1514
|
+
string and realize that you want to render the <tt>_form.html.erb</tt> file in
|
1515
|
+
the <tt>app/views/comments</tt> directory.
|
1128
1516
|
|
1129
|
-
The +@post+ object is available to any partials rendered in the view because we
|
1517
|
+
The +@post+ object is available to any partials rendered in the view because we
|
1518
|
+
defined it as an instance variable.
|
1130
1519
|
|
1131
1520
|
h3. Deleting Comments
|
1132
1521
|
|
1133
|
-
Another important feature on a blog is being able to delete SPAM comments. To do
|
1522
|
+
Another important feature on a blog is being able to delete SPAM comments. To do
|
1523
|
+
this, we need to implement a link of some sort in the view and a +DELETE+ action
|
1524
|
+
in the +CommentsController+.
|
1134
1525
|
|
1135
|
-
So first, let's add the delete link in the
|
1526
|
+
So first, let's add the delete link in the
|
1527
|
+
+app/views/comments/_comment.html.erb+ partial:
|
1136
1528
|
|
1137
1529
|
<erb>
|
1138
1530
|
<p>
|
@@ -1152,7 +1544,10 @@ So first, let's add the delete link in the +app/views/comments/_comment.html.erb
|
|
1152
1544
|
</p>
|
1153
1545
|
</erb>
|
1154
1546
|
|
1155
|
-
Clicking this new "Destroy Comment" link will fire off a <tt>DELETE
|
1547
|
+
Clicking this new "Destroy Comment" link will fire off a <tt>DELETE
|
1548
|
+
/posts/:id/comments/:id</tt> to our +CommentsController+, which can then use
|
1549
|
+
this to find the comment we want to delete, so let's add a destroy action to our
|
1550
|
+
controller:
|
1156
1551
|
|
1157
1552
|
<ruby>
|
1158
1553
|
class CommentsController < ApplicationController
|
@@ -1173,12 +1568,17 @@ class CommentsController < ApplicationController
|
|
1173
1568
|
end
|
1174
1569
|
</ruby>
|
1175
1570
|
|
1176
|
-
The +destroy+ action will find the post we are looking at, locate the comment
|
1571
|
+
The +destroy+ action will find the post we are looking at, locate the comment
|
1572
|
+
within the <tt>@post.comments</tt> collection, and then remove it from the
|
1573
|
+
database and send us back to the show action for the post.
|
1177
1574
|
|
1178
1575
|
|
1179
1576
|
h4. Deleting Associated Objects
|
1180
1577
|
|
1181
|
-
If you delete a post then its associated comments will also need to be deleted.
|
1578
|
+
If you delete a post then its associated comments will also need to be deleted.
|
1579
|
+
Otherwise they would simply occupy space in the database. Rails allows you to
|
1580
|
+
use the +dependent+ option of an association to achieve this. Modify the Post
|
1581
|
+
model, +app/models/post.rb+, as follows:
|
1182
1582
|
|
1183
1583
|
<ruby>
|
1184
1584
|
class Post < ActiveRecord::Base
|
@@ -1191,13 +1591,20 @@ end
|
|
1191
1591
|
|
1192
1592
|
h3. Security
|
1193
1593
|
|
1194
|
-
If you were to publish your blog online, anybody would be able to add, edit and
|
1594
|
+
If you were to publish your blog online, anybody would be able to add, edit and
|
1595
|
+
delete posts or delete comments.
|
1195
1596
|
|
1196
|
-
Rails provides a very simple HTTP authentication system that will work nicely in
|
1597
|
+
Rails provides a very simple HTTP authentication system that will work nicely in
|
1598
|
+
this situation.
|
1197
1599
|
|
1198
|
-
In the +PostsController+ we need to have a way to block access to the various
|
1600
|
+
In the +PostsController+ we need to have a way to block access to the various
|
1601
|
+
actions if the person is not authenticated, here we can use the Rails
|
1602
|
+
<tt>http_basic_authenticate_with</tt> method, allowing access to the requested
|
1603
|
+
action if that method allows it.
|
1199
1604
|
|
1200
|
-
To use the authentication system, we specify it at the top of our
|
1605
|
+
To use the authentication system, we specify it at the top of our
|
1606
|
+
+PostsController+, in this case, we want the user to be authenticated on every
|
1607
|
+
action, except for +index+ and +show+, so we write that:
|
1201
1608
|
|
1202
1609
|
<ruby>
|
1203
1610
|
class PostsController < ApplicationController
|
@@ -1212,7 +1619,8 @@ class PostsController < ApplicationController
|
|
1212
1619
|
# snipped for brevity
|
1213
1620
|
</ruby>
|
1214
1621
|
|
1215
|
-
We also only want to allow authenticated users to delete comments, so in the
|
1622
|
+
We also only want to allow authenticated users to delete comments, so in the
|
1623
|
+
+CommentsController+ we write:
|
1216
1624
|
|
1217
1625
|
<ruby>
|
1218
1626
|
class CommentsController < ApplicationController
|
@@ -1224,16 +1632,21 @@ class CommentsController < ApplicationController
|
|
1224
1632
|
# snipped for brevity
|
1225
1633
|
</ruby>
|
1226
1634
|
|
1227
|
-
Now if you try to create a new post, you will be greeted with a basic HTTP
|
1635
|
+
Now if you try to create a new post, you will be greeted with a basic HTTP
|
1636
|
+
Authentication challenge
|
1228
1637
|
|
1229
1638
|
!images/challenge.png(Basic HTTP Authentication Challenge)!
|
1230
1639
|
|
1231
1640
|
|
1232
1641
|
h3. Building a Multi-Model Form
|
1233
1642
|
|
1234
|
-
Another feature of your average blog is the ability to tag posts. To implement
|
1643
|
+
Another feature of your average blog is the ability to tag posts. To implement
|
1644
|
+
this feature your application needs to interact with more than one model on a
|
1645
|
+
single form. Rails offers support for nested forms.
|
1235
1646
|
|
1236
|
-
To demonstrate this, we will add support for giving each post multiple tags,
|
1647
|
+
To demonstrate this, we will add support for giving each post multiple tags,
|
1648
|
+
right in the form where you create the post. First, create a new model to hold
|
1649
|
+
the tags:
|
1237
1650
|
|
1238
1651
|
<shell>
|
1239
1652
|
$ rails generate model tag name:string post:references
|
@@ -1245,7 +1658,9 @@ Again, run the migration to create the database table:
|
|
1245
1658
|
$ rake db:migrate
|
1246
1659
|
</shell>
|
1247
1660
|
|
1248
|
-
Next, edit the +post.rb+ file to create the other side of the association, and
|
1661
|
+
Next, edit the +post.rb+ file to create the other side of the association, and
|
1662
|
+
to tell Rails (via the +accepts_nested_attributes_for+ macro) that you intend to
|
1663
|
+
edit tags via posts:
|
1249
1664
|
|
1250
1665
|
<ruby>
|
1251
1666
|
class Post < ActiveRecord::Base
|
@@ -1261,7 +1676,10 @@ class Post < ActiveRecord::Base
|
|
1261
1676
|
end
|
1262
1677
|
</ruby>
|
1263
1678
|
|
1264
|
-
The +:allow_destroy+ option on the nested attribute declaration tells Rails to
|
1679
|
+
The +:allow_destroy+ option on the nested attribute declaration tells Rails to
|
1680
|
+
display a "remove" checkbox on the view that you'll build shortly. The
|
1681
|
+
+:reject_if+ option prevents saving new tags that do not have any attributes
|
1682
|
+
filled in.
|
1265
1683
|
|
1266
1684
|
We will modify +views/posts/_form.html.erb+ to render a partial to make a tag:
|
1267
1685
|
|
@@ -1300,13 +1718,20 @@ We will modify +views/posts/_form.html.erb+ to render a partial to make a tag:
|
|
1300
1718
|
<% end %>
|
1301
1719
|
</erb>
|
1302
1720
|
|
1303
|
-
Note that we have changed the +f+ in +form_for(@post) do |f|+ to +post_form+ to
|
1721
|
+
Note that we have changed the +f+ in +form_for(@post) do |f|+ to +post_form+ to
|
1722
|
+
make it easier to understand what is going on.
|
1304
1723
|
|
1305
|
-
This example shows another option of the render helper, being able to pass in
|
1724
|
+
This example shows another option of the render helper, being able to pass in
|
1725
|
+
local variables, in this case, we want the local variable +form+ in the partial
|
1726
|
+
to refer to the +post_form+ object.
|
1306
1727
|
|
1307
|
-
We also add a <tt>@post.tags.build</tt> at the top of this form, this is to make
|
1728
|
+
We also add a <tt>@post.tags.build</tt> at the top of this form, this is to make
|
1729
|
+
sure there is a new tag ready to have it's name filled in by the user. If you do
|
1730
|
+
not build the new tag, then the form will not appear as there is no new Tag
|
1731
|
+
object ready to create.
|
1308
1732
|
|
1309
|
-
Now create the folder <tt>app/views/tags</tt> and make a file in there called
|
1733
|
+
Now create the folder <tt>app/views/tags</tt> and make a file in there called
|
1734
|
+
<tt>_form.html.erb</tt> which contains the form for the tag:
|
1310
1735
|
|
1311
1736
|
<erb>
|
1312
1737
|
<%= form.fields_for :tags do |tag_form| %>
|
@@ -1323,7 +1748,8 @@ Now create the folder <tt>app/views/tags</tt> and make a file in there called <t
|
|
1323
1748
|
<% end %>
|
1324
1749
|
</erb>
|
1325
1750
|
|
1326
|
-
Finally, we will edit the <tt>app/views/posts/show.html.erb</tt> template to
|
1751
|
+
Finally, we will edit the <tt>app/views/posts/show.html.erb</tt> template to
|
1752
|
+
show our tags.
|
1327
1753
|
|
1328
1754
|
<erb>
|
1329
1755
|
<p class="notice"><%= notice %></p>
|
@@ -1359,13 +1785,18 @@ Finally, we will edit the <tt>app/views/posts/show.html.erb</tt> template to sho
|
|
1359
1785
|
<%= link_to 'Back to Posts', posts_path %> |
|
1360
1786
|
</erb>
|
1361
1787
|
|
1362
|
-
With these changes in place, you'll find that you can edit a post and its tags
|
1788
|
+
With these changes in place, you'll find that you can edit a post and its tags
|
1789
|
+
directly on the same view.
|
1363
1790
|
|
1364
|
-
However, that method call <tt>@post.tags.map { |t| t.name }.join(", ")</tt> is
|
1791
|
+
However, that method call <tt>@post.tags.map { |t| t.name }.join(", ")</tt> is
|
1792
|
+
awkward, we could handle this by making a helper method.
|
1365
1793
|
|
1366
1794
|
h3. View Helpers
|
1367
1795
|
|
1368
|
-
View Helpers live in <tt>app/helpers</tt> and provide small snippets of reusable
|
1796
|
+
View Helpers live in <tt>app/helpers</tt> and provide small snippets of reusable
|
1797
|
+
code for views. In our case, we want a method that strings a bunch of objects
|
1798
|
+
together using their name attribute and joining them with a comma. As this is
|
1799
|
+
for the Post show template, we put it in the PostsHelper.
|
1369
1800
|
|
1370
1801
|
Open up <tt>app/helpers/posts_helper.rb</tt> and add the following:
|
1371
1802
|
|
@@ -1377,7 +1808,8 @@ module PostsHelper
|
|
1377
1808
|
end
|
1378
1809
|
</erb>
|
1379
1810
|
|
1380
|
-
Now you can edit the view in <tt>app/views/posts/show.html.erb</tt> to look like
|
1811
|
+
Now you can edit the view in <tt>app/views/posts/show.html.erb</tt> to look like
|
1812
|
+
this:
|
1381
1813
|
|
1382
1814
|
<erb>
|
1383
1815
|
<p class="notice"><%= notice %></p>
|
@@ -1415,7 +1847,10 @@ Now you can edit the view in <tt>app/views/posts/show.html.erb</tt> to look like
|
|
1415
1847
|
|
1416
1848
|
h3. What's Next?
|
1417
1849
|
|
1418
|
-
Now that you've seen your first Rails application, you should feel free to
|
1850
|
+
Now that you've seen your first Rails application, you should feel free to
|
1851
|
+
update it and experiment on your own. But you don't have to do everything
|
1852
|
+
without help. As you need assistance getting up and running with Rails, feel
|
1853
|
+
free to consult these support resources:
|
1419
1854
|
|
1420
1855
|
* The "Ruby on Rails guides":index.html
|
1421
1856
|
* The "Ruby on Rails Tutorial":http://railstutorial.org/book
|
@@ -1430,9 +1865,18 @@ Rails also comes with built-in help that you can generate using the rake command
|
|
1430
1865
|
|
1431
1866
|
h3. Configuration Gotchas
|
1432
1867
|
|
1433
|
-
The easiest way to work with Rails is to store all external data as UTF-8. If
|
1434
|
-
|
1435
|
-
|
1868
|
+
The easiest way to work with Rails is to store all external data as UTF-8. If
|
1869
|
+
you don't, Ruby libraries and Rails will often be able to convert your native
|
1870
|
+
data into UTF-8, but this doesn't always work reliably, so you're better off
|
1871
|
+
ensuring that all external data is UTF-8.
|
1872
|
+
|
1873
|
+
If you have made a mistake in this area, the most common symptom is a black
|
1874
|
+
diamond with a question mark inside appearing in the browser. Another common
|
1875
|
+
symptom is characters like "ü" appearing instead of "ü". Rails takes a number
|
1876
|
+
of internal steps to mitigate common causes of these problems that can be
|
1877
|
+
automatically detected and corrected. However, if you have external data that is
|
1878
|
+
not stored as UTF-8, it can occasionally result in these kinds of issues that
|
1879
|
+
cannot be automatically detected by Rails and corrected.
|
1436
1880
|
|
1437
1881
|
Two very common sources of data that are not UTF-8:
|
1438
1882
|
* Your text editor: Most text editors (such as Textmate), default to saving files as
|