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.
Files changed (74) hide show
  1. data/CHANGELOG +7 -9
  2. data/bin/rails +2 -0
  3. data/guides/assets/images/rails_welcome.png +0 -0
  4. data/guides/rails_guides/generator.rb +1 -1
  5. data/guides/rails_guides/textile_extensions.rb +18 -17
  6. data/guides/source/3_0_release_notes.textile +21 -21
  7. data/guides/source/action_controller_overview.textile +1 -1
  8. data/guides/source/action_mailer_basics.textile +27 -6
  9. data/guides/source/action_view_overview.textile +6 -6
  10. data/guides/source/active_record_querying.textile +77 -7
  11. data/guides/source/active_record_validations_callbacks.textile +78 -81
  12. data/guides/source/active_support_core_extensions.textile +87 -31
  13. data/guides/source/ajax_on_rails.textile +1 -1
  14. data/guides/source/api_documentation_guidelines.textile +12 -8
  15. data/guides/source/asset_pipeline.textile +416 -0
  16. data/guides/source/association_basics.textile +2 -4
  17. data/guides/source/caching_with_rails.textile +7 -6
  18. data/guides/source/command_line.textile +78 -116
  19. data/guides/source/configuring.textile +34 -17
  20. data/guides/source/contribute.textile +1 -1
  21. data/guides/source/contributing_to_ruby_on_rails.textile +3 -3
  22. data/guides/source/debugging_rails_applications.textile +2 -2
  23. data/guides/source/form_helpers.textile +40 -51
  24. data/guides/source/getting_started.textile +641 -197
  25. data/guides/source/initialization.textile +4 -4
  26. data/guides/source/layouts_and_rendering.textile +2 -2
  27. data/guides/source/migrations.textile +114 -32
  28. data/guides/source/nested_model_forms.textile +6 -6
  29. data/guides/source/performance_testing.textile +6 -6
  30. data/guides/source/plugins.textile +23 -22
  31. data/guides/source/rails_application_templates.textile +8 -14
  32. data/guides/source/routing.textile +57 -51
  33. data/guides/source/ruby_on_rails_guides_guidelines.textile +3 -3
  34. data/guides/source/security.textile +10 -10
  35. data/guides/source/testing.textile +1 -1
  36. data/lib/rails.rb +27 -1
  37. data/lib/rails/all.rb +1 -0
  38. data/lib/rails/application.rb +4 -10
  39. data/lib/rails/application/configuration.rb +3 -12
  40. data/lib/rails/application/railties.rb +1 -1
  41. data/lib/rails/engine.rb +53 -42
  42. data/lib/rails/generators.rb +1 -1
  43. data/lib/rails/generators/app_base.rb +36 -15
  44. data/lib/rails/generators/generated_attribute.rb +1 -1
  45. data/lib/rails/generators/js/assets/assets_generator.rb +13 -0
  46. data/lib/rails/generators/js/assets/templates/javascript.js +2 -0
  47. data/lib/rails/generators/rails/app/app_generator.rb +3 -1
  48. data/lib/rails/generators/rails/app/templates/Gemfile +11 -7
  49. data/lib/rails/generators/rails/app/templates/config/application.rb +7 -3
  50. data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml +62 -0
  51. data/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml +3 -3
  52. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml +3 -12
  53. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml +3 -3
  54. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +0 -3
  55. data/lib/rails/generators/rails/assets/assets_generator.rb +2 -9
  56. data/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +12 -10
  57. data/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec +5 -2
  58. data/lib/rails/generators/rails/plugin_new/templates/Gemfile +6 -3
  59. data/lib/rails/generators/rails/plugin_new/templates/Rakefile +5 -1
  60. data/lib/rails/generators/rails/plugin_new/templates/app/views/layouts/application.html.erb.tt +14 -0
  61. data/lib/rails/generators/rails/plugin_new/templates/rails/application.rb +5 -3
  62. data/lib/rails/info.rb +4 -0
  63. data/lib/rails/paths.rb +5 -5
  64. data/lib/rails/railtie.rb +4 -4
  65. data/lib/rails/tasks.rb +0 -1
  66. data/lib/rails/tasks/documentation.rake +3 -3
  67. data/lib/rails/tasks/engine.rake +2 -0
  68. data/lib/rails/tasks/framework.rake +3 -3
  69. data/lib/rails/tasks/tmp.rake +1 -1
  70. data/lib/rails/test_unit/testing.rake +2 -2
  71. data/lib/rails/version.rb +1 -1
  72. metadata +19 -33
  73. data/lib/rails/generators/rails/assets/templates/javascript.js.coffee +0 -3
  74. data/lib/rails/tasks/assets.rake +0 -21
@@ -512,7 +512,7 @@ h4. +railties/lib/rails/ruby_version_check.rb+
512
512
 
513
513
  This file simply checks if the Ruby version is less than 1.8.7 or is 1.9.1 and raises an error if that is the case. Rails 3 simply will not run on earlier versions of Ruby than 1.8.7 or 1.9.1.
514
514
 
515
- NOTE: You should always endeavour to run the latest version of Ruby with your Rails applications. The benefits are many, including security fixes and the like, and very often there is a speed increase associated with it. The caveat is that you could have code that potentially breaks on the latest version, which should be fixed to work on the latest version rather than kept around as an excuse not to upgrade.
515
+ NOTE: You should always endeavor to run the latest version of Ruby with your Rails applications. The benefits are many, including security fixes and the like, and very often there is a speed increase associated with it. The caveat is that you could have code that potentially breaks on the latest version, which should be fixed to work on the latest version rather than kept around as an excuse not to upgrade.
516
516
 
517
517
  h4. +active_support/core_ext/kernel/reporting.rb+
518
518
 
@@ -661,9 +661,9 @@ require 'active_support/inflections'
661
661
  require 'active_support/core_ext/string/inflections'
662
662
  </ruby>
663
663
 
664
- The +active_support/inflector/methods+ file has already been required by +active_support/autoload+ and so won't be loaded again here.
664
+ The +active_support/inflector/methods+ file has already been required by +active_support/autoload+ and so won't be loaded again here. The +activesupport/lib/active_support/inflector/inflections.rb+ is required by +active_support/inflector/methods+.
665
665
 
666
- h4. +activesupport/lib/active_support/inflector/inflections.rb+
666
+ h4. +active_support/inflections+
667
667
 
668
668
  This file references the +ActiveSupport::Inflector+ constant which isn't loaded by this point. But there were autoloads set up in +activesupport/lib/active_support.rb+ which will load the file which loads this constant and so then it will be defined. Then this file defines pluralization and singularization rules for words in Rails. This is how Rails knows how to pluralize "tomato" to "tomatoes".
669
669
 
@@ -866,7 +866,7 @@ def +(other)
866
866
  end
867
867
  </ruby>
868
868
 
869
- So this <tt>+</tt> method is overriden to return a new collection comprising of the existing collection as an array and then using the <tt>Array#+</tt> method combines these two collections, returning a "super" +Collection+ object. In this case, the only initializer that's going to be in this new +Collection+ object is the +i18n.callbacks+ initializer.
869
+ So this <tt>+</tt> method is overridden to return a new collection comprising of the existing collection as an array and then using the <tt>Array#+</tt> method combines these two collections, returning a "super" +Collection+ object. In this case, the only initializer that's going to be in this new +Collection+ object is the +i18n.callbacks+ initializer.
870
870
 
871
871
  The next method to be called after this +initializer+ method is the +after_initialize+ method on the +config+ object, which is defined like this:
872
872
 
@@ -94,7 +94,7 @@ NOTE: The actual rendering is done by subclasses of +ActionView::TemplateHandler
94
94
 
95
95
  h4. Using +render+
96
96
 
97
- In most cases, the +ActionController::Base#render+ method does the heavy lifting of rendering your application's content for use by a browser. There are a variety of ways to customise the behaviour of +render+. You can render the default view for a Rails template, or a specific template, or a file, or inline code, or nothing at all. You can render text, JSON, or XML. You can specify the content type or HTTP status of the rendered response as well.
97
+ In most cases, the +ActionController::Base#render+ method does the heavy lifting of rendering your application's content for use by a browser. There are a variety of ways to customize the behaviour of +render+. You can render the default view for a Rails template, or a specific template, or a file, or inline code, or nothing at all. You can render text, JSON, or XML. You can specify the content type or HTTP status of the rendered response as well.
98
98
 
99
99
  TIP: If you want to see the exact results of a call to +render+ without needing to inspect it in a browser, you can call +render_to_string+. This method takes exactly the same options as +render+, but it returns a string instead of sending a response back to the browser.
100
100
 
@@ -123,7 +123,7 @@ Cache-Control: no-cache
123
123
  $
124
124
  </shell>
125
125
 
126
- We see there is an empty response (no data after the +Cache-Control+ line), but the request was successful because Rails has set the response to 200 OK. You can set the +:status+ option on render to change this response. Rendering nothing can be useful for AJAX requests where all you want to send back to the browser is an acknowledgement that the request was completed.
126
+ We see there is an empty response (no data after the +Cache-Control+ line), but the request was successful because Rails has set the response to 200 OK. You can set the +:status+ option on render to change this response. Rendering nothing can be useful for AJAX requests where all you want to send back to the browser is an acknowledgment that the request was completed.
127
127
 
128
128
  TIP: You should probably be using the +head+ method, discussed later in this guide, instead of +render :nothing+. This provides additional flexibility and makes it explicit that you're only generating HTTP headers.
129
129
 
@@ -17,7 +17,7 @@ endprologue.
17
17
 
18
18
  h3. Anatomy of a Migration
19
19
 
20
- Before I dive into the details of a migration, here are a few examples of the sorts of things you can do:
20
+ Before we dive into the details of a migration, here are a few examples of the sorts of things you can do:
21
21
 
22
22
  <ruby>
23
23
  class CreateProducts < ActiveRecord::Migration
@@ -117,6 +117,33 @@ Occasionally you will make a mistake when writing a migration. If you have alrea
117
117
 
118
118
  In general editing existing migrations is not a good idea: you will be creating extra work for yourself and your co-workers and cause major headaches if the existing version of the migration has already been run on production machines. Instead you should write a new migration that performs the changes you require. Editing a freshly generated migration that has not yet been committed to source control (or more generally which has not been propagated beyond your development machine) is relatively harmless.
119
119
 
120
+ h4. Supported Types
121
+
122
+ Active Record supports the following types:
123
+
124
+ * +:primary_key+
125
+ * +:string+
126
+ * +:text+
127
+ * +:integer+
128
+ * +:float+
129
+ * +:decimal+
130
+ * +:datetime+
131
+ * +:timestamp+
132
+ * +:time+
133
+ * +:date+
134
+ * +:binary+
135
+ * +:boolean+
136
+
137
+ These will be mapped onto an appropriate underlying database type, for example with MySQL +:string+ is mapped to +VARCHAR(255)+. You can create columns of types not supported by Active Record when using the non-sexy syntax, for example
138
+
139
+ <ruby>
140
+ create_table :products do |t|
141
+ t.column :name, 'polygon', :null => false
142
+ end
143
+ </ruby>
144
+
145
+ This may however hinder portability to other databases.
146
+
120
147
  h3. Creating a Migration
121
148
 
122
149
  h4. Creating a Model
@@ -261,18 +288,6 @@ end
261
288
 
262
289
  will append +ENGINE=BLACKHOLE+ to the SQL statement used to create the table (when using MySQL the default is +ENGINE=InnoDB+).
263
290
 
264
- The types supported by Active Record are +:primary_key+, +:string+, +:text+, +:integer+, +:float+, +:decimal+, +:datetime+, +:timestamp+, +:time+, +:date+, +:binary+, +:boolean+.
265
-
266
- These will be mapped onto an appropriate underlying database type, for example with MySQL +:string+ is mapped to +VARCHAR(255)+. You can create columns of types not supported by Active Record when using the non-sexy syntax, for example
267
-
268
- <ruby>
269
- create_table :products do |t|
270
- t.column :name, 'polygon', :null => false
271
- end
272
- </ruby>
273
-
274
- This may however hinder portability to other databases.
275
-
276
291
  h4. Changing Tables
277
292
 
278
293
  A close cousin of +create_table+ is +change_table+, used for changing existing tables. It is used in a similar fashion to +create_table+ but the object yielded to the block knows more tricks. For example
@@ -344,7 +359,7 @@ The +change+ method removes the need to write both +up+ and +down+ methods in th
344
359
 
345
360
  * +add_column+
346
361
  * +add_index+
347
- * +add_timestamp+
362
+ * +add_timestamps+
348
363
  * +create_table+
349
364
  * +remove_timestamps+
350
365
  * +rename_column+
@@ -462,7 +477,7 @@ Several methods are provided that allow you to control all this:
462
477
 
463
478
  For example, this migration
464
479
 
465
- <ruby>
480
+ <pre>
466
481
  class CreateProducts < ActiveRecord::Migration
467
482
  def change
468
483
  suppress_messages do
@@ -481,7 +496,7 @@ class CreateProducts < ActiveRecord::Migration
481
496
  end
482
497
  end
483
498
  end
484
- </ruby>
499
+ </pre>
485
500
 
486
501
  generates the following output
487
502
 
@@ -499,40 +514,107 @@ If you just want Active Record to shut up then running +rake db:migrate VERBOSE=
499
514
 
500
515
  h3. Using Models in Your Migrations
501
516
 
502
- When creating or updating data in a migration it is often tempting to use one of your models. After all they exist to provide easy access to the underlying data. This can be done but some caution should be observed.
517
+ When creating or updating data in a migration it is often tempting to use one of your models. After all they exist to provide easy access to the underlying data. This can be done, but some caution should be observed.
503
518
 
504
- Consider for example a migration that uses the +Product+ model to update a row in the corresponding table. Alice later updates the +Product+ model, adding a new column and a validation on it. Bob comes back from holiday, updates the source and runs outstanding migrations with +rake db:migrate+, including the one that used the +Product+ model. When the migration runs the source is up to date and so the +Product+ model has the validation added by Alice. The database however is still old and so does not have that column and an error ensues because that validation is on a column that does not yet exist.
519
+ For example, problems occur when the model uses database columns which are (1) not currently in the database and (2) will be created by this or a subsequent migration.
505
520
 
506
- Frequently I just want to update rows in the database without writing out the SQL by hand: I'm not using anything specific to the model. One pattern for this is to define a copy of the model inside the migration itself, for example:
521
+ Consider this example, where Alice and Bob are working on the same code base which contains a +Product+ model:
507
522
 
508
- <ruby>
509
- class AddPartNumberToProducts < ActiveRecord::Migration
510
- class Product < ActiveRecord::Base
523
+ Bob goes on vacation.
524
+
525
+ Alice creates a migration for the +products+ table which adds a new column and initializes it.
526
+ She also adds a validation to the Product model for the new column.
527
+
528
+ <pre>
529
+ # db/migrate/20100513121110_add_flag_to_product.rb
530
+
531
+ class AddFlagToProduct < ActiveRecord::Migration
532
+ def change
533
+ add_column :products, :flag, :int
534
+ Product.all.each { |f| f.update_attributes!(:flag => 'false') }
511
535
  end
536
+ end
537
+ </pre>
538
+
539
+ <pre>
540
+ # app/model/product.rb
541
+
542
+ class Product < ActiveRecord::Base
543
+ validates_presence_of :flag
544
+ end
545
+ </pre>
546
+
547
+ Alice adds a second migration which adds and initializes another column to the +products+ table and also adds a validation to the Product model for the new column.
512
548
 
549
+ <pre>
550
+ # db/migrate/20100515121110_add_fuzz_to_product.rb
551
+
552
+ class AddFuzzToProduct < ActiveRecord::Migration
513
553
  def change
514
- ...
554
+ add_column :products, :fuzz, :string
555
+ Product.all.each { |f| f.update_attributes! :fuzz => 'fuzzy' }
515
556
  end
516
557
  end
517
- </ruby>
518
- The migration has its own minimal copy of the +Product+ model and no longer cares about the +Product+ model defined in the application.
558
+ </pre>
519
559
 
520
- h4. Dealing with Changing Models
560
+ <pre>
561
+ # app/model/product.rb
521
562
 
522
- For performance reasons information about the columns a model has is cached. For example if you add a column to a table and then try and use the corresponding model to insert a new row it may try to use the old column information. You can force Active Record to re-read the column information with the +reset_column_information+ method, for example
563
+ class Product < ActiveRecord::Base
564
+ validates_presence_of :flag
565
+ validates_presence_of :fuzz
566
+ end
567
+ </pre>
523
568
 
524
- <ruby>
525
- class AddPartNumberToProducts < ActiveRecord::Migration
569
+ Both migrations work for Alice.
570
+
571
+ Bob comes back from vacation and:
572
+
573
+ # updates the source - which contains both migrations and the latests version of the Product model.
574
+ # runs outstanding migrations with +rake db:migrate+, which includes the one that updates the +Product+ model.
575
+
576
+ The migration crashes because when the model attempts to save, it tries to validate the second added column, which is not in the database when the _first_ migration runs.
577
+
578
+ <pre>
579
+ rake aborted!
580
+ An error has occurred, this and all later migrations canceled:
581
+
582
+ undefined method `fuzz' for #<Product:0x000001049b14a0>
583
+ </pre>
584
+
585
+ A fix for this is to create a local model within the migration. This keeps rails from running the validations, so that the migrations run to completion.
586
+
587
+ When using a faux model, it's a good idea to call +Product.reset_column_information+ to refresh the ActiveRecord cache for the Product model prior to updating data in the database.
588
+
589
+ If Alice had done this instead, there would have been no problem:
590
+
591
+ <pre>
592
+ # db/migrate/20100513121110_add_flag_to_product.rb
593
+
594
+ class AddFlagToProduct < ActiveRecord::Migration
526
595
  class Product < ActiveRecord::Base
527
596
  end
597
+ def change
598
+ add_column :products, :flag, :int
599
+ Product.reset_column_information
600
+ Product.all.each { |f| f.update_attributes!(:flag => false) }
601
+ end
602
+ end
603
+ </pre>
604
+
605
+ <pre>
606
+ # db/migrate/20100515121110_add_fuzz_to_product.rb
528
607
 
608
+ class AddFuzzToProduct < ActiveRecord::Migration
609
+ class Product < ActiveRecord::Base
610
+ end
529
611
  def change
530
- add_column :product, :part_number, :string
612
+ add_column :products, :fuzz, :string
531
613
  Product.reset_column_information
532
- ...
614
+ Product.all.each { |f| f.update_attributes! :fuzz => 'fuzzy' }
533
615
  end
534
616
  end
535
- </ruby>
617
+ </pre>
536
618
 
537
619
 
538
620
  h3. Schema Dumping and You
@@ -90,7 +90,7 @@ h3. Views
90
90
 
91
91
  h4. Controller code
92
92
 
93
- A nested model form will _only_ be build if the associated object(s) exist. This means that for a new model instance you would probably want to build the associated object(s) first.
93
+ A nested model form will _only_ be built if the associated object(s) exist. This means that for a new model instance you would probably want to build the associated object(s) first.
94
94
 
95
95
  Consider the following typical RESTful controller which will prepare a new Person instance and its +address+ and +projects+ associations before rendering the +new+ template:
96
96
 
@@ -144,7 +144,7 @@ Now add a nested form for the +address+ association:
144
144
  <%= f.text_field :name %>
145
145
 
146
146
  <%= f.fields_for :address do |af| %>
147
- <%= f.text_field :street %>
147
+ <%= af.text_field :street %>
148
148
  <% end %>
149
149
  <% end %>
150
150
  </erb>
@@ -159,7 +159,7 @@ This generates:
159
159
  </form>
160
160
  </html>
161
161
 
162
- Notice that +fields_for+ recognized the +address+ as an association for which a nested model form should be build by the way it has namespaced the +name+ attribute.
162
+ Notice that +fields_for+ recognized the +address+ as an association for which a nested model form should be built by the way it has namespaced the +name+ attribute.
163
163
 
164
164
  When this form is posted the Rails parameter parser will construct a hash like the following:
165
165
 
@@ -185,7 +185,7 @@ The form code for an association collection is pretty similar to that of a singl
185
185
  <%= f.text_field :name %>
186
186
 
187
187
  <%= f.fields_for :projects do |pf| %>
188
- <%= f.text_field :name %>
188
+ <%= pf.text_field :name %>
189
189
  <% end %>
190
190
  <% end %>
191
191
  </erb>
@@ -201,7 +201,7 @@ Which generates:
201
201
  </form>
202
202
  </html>
203
203
 
204
- As you can see it has generated 2 +project name+ inputs, one for each new +project+ that’s build in the controllers +new+ action. Only this time the +name+ attribute of the input contains a digit as an extra namespace. This will be parsed by the Rails parameter parser as:
204
+ As you can see it has generated 2 +project name+ inputs, one for each new +project+ that was built in the controller's +new+ action. Only this time the +name+ attribute of the input contains a digit as an extra namespace. This will be parsed by the Rails parameter parser as:
205
205
 
206
206
  <ruby>
207
207
  {
@@ -215,7 +215,7 @@ As you can see it has generated 2 +project name+ inputs, one for each new +proje
215
215
  }
216
216
  </ruby>
217
217
 
218
- You can basically see the +projects_attributes+ hash as an array of attribute hashes. One for each model instance.
218
+ You can basically see the +projects_attributes+ hash as an array of attribute hashes, one for each model instance.
219
219
 
220
220
  NOTE: The reason that +fields_for+ constructed a form which would result in a hash instead of an array is that it won't work for any forms nested deeper than one level deep.
221
221
 
@@ -66,7 +66,7 @@ resources :posts
66
66
  # home_controller.rb
67
67
  class HomeController < ApplicationController
68
68
  def dashboard
69
- @users = User.last_ten(:include => :avatars)
69
+ @users = User.last_ten.includes(:avatars)
70
70
  @posts = Post.all_today
71
71
  end
72
72
  end
@@ -151,7 +151,7 @@ Performance tests can be run in two modes: Benchmarking and Profiling.
151
151
 
152
152
  h5. Benchmarking
153
153
 
154
- Benchmarking makes it easy to quickly gather a few metrics about each test tun. By default, each test case is run +4 times+ in benchmarking mode.
154
+ Benchmarking makes it easy to quickly gather a few metrics about each test tun. By default, each test case is run *4 times* in benchmarking mode.
155
155
 
156
156
  To run performance tests in benchmarking mode:
157
157
 
@@ -161,7 +161,7 @@ $ rake test:benchmark
161
161
 
162
162
  h5. Profiling
163
163
 
164
- Profiling allows you to make an in-depth analysis of each of your tests by using an external profiler. Depending on your Ruby interpreter, this profiler can be native (Rubinius, JRuby) or not (MRI, which uses RubyProf). By default, each test case is run +1 time+ in profiling mode.
164
+ Profiling allows you to make an in-depth analysis of each of your tests by using an external profiler. Depending on your Ruby interpreter, this profiler can be native (Rubinius, JRuby) or not (MRI, which uses RubyProf). By default, each test case is run *once* in profiling mode.
165
165
 
166
166
  To run performance tests in profiling mode:
167
167
 
@@ -276,7 +276,7 @@ measurement,created_at,app,rails,ruby,platform
276
276
 
277
277
  h5(#output-profiling). Profiling
278
278
 
279
- In profiling mode, performance tests can generate multiple types of outputs. The command line output is always presented but support for the others is dependant on the interpreter in use. A brief description of each type and their availability across interpreters is given below.
279
+ In profiling mode, performance tests can generate multiple types of outputs. The command line output is always presented but support for the others is dependent on the interpreter in use. A brief description of each type and their availability across interpreters is given below.
280
280
 
281
281
  h6. Command Line
282
282
 
@@ -481,7 +481,7 @@ h4. +profiler+
481
481
  Usage:
482
482
 
483
483
  <shell>
484
- Usage: rails benchmarker 'Ruby.code' 'Ruby.more_code' ... [OPTS]
484
+ Usage: rails profiler 'Ruby.code' 'Ruby.more_code' ... [OPTS]
485
485
  -r, --runs N Number of runs.
486
486
  Default: 1
487
487
  -o, --output PATH Directory to use when writing the results.
@@ -573,7 +573,7 @@ h3. Useful Links
573
573
  h4. Rails Plugins and Gems
574
574
 
575
575
  * "Rails Analyzer":http://rails-analyzer.rubyforge.org
576
- * "Palmist":http://www.flyingmachinestudios.com/projects/
576
+ * "Palmist":http://www.flyingmachinestudios.com/programming/announcing-palmist
577
577
  * "Rails Footnotes":https://github.com/josevalim/rails-footnotes/tree/master
578
578
  * "Query Reviewer":https://github.com/dsboulder/query_reviewer/tree/master
579
579
 
@@ -25,33 +25,36 @@ endprologue.
25
25
 
26
26
  h3. Setup
27
27
 
28
- h4. Generating the Plugin Skeleton
28
+ Before you continue, take a moment to decide if your new plugin will be potentially shared across different Rails applications.
29
29
 
30
- Rails currently ships with a generator to generate a plugin within a Rails application. Help text is available that will explain
31
- how this generator works.
30
+ * If your plugin is specific to your application, your new plugin will be a _vendored plugin_.
31
+ * If you think your plugin may be used across applications, build it as a _gemified plugin_.
32
+
33
+ h4. Either generate a vendored plugin...
34
+
35
+ Use the +rails generate plugin+ command in your Rails root directory
36
+ to create a new plugin that will live in the +vendor/plugins+
37
+ directory. See usage and options by asking for help:
32
38
 
33
39
  <shell>
34
40
  $ rails generate plugin --help
35
41
  </shell>
36
42
 
37
- This generator places the plugin into the vendor/plugins directory.
43
+ h4. Or generate a gemified plugin.
38
44
 
39
- Vendored plugins are useful for quickly prototyping your plugin but current thinking in the Rails community is shifting towards
40
- packaging plugins as gems, especially with the inclusion of Bundler as the Rails dependency manager.
41
- Packaging a plugin as a gem may be overkill for any plugins that will not be shared across projects but doing so from the start makes it easier to share the plugin going forward without adding too much additional overhead during development.
45
+ Writing your Rails plugin as a gem, rather than as a vendored plugin,
46
+ lets you share your plugin across different rails applications using
47
+ RubyGems and Bundler.
42
48
 
43
- Rails 3.1 will ship with a plugin generator that will default to setting up a plugin
44
- as a gem. This tutorial will begin to bridge that gap by demonstrating how to create a gem based plugin using the
45
- "Enginex gem":http://www.github.com/josevalim/enginex.
49
+ Rails 3.1 ships with a +rails plugin new+ command which creates a
50
+ skeleton for developing any kind of Rails extension with the ability
51
+ to run integration tests using a dummy Rails application. See usage
52
+ and options by asking for help:
46
53
 
47
54
  <shell>
48
- $ gem install enginex
49
- $ enginex --help
50
- $ enginex yaffle
55
+ $ rails plugin --help
51
56
  </shell>
52
57
 
53
- This command will create a new directory named "yaffle" within the current directory.
54
-
55
58
  h3. Testing your newly generated plugin
56
59
 
57
60
  You can navigate to the directory that contains the plugin, run the +bundle install+ command
@@ -83,7 +86,7 @@ class CoreExtTest < Test::Unit::TestCase
83
86
  end
84
87
  </ruby>
85
88
 
86
- Run +rake+ to run the test. This test should fail because we haven't implemented the +to_squak+ method:
89
+ Run +rake+ to run the test. This test should fail because we haven't implemented the +to_squawk+ method:
87
90
 
88
91
  <shell>
89
92
  1) Error:
@@ -215,8 +218,8 @@ test/dummy directory:
215
218
 
216
219
  <shell>
217
220
  $ cd test/dummy
218
- $ rails generate model Hickwall last_squak:string
219
- $ rails generate model Wickwall last_squak:string last_tweet:string
221
+ $ rails generate model Hickwall last_squawk:string
222
+ $ rails generate model Wickwall last_squawk:string last_tweet:string
220
223
  </shell>
221
224
 
222
225
  Now you can create the necessary database tables in your testing database by navigating to your dummy app
@@ -319,7 +322,7 @@ When you run +rake+ you should see the tests all pass:
319
322
 
320
323
  h4. Add an Instance Method
321
324
 
322
- This plugin will add a method named 'squawk' to any Active Record objects that call 'acts_as_yaffle'. The 'squawk'
325
+ This plugin will add a method named 'squawk' to any Active Record objects that call 'acts_as_yaffle'. The 'squawk'
323
326
  method will simply set the value of one of the fields in the database.
324
327
 
325
328
  To start out, write a failing test that shows the behavior you'd like:
@@ -387,9 +390,7 @@ Run +rake+ one final time and you should see:
387
390
  7 tests, 7 assertions, 0 failures, 0 errors, 0 skips
388
391
  </shell>
389
392
 
390
- NOTE: The use of +write_attribute+ to write to the field in model is just one example of how a plugin can
391
- interact with the model, and will not always be the right method to use. For example, you could also
392
- use +send("#{self.class.yaffle_text_field}=", string.to_squawk)+.
393
+ NOTE: The use of +write_attribute+ to write to the field in model is just one example of how a plugin can interact with the model, and will not always be the right method to use. For example, you could also use <tt>send("#{self.class.yaffle_text_field}=", string.to_squawk)</tt>.
393
394
 
394
395
  h3. Generators
395
396