From 42d3764b3ddc67ac5818deff06b7dfbcdd95e834 Mon Sep 17 00:00:00 2001 From: James Miller Date: Tue, 6 Apr 2010 16:36:43 -0700 Subject: ERB update for AC overview guide --- railties/guides/source/action_controller_overview.textile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'railties/guides/source') diff --git a/railties/guides/source/action_controller_overview.textile b/railties/guides/source/action_controller_overview.textile index bedca59c12..e193c57935 100644 --- a/railties/guides/source/action_controller_overview.textile +++ b/railties/guides/source/action_controller_overview.textile @@ -492,10 +492,10 @@ The way this is done is to add a non-guessable token which is only known to your If you generate a form like this: -<% form_for @user do |f| -%> +<%= form_for @user do |f| %> <%= f.text_field :username %> <%= f.text_field :password -%> -<% end -%> +<% end %> You will see how the token gets added as a hidden field: -- cgit v1.2.3 From 4f0982db91f4e67b36aec7f1e7445655e7bce8ce Mon Sep 17 00:00:00 2001 From: James Miller Date: Tue, 6 Apr 2010 16:52:39 -0700 Subject: More on the new ERB syntax in the guides --- .../source/action_controller_overview.textile | 10 +++++----- .../guides/source/action_view_overview.textile | 22 +++++++++++----------- .../activerecord_validations_callbacks.textile | 2 +- railties/guides/source/getting_started.textile | 2 +- .../guides/source/layouts_and_rendering.textile | 6 +++--- railties/guides/source/nested_model_forms.textile | 6 +++--- railties/guides/source/testing.textile | 2 +- 7 files changed, 25 insertions(+), 25 deletions(-) (limited to 'railties/guides/source') diff --git a/railties/guides/source/action_controller_overview.textile b/railties/guides/source/action_controller_overview.textile index e193c57935..caa7646b7f 100644 --- a/railties/guides/source/action_controller_overview.textile +++ b/railties/guides/source/action_controller_overview.textile @@ -255,12 +255,12 @@ The +destroy+ action redirects to the application's +root_url+, where the messag - <% if flash[:notice] -%> + <% if flash[:notice] %>

<%= flash[:notice] %>

- <% end -%> - <% if flash[:error] -%> + <% end %> + <% if flash[:error] %>

<%= flash[:error] %>

- <% end -%> + <% end %> @@ -494,7 +494,7 @@ If you generate a form like this: <%= form_for @user do |f| %> <%= f.text_field :username %> - <%= f.text_field :password -%> + <%= f.text_field :password %> <% end %> diff --git a/railties/guides/source/action_view_overview.textile b/railties/guides/source/action_view_overview.textile index df8cf4dc29..43ebe87875 100644 --- a/railties/guides/source/action_view_overview.textile +++ b/railties/guides/source/action_view_overview.textile @@ -135,7 +135,7 @@ The +post+ partial wraps the post's +body+ in a +div+ with the +id+ of the post *posts/_post.html.erb* -<% div_for(post) do %> +<%= div_for(post) do %>

<%= post.body %>

<% end %>
@@ -158,7 +158,7 @@ You can also render a block of code within a partial layout instead of calling + <% render(:layout => 'box', :locals => {:post => @post}) do %> - <% div_for(post) do %> + <%= div_for(post) do %>

<%= post.body %>

<% end %> <% end %> @@ -654,7 +654,7 @@ The core method of this helper, form_for, gives you the ability to create a form # Note: a @person variable will have been created in the controller (e.g. @person = Person.new) -<% form_for :person, @person, :url => { :action => "create" } do |f| %> +<%= form_for :person, @person, :url => { :action => "create" } do |f| %> <%= f.text_field :first_name %> <%= f.text_field :last_name %> <%= submit_tag 'Create' %> @@ -695,7 +695,7 @@ h5. fields_for Creates a scope around a specific model object like form_for, but doesn‘t create the form tags themselves. This makes fields_for suitable for specifying additional model objects in the same form: -<% form_for @person, :url => { :action => "update" } do |person_form| %> +<%= form_for @person, :url => { :action => "update" } do |person_form| %> First name: <%= person_form.text_field :first_name %> Last name : <%= person_form.text_field :last_name %> @@ -719,7 +719,7 @@ h5. form_for Creates a form and a scope around a specific model object that is used as a base for questioning about values for the fields. -<% form_for @post do |f| %> +<%= form_for @post do |f| %> <%= f.label :title, 'Title' %>: <%= f.text_field :title %>
<%= f.label :body, 'Body' %>: @@ -957,7 +957,7 @@ h5. field_set_tag Creates a field set for grouping HTML form elements. -<% field_set_tag do %> +<%= field_set_tag do %>

<%= text_field_tag 'name' %>

<% end %> # =>

@@ -970,10 +970,10 @@ Creates a file upload field. If you are using file uploads then you will also need to set the multipart option for the form tag: -<%= form_tag { :action => "post" }, { :multipart => true } %> +<%= form_tag { :action => "post" }, { :multipart => true } do %> <%= file_field_tag "file" %> <%= submit_tag %> -<%= end_form_tag %> +<% end %> Example output: @@ -988,9 +988,9 @@ h5. form_tag Starts a form tag that points the action to an url configured with +url_for_options+ just like +ActionController::Base#url_for+. -<% form_tag '/posts' do -%> +<%= form_tag '/posts' do %>
<%= submit_tag 'Save' %>
-<% end -%> +<% end %> # =>
@@ -1251,7 +1251,7 @@ h5. remote_form_for Creates a form that will submit using XMLHttpRequest in the background instead of the regular reloading POST arrangement and a scope around a specific resource that is used as a base for questioning about values for the fields. -<% remote_form_for(@post) do |f| %> +<%= remote_form_for(@post) do |f| %> ... <% end %> diff --git a/railties/guides/source/activerecord_validations_callbacks.textile b/railties/guides/source/activerecord_validations_callbacks.textile index 6575612bee..126a6efff5 100644 --- a/railties/guides/source/activerecord_validations_callbacks.textile +++ b/railties/guides/source/activerecord_validations_callbacks.textile @@ -712,7 +712,7 @@ end
-<% form_for(@product) do |f| %> +<%= form_for(@product) do |f| %> <%= f.error_messages %>

<%= f.label :description %>
diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index 17279146a7..2bbb4dc252 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -974,7 +974,7 @@ Once we have made the new comment, we send the user back to the +post_path(@post <% end %>

Add a comment:

-<% form_for([@post, @post.comments.build]) do |f| %> +<%= form_for([@post, @post.comments.build]) do |f| %> <%= f.error_messages %>
diff --git a/railties/guides/source/layouts_and_rendering.textile b/railties/guides/source/layouts_and_rendering.textile index fad687466e..92b36ab3e4 100644 --- a/railties/guides/source/layouts_and_rendering.textile +++ b/railties/guides/source/layouts_and_rendering.textile @@ -1037,7 +1037,7 @@ You can also pass local variables into partials, making them even more powerful * +_form.html.erb+ -<% form_for(zone) do |f| %> +<%= form_for(zone) do |f| %>

Zone name
<%= f.text_field :name %> @@ -1181,11 +1181,11 @@ On pages generated by +NewsController+, you want to hide the top menu and add a <% content_for :stylesheets do %> #top_menu {display: none} #right_menu {float: right; background-color: yellow; color: black} -<% end -%> +<% end %> <% content_for :content do %>

Right menu items here
<%= yield(:news_content) or yield %> -<% end -%> +<% end %> <%= render :file => 'layouts/application' %>
diff --git a/railties/guides/source/nested_model_forms.textile b/railties/guides/source/nested_model_forms.textile index 4b685b214e..4a79902232 100644 --- a/railties/guides/source/nested_model_forms.textile +++ b/railties/guides/source/nested_model_forms.textile @@ -122,7 +122,7 @@ h5. Standard form Start out with a regular RESTful form: -<% form_for @person do |f| %> +<%= form_for @person do |f| %> <%= f.text_field :name %> <% end %> @@ -140,7 +140,7 @@ h5. Nested form for a single associated object Now add a nested form for the +address+ association: -<% form_for @person do |f| %> +<%= form_for @person do |f| %> <%= f.text_field :name %> <% f.fields_for :address do |af| %> @@ -181,7 +181,7 @@ h5. Nested form for a collection of associated objects The form code for an association collection is pretty similar to that of a single associated object: -<% form_for @person do |f| %> +<%= form_for @person do |f| %> <%= f.text_field :name %> <% f.fields_for :projects do |pf| %> diff --git a/railties/guides/source/testing.textile b/railties/guides/source/testing.textile index b291b541ba..6e25515fed 100644 --- a/railties/guides/source/testing.textile +++ b/railties/guides/source/testing.textile @@ -84,7 +84,7 @@ h5. ERb'in It Up ERb allows you embed ruby code within templates. Both the YAML and CSV fixture formats are pre-processed with ERb when you load fixtures. This allows you to use Ruby to help you generate some sample data. -<% earth_size = 20 -%> +<% earth_size = 20 %> mercury: size: <%= earth_size / 50 %> brightest_on: <%= 113.days.ago.to_s(:db) %> -- cgit v1.2.3 From 647addd8e022012b159bc2298c5e23b5c8ff315c Mon Sep 17 00:00:00 2001 From: Jaime Iniesta Date: Wed, 7 Apr 2010 17:56:51 +0200 Subject: Fixed duplicated IDs on associations_basics guide to validate XHTML 1.0 Strict --- railties/guides/source/association_basics.textile | 163 +++++++++++----------- 1 file changed, 82 insertions(+), 81 deletions(-) (limited to 'railties/guides/source') diff --git a/railties/guides/source/association_basics.textile b/railties/guides/source/association_basics.textile index 4256466bec..f13f6db6ee 100644 --- a/railties/guides/source/association_basics.textile +++ b/railties/guides/source/association_basics.textile @@ -603,11 +603,11 @@ The +belongs_to+ association supports these options: * +:touch+ * +:validate+ -h6. +:autosave+ +h6(#belongs_to-autosave). +:autosave+ If you set the +:autosave+ option to +true+, Rails will save any loaded members and destroy members that are marked for destruction whenever you save the parent object. -h6. +:class_name+ +h6(#belongs_to-class_name). +:class_name+ If the name of the other model cannot be derived from the association name, you can use the +:class_name+ option to supply the model name. For example, if an order belongs to a customer, but the actual name of the model containing customers is +Patron+, you'd set things up this way: @@ -617,7 +617,7 @@ class Order < ActiveRecord::Base end -h6. +:conditions+ +h6(#belongs_to-conditions). +:conditions+ The +:conditions+ option lets you specify the conditions that the associated object must meet (in the syntax used by a SQL +WHERE+ clause). @@ -666,13 +666,13 @@ end Counter cache columns are added to the containing model's list of read-only attributes through +attr_readonly+. -h6. +:dependent+ +h6(#belongs_to-dependent). +:dependent+ If you set the +:dependent+ option to +:destroy+, then deleting this object will call the +destroy+ method on the associated object to delete that object. If you set the +:dependent+ option to +:delete+, then deleting this object will delete the associated object _without_ calling its +destroy+ method. WARNING: You should not specify this option on a +belongs_to+ association that is connected with a +has_many+ association on the other class. Doing so can lead to orphaned records in your database. -h6. +:foreign_key+ +h6(#belongs_to-foreign_key). +:foreign_key+ By convention, Rails guesses that the column used to hold the foreign key on this model is the name of the association with the suffix +_id+ added. The +:foreign_key+ option lets you set the name of the foreign key directly: @@ -685,7 +685,7 @@ end TIP: In any case, Rails will not create foreign key columns for you. You need to explicitly define them as part of your migrations. -h6. +:include+ +h6(#belongs_to-includes). +:include+ You can use the +:include+ option to specify second-order associations that should be eager-loaded when this association is used. For example, consider these models: @@ -727,11 +727,11 @@ h6. +:polymorphic+ Passing +true+ to the +:polymorphic+ option indicates that this is a polymorphic association. Polymorphic associations were discussed in detail earlier in this guide. -h6. +:readonly+ +h6(#belongs_to-readonly). +:readonly+ If you set the +:readonly+ option to +true+, then the associated object will be read-only when retrieved via the association. -h6. +:select+ +h6(#belongs_to-select). +:select+ The +:select+ option lets you override the SQL +SELECT+ clause that is used to retrieve data about the associated object. By default, Rails retrieves all columns. @@ -759,11 +759,11 @@ class Order < ActiveRecord::Base end -h6. +:validate+ +h6(#belongs_to-validate). +:validate+ If you set the +:validate+ option to +true+, then associated objects will be validated whenever you save this object. By default, this is +false+: associated objects will not be validated when this object is saved. -h5. How To Know Whether There's an Associated Object? +h5(#belongs_to-how_to_know_whether_theres_an_associated_object). How To Know Whether There's an Associated Object? To know whether there's and associated object just check association.nil?: @@ -773,7 +773,7 @@ if @order.customer.nil? end -h5. When are Objects Saved? +h5(#belongs_to-when_are_objects_saved). When are Objects Saved? Assigning an object to a +belongs_to+ association does _not_ automatically save the object. It does not save the associated object either. @@ -869,15 +869,15 @@ The +has_one+ association supports these options: * +:through+ * +:validate+ -h6. +:as+ +h6(#has_one-as). +:as+ Setting the +:as+ option indicates that this is a polymorphic association. Polymorphic associations were discussed in detail earlier in this guide. -h6. +:autosave+ +h6(#has_one-autosave). +:autosave+ If you set the +:autosave+ option to +true+, Rails will save any loaded members and destroy members that are marked for destruction whenever you save the parent object. -h6. +:class_name+ +h6(#has_one-class_name). +:class_name+ If the name of the other model cannot be derived from the association name, you can use the +:class_name+ option to supply the model name. For example, if a supplier has an account, but the actual name of the model containing accounts is +Billing+, you'd set things up this way: @@ -887,7 +887,7 @@ class Supplier < ActiveRecord::Base end -h6. +:conditions+ +h6(#has_one-conditions). +:conditions+ The +:conditions+ option lets you specify the conditions that the associated object must meet (in the syntax used by a SQL +WHERE+ clause). @@ -897,11 +897,11 @@ class Supplier < ActiveRecord::Base end -h6. +:dependent+ +h6(#has_one-dependent). +:dependent+ If you set the +:dependent+ option to +:destroy+, then deleting this object will call the +destroy+ method on the associated object to delete that object. If you set the +:dependent+ option to +:delete+, then deleting this object will delete the associated object _without_ calling its +destroy+ method. If you set the +:dependent+ option to +:nullify+, then deleting this object will set the foreign key in the association object to +NULL+. -h6. +:foreign_key+ +h6(#has_one-foreign_key). +:foreign_key+ By convention, Rails guesses that the column used to hold the foreign key on the other model is the name of this model with the suffix +_id+ added. The +:foreign_key+ option lets you set the name of the foreign key directly: @@ -913,7 +913,7 @@ end TIP: In any case, Rails will not create foreign key columns for you. You need to explicitly define them as part of your migrations. -h6. +:include+ +h6(#has_one-include). +:include+ You can use the +:include+ option to specify second-order associations that should be eager-loaded when this association is used. For example, consider these models: @@ -949,39 +949,39 @@ class Representative < ActiveRecord::Base end -h6. +:order+ +h6(#has_one-order). +:order+ The +:order+ option dictates the order in which associated objects will be received (in the syntax used by a SQL +ORDER BY+ clause). Because a +has_one+ association will only retrieve a single associated object, this option should not be needed. -h6. +:primary_key+ +h6(#has_one-primary_key). +:primary_key+ By convention, Rails guesses that the column used to hold the primary key of this model is +id+. You can override this and explicitly specify the primary key with the +:primary_key+ option. -h6. +:readonly+ +h6(#has_one-readonly). +:readonly+ If you set the +:readonly+ option to +true+, then the associated object will be read-only when retrieved via the association. -h6. +:select+ +h6(#has_one-select). +:select+ The +:select+ option lets you override the SQL +SELECT+ clause that is used to retrieve data about the associated object. By default, Rails retrieves all columns. -h6. +:source+ +h6(#has_one-source). +:source+ The +:source+ option specifies the source association name for a +has_one :through+ association. -h6. +:source_type+ +h6(#has_one-source_type). +:source_type+ The +:source_type+ option specifies the source association type for a +has_one :through+ association that proceeds through a polymorphic association. -h6. +:through+ +h6(#has_one-through). +:through+ The +:through+ option specifies a join model through which to perform the query. +has_one :through+ associations were discussed in detail earlier in this guide. -h6. +:validate+ +h6(#has_one-validate). +:validate+ If you set the +:validate+ option to +true+, then associated objects will be validated whenever you save this object. By default, this is +false+: associated objects will not be validated when this object is saved. -h5. How To Know Whether There's an Associated Object? +h5(#has_one-how_to_know_whether_theres_an_associated_object). How To Know Whether There's an Associated Object? To know whether there's and associated object just check association.nil?: @@ -991,7 +991,7 @@ if @supplier.account.nil? end -h5. When are Objects Saved? +h5(#has_one-when_are_objects_saved). When are Objects Saved? When you assign an object to a +has_one+ association, that object is automatically saved (in order to update its foreign key). In addition, any object being replaced is also automatically saved, because its foreign key will change too. @@ -1005,7 +1005,7 @@ h4. +has_many+ Association Reference The +has_many+ association creates a one-to-many relationship with another model. In database terms, this association says that the other class will have a foreign key that refers to instances of this class. -h5. Methods Added +h5. Methods Added by +has_many+ When you declare a +has_many+ association, the declaring class automatically gains 13 methods related to the association: @@ -1049,7 +1049,7 @@ orders.build(attributes = {}, ...) orders.create(attributes = {}) -h6. collection(force_reload = false) +h6(#has_many-collection). collection(force_reload = false) The collection method returns an array of all of the associated objects. If there are no associated objects, it returns an empty array. @@ -1057,7 +1057,7 @@ The collection method returns an array of all of the associate @orders = @customer.orders -h6. collection<<(object, ...) +h6(#has_many-collection-lt_lt). collection<<(object, ...) The collection<< method adds one or more objects to the collection by setting their foreign keys to the primary key of the calling model. @@ -1065,7 +1065,7 @@ The collection<< method adds one or more objects to the collec @customer.orders << @order1 -h6. collection.delete(object, ...) +h6(#has_many-collection-delete). collection.delete(object, ...) The collection.delete method removes one or more objects from the collection by setting their foreign keys to +NULL+. @@ -1076,11 +1076,11 @@ The collection.delete method removes one or more objects from WARNING: Objects will be in addition destroyed if they're associated with +:dependent => :destroy+, and deleted if they're associated with +:dependent => :delete_all+. -h6. collection=objects +h6(#has_many-collection_equal). collection=objects The collection= method makes the collection contain only the supplied objects, by adding and deleting as appropriate. -h6. collection_singular_ids +h6(#has_many-collection_singular). collection_singular_ids The collection_singular_ids method returns an array of the ids of the objects in the collection. @@ -1088,11 +1088,11 @@ The collection_singular_ids method returns an array of the ids @order_ids = @customer.order_ids -h6. collection_singular_ids=ids +h6(#has_many-collection_singular_ids_ids). collection_singular_ids=ids The collection_singular_ids= method makes the collection contain only the objects identified by the supplied primary key values, by adding and deleting as appropriate. -h6. collection.clear +h6(#has_many-collection_clear). collection.clear The collection.clear method removes every object from the collection. This destroys the associated objects if they are associated with +:dependent => :destroy+, deletes them directly from the database if +:dependent => :delete_all+, and otherwise sets their foreign keys to +NULL+. @@ -1179,7 +1179,7 @@ The +has_many+ association supports these options: * +:uniq+ * +:validate+ -h6. +:as+ +h6(#has_many-as). +:as+ Setting the +:as+ option indicates that this is a polymorphic association, as discussed earlier in this guide. @@ -1187,7 +1187,7 @@ h6. +:autosave+ If you set the +:autosave+ option to +true+, Rails will save any loaded members and destroy members that are marked for destruction whenever you save the parent object. -h6. +:class_name+ +h6(#has_many-class_name). +:class_name+ If the name of the other model cannot be derived from the association name, you can use the +:class_name+ option to supply the model name. For example, if a customer has many orders, but the actual name of the model containing orders is +Transaction+, you'd set things up this way: @@ -1197,7 +1197,7 @@ class Customer < ActiveRecord::Base end -h6. +:conditions+ +h6(#has_many-conditions). +:conditions+ The +:conditions+ option lets you specify the conditions that the associated object must meet (in the syntax used by a SQL +WHERE+ clause). @@ -1230,27 +1230,27 @@ end Be sure to use single quotes. -h6. +:counter_sql+ +h6(#has_many-counter_sql). +:counter_sql+ Normally Rails automatically generates the proper SQL to count the association members. With the +:counter_sql+ option, you can specify a complete SQL statement to count them yourself. NOTE: If you specify +:finder_sql+ but not +:counter_sql+, then the counter SQL will be generated by substituting +SELECT COUNT(*) FROM+ for the +SELECT ... FROM+ clause of your +:finder_sql+ statement. -h6. +:dependent+ +h6(#has_many-dependent). +:dependent+ If you set the +:dependent+ option to +:destroy+, then deleting this object will call the +destroy+ method on the associated objects to delete those objects. If you set the +:dependent+ option to +:delete_all+, then deleting this object will delete the associated objects _without_ calling their +destroy+ method. If you set the +:dependent+ option to +:nullify+, then deleting this object will set the foreign key in the associated objects to +NULL+. NOTE: This option is ignored when you use the +:through+ option on the association. -h6. +:extend+ +h6(#has_many-extend). +:extend+ The +:extend+ option specifies a named module to extend the association proxy. Association extensions are discussed in detail later in this guide. -h6. +:finder_sql+ +h6(#has_many-finder_sql). +:finder_sql+ Normally Rails automatically generates the proper SQL to fetch the association members. With the +:finder_sql+ option, you can specify a complete SQL statement to fetch them yourself. If fetching objects requires complex multi-table SQL, this may be necessary. -h6. +:foreign_key+ +h6(#has_many-foreign_key). +:foreign_key+ By convention, Rails guesses that the column used to hold the foreign key on the other model is the name of this model with the suffix +_id+ added. The +:foreign_key+ option lets you set the name of the foreign key directly: @@ -1262,7 +1262,7 @@ end TIP: In any case, Rails will not create foreign key columns for you. You need to explicitly define them as part of your migrations. -h6. +:group+ +h6(:has_many-group). +:group+ The +:group+ option supplies an attribute name to group the result set by, using a +GROUP BY+ clause in the finder SQL. @@ -1272,7 +1272,7 @@ class Customer < ActiveRecord::Base end -h6. +:include+ +h6(#has_many-include). +:include+ You can use the +:include+ option to specify second-order associations that should be eager-loaded when this association is used. For example, consider these models: @@ -1308,7 +1308,7 @@ class LineItem < ActiveRecord::Base end -h6. +:limit+ +h6(#has_many-limit). +:limit+ The +:limit+ option lets you restrict the total number of objects that will be fetched through an association. @@ -1319,11 +1319,11 @@ class Customer < ActiveRecord::Base end -h6. +:offset+ +h6(#has_many-offset). +:offset+ The +:offset+ option lets you specify the starting offset for fetching objects via an association. For example, if you set +:offset => 11+, it will skip the first 11 records. -h6. +:order+ +h6(#has_many-order). +:order+ The +:order+ option dictates the order in which associated objects will be received (in the syntax used by a SQL +ORDER BY+ clause). @@ -1333,41 +1333,41 @@ class Customer < ActiveRecord::Base end -h6. +:primary_key+ +h6(#has_many-primary_key). +:primary_key+ By convention, Rails guesses that the column used to hold the primary key of the association is +id+. You can override this and explicitly specify the primary key with the +:primary_key+ option. -h6. +:readonly+ +h6(#has_many-readonly). +:readonly+ If you set the +:readonly+ option to +true+, then the associated objects will be read-only when retrieved via the association. -h6. +:select+ +h6(#has_many-select). +:select+ The +:select+ option lets you override the SQL +SELECT+ clause that is used to retrieve data about the associated objects. By default, Rails retrieves all columns. WARNING: If you specify your own +:select+, be sure to include the primary key and foreign key columns of the associated model. If you do not, Rails will throw an error. -h6. +:source+ +h6(#has_many-source). +:source+ The +:source+ option specifies the source association name for a +has_many :through+ association. You only need to use this option if the name of the source association cannot be automatically inferred from the association name. -h6. +:source_type+ +h6(#has_many-source_type). +:source_type+ The +:source_type+ option specifies the source association type for a +has_many :through+ association that proceeds through a polymorphic association. -h6. +:through+ +h6(#has_many-through). +:through+ The +:through+ option specifies a join model through which to perform the query. +has_many :through+ associations provide a way to implement many-to-many relationships, as discussed earlier in this guide. -h6. +:uniq+ +h6(#has_many-uniq). +:uniq+ Specify the +:uniq => true+ option to remove duplicates from the collection. This is most useful in conjunction with the +:through+ option. -h6. +:validate+ +h6(#has_many-validate). +:validate+ If you set the +:validate+ option to +false+, then associated objects will not be validated whenever you save this object. By default, this is +true+: associated objects will be validated when this object is saved. -h5. When are Objects Saved? +h5(#has_many-when_are_objects_saved). When are Objects Saved? When you assign an object to a +has_many+ association, that object is automatically saved (in order to update its foreign key). If you assign multiple objects in one statement, then they are all saved. @@ -1381,7 +1381,7 @@ h4. +has_and_belongs_to_many+ Association Reference The +has_and_belongs_to_many+ association creates a many-to-many relationship with another model. In database terms, this associates two classes via an intermediate join table that includes foreign keys referring to each of the classes. -h5. Methods Added +h5. Methods Added by +has_and_belongs_to_many+ When you declare a +has_and_belongs_to_many+ association, the declaring class automatically gains 13 methods related to the association: @@ -1478,7 +1478,7 @@ h6. collection.clear The collection.clear method removes every object from the collection by deleting the rows from the joining table. This does not destroy the associated objects. -h6. collection.empty? +h6(#has_and_belongs_to_many-collection-empty). collection.empty? The collection.empty? method returns +true+ if the collection does not contain any associated objects. @@ -1488,7 +1488,7 @@ The collection.empty? method returns +true+ if the collection <% end %> -h6. collection.size +h6(#has_and_belongs_to_many-collection-size). collection.size The collection.size method returns the number of objects in the collection. @@ -1496,7 +1496,7 @@ The collection.size method returns the number of objects in th @assembly_count = @part.assemblies.size -h6. collection.find(...) +h6(#has_and_belongs_to_many-collection-find). collection.find(...) The collection.find method finds objects within the collection. It uses the same syntax and options as +ActiveRecord::Base.find+. It also adds the additional condition that the object must be in the collection. @@ -1505,7 +1505,7 @@ The collection.find method finds objects within the collection :conditions => ["created_at > ?", 2.days.ago]) -h6. collection.exists?(...) +h6(#has_and_belongs_to_many-collection-exists). collection.exists?(...) The collection.exists? method checks whether an object meeting the supplied conditions exists in the collection. It uses the same syntax and options as +ActiveRecord::Base.exists?+. @@ -1518,7 +1518,7 @@ The collection.build method returns a new object of the associ {:assembly_name => "Transmission housing"}) -h6. collection.create(attributes = {}) +h6(#has_and_belongs_to_many-create-attributes). collection.create(attributes = {}) The collection.create method returns a new object of the associated type. This object will be instantiated from the passed attributes, the link through the join table will be created, and the associated object _will_ be saved (assuming that it passes any validations). @@ -1575,11 +1575,11 @@ class User < ActiveRecord::Base end -h6. +:autosave+ +h6(#has_and_belongs_to_many-autosave). +:autosave+ If you set the +:autosave+ option to +true+, Rails will save any loaded members and destroy members that are marked for destruction whenever you save the parent object. -h6. +:class_name+ +h6(#has_and_belongs_to_many-class_name). +:class_name+ If the name of the other model cannot be derived from the association name, you can use the +:class_name+ option to supply the model name. For example, if a part has many assemblies, but the actual name of the model containing assemblies is +Gadget+, you'd set things up this way: @@ -1589,7 +1589,7 @@ class Parts < ActiveRecord::Base end -h6. +:conditions+ +h6(#has_and_belongs_to_many-conditions). +:conditions+ The +:conditions+ option lets you specify the conditions that the associated object must meet (in the syntax used by a SQL +WHERE+ clause). @@ -1611,7 +1611,7 @@ end If you use a hash-style +:conditions+ option, then record creation via this association will be automatically scoped using the hash. In this case, using +@parts.assemblies.create+ or +@parts.assemblies.build+ will create orders where the +factory+ column has the value "Seattle". -h6. +:counter_sql+ +h6(#has_and_belongs_to_many-counter_sql). +:counter_sql+ Normally Rails automatically generates the proper SQL to count the association members. With the +:counter_sql+ option, you can specify a complete SQL statement to count them yourself. @@ -1621,15 +1621,15 @@ h6. +:delete_sql+ Normally Rails automatically generates the proper SQL to remove links between the associated classes. With the +:delete_sql+ option, you can specify a complete SQL statement to delete them yourself. -h6. +:extend+ +h6(#has_and_belongs_to_many-extend). +:extend+ The +:extend+ option specifies a named module to extend the association proxy. Association extensions are discussed in detail later in this guide. -h6. +:finder_sql+ +h6(#has_and_belongs_to_many-finder_sql). +:finder_sql+ Normally Rails automatically generates the proper SQL to fetch the association members. With the +:finder_sql+ option, you can specify a complete SQL statement to fetch them yourself. If fetching objects requires complex multi-table SQL, this may be necessary. -h6. +:foreign_key+ +h6(#has_and_belongs_to_many-foreign_key). +:foreign_key+ By convention, Rails guesses that the column in the join table used to hold the foreign key pointing to this model is the name of this model with the suffix +_id+ added. The +:foreign_key+ option lets you set the name of the foreign key directly: @@ -1641,7 +1641,7 @@ class User < ActiveRecord::Base end -h6. +:group+ +h6(#has_and_belongs_to_many-group). +:group+ The +:group+ option supplies an attribute name to group the result set by, using a +GROUP BY+ clause in the finder SQL. @@ -1651,7 +1651,7 @@ class Parts < ActiveRecord::Base end -h6. +:include+ +h6(#has_and_belongs_to_many-include). +:include+ You can use the +:include+ option to specify second-order associations that should be eager-loaded when this association is used. @@ -1663,7 +1663,7 @@ h6. +:join_table+ If the default name of the join table, based on lexical ordering, is not what you want, you can use the +:join_table+ option to override the default. -h6. +:limit+ +h6(#has_and_belongs_to_many-limit). +:limit+ The +:limit+ option lets you restrict the total number of objects that will be fetched through an association. @@ -1674,11 +1674,11 @@ class Parts < ActiveRecord::Base end -h6. +:offset+ +h6(#has_and_belongs_to_many-offset). +:offset+ The +:offset+ option lets you specify the starting offset for fetching objects via an association. For example, if you set +:offset => 11+, it will skip the first 11 records. -h6. +:order+ +h6(#has_and_belongs_to_many-order). +:order+ The +:order+ option dictates the order in which associated objects will be received (in the syntax used by a SQL +ORDER BY+ clause). @@ -1688,23 +1688,23 @@ class Parts < ActiveRecord::Base end -h6. +:readonly+ +h6(#has_and_belongs_to_many-readonly). +:readonly+ If you set the +:readonly+ option to +true+, then the associated objects will be read-only when retrieved via the association. -h6. +:select+ +h6(#has_and_belongs_to_many-select). +:select+ The +:select+ option lets you override the SQL +SELECT+ clause that is used to retrieve data about the associated objects. By default, Rails retrieves all columns. -h6. +:uniq+ +h6(#has_and_belongs_to_many-uniq). +:uniq+ Specify the +:uniq => true+ option to remove duplicates from the collection. -h6. +:validate+ +h6(#has_and_belongs_to_many-validate). +:validate+ If you set the +:validate+ option to +false+, then associated objects will not be validated whenever you save this object. By default, this is +true+: associated objects will be validated when this object is saved. -h5. When are Objects Saved? +h5(#has_and_belongs_to_many-when_are_objects_saved). When are Objects Saved? When you assign an object to a +has_and_belongs_to_many+ association, that object is automatically saved (in order to update the join table). If you assign multiple objects in one statement, then they are all saved. @@ -1809,6 +1809,7 @@ h3. Changelog "Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/11 +* April 7, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com * April 19, 2009: Added +:touch+ option to +belongs_to+ associations by "Mike Gunderloy":credits.html#mgunderloy * February 1, 2009: Added +:autosave+ option "Mike Gunderloy":credits.html#mgunderloy * September 28, 2008: Corrected +has_many :through+ diagram, added polymorphic diagram, some reorganization by "Mike Gunderloy":credits.html#mgunderloy . First release version. -- cgit v1.2.3 From 40e9cb6f4df3f10ef80284023595fe6a955e1740 Mon Sep 17 00:00:00 2001 From: Jaime Iniesta Date: Wed, 7 Apr 2010 18:19:17 +0200 Subject: Fixed duplicated IDs on active_record_querying guide to validate XHTML 1.0 Strict --- railties/guides/source/active_record_querying.textile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'railties/guides/source') diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index a993dad900..edd8ea3640 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -274,7 +274,7 @@ Client.where( This makes for clearer readability if you have a large number of variable conditions. -h5. Range Conditions +h5(#array-range_conditions). Range Conditions If you're looking for a range inside of a table (for example, users created in a certain timeframe) you can use the conditions option coupled with the +IN+ SQL statement for this. If you had two dates coming in from a controller you could do something like this to look for a range: @@ -353,7 +353,7 @@ The field name does not have to be a symbol it can also be a string: Client.where({ 'locked' => true }) -h5. Range Conditions +h5(#hash-range_conditions). Range Conditions The good thing about this is that we can pass in a range for our fields without it generating a large query as shown in the preamble of this section. -- cgit v1.2.3 From 1133146679d4213bec05ff8d97938ec03414c52c Mon Sep 17 00:00:00 2001 From: Jaime Iniesta Date: Wed, 7 Apr 2010 18:21:31 +0200 Subject: update changelog --- railties/guides/source/active_record_querying.textile | 1 + 1 file changed, 1 insertion(+) (limited to 'railties/guides/source') diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index edd8ea3640..e47615f070 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -934,6 +934,7 @@ h3. Changelog "Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/16 +* April 7, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com * February 3, 2010: Update to Rails 3 by "James Miller":credits.html#bensie * February 7, 2009: Second version by "Pratik":credits.html#lifo * December 29 2008: Initial version by "Ryan Bigg":credits.html#radar -- cgit v1.2.3 From 5fa70e8ba96965b44a971908080e5506b495a0bd Mon Sep 17 00:00:00 2001 From: eparreno Date: Fri, 9 Apr 2010 04:45:04 -0700 Subject: CL guide: revises fonts in a few places --- railties/guides/source/command_line.textile | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'railties/guides/source') diff --git a/railties/guides/source/command_line.textile b/railties/guides/source/command_line.textile index c888212604..f2b53023a5 100644 --- a/railties/guides/source/command_line.textile +++ b/railties/guides/source/command_line.textile @@ -18,12 +18,12 @@ h3. Command Line Basics There are a few commands that are absolutely critical to your everyday usage of Rails. In the order of how much you'll probably use them are: -* rails console -* rails server -* rake -* rails generate -* rails dbconsole -* rails app_name +* rails console +* rails server +* rake +* rails generate +* rails dbconsole +* rails app_name Let's create a simple Rails application to step through each of these commands in context. @@ -246,9 +246,13 @@ $ rake db:migrate INFO: Let's talk about unit tests. Unit tests are code that tests and makes assertions about code. In unit testing, we take a little part of code, say a method of a model, and test its inputs and outputs. Unit tests are your friend. The sooner you make peace with the fact that your quality of life will drastically increase when you unit test your code, the better. Seriously. We'll make one in a moment. -Let's see the interface Rails created for us. rails server; http://localhost:3000/high_scores +Let's see the interface Rails created for us. -We can create new high scores (55,160 on Space Invaders!) + +$ rails server + + +Go to your browser and open "http://localhost:3000/high_scores":http://localhost:3000/high_scores, now we can create new high scores (55,160 on Space Invaders!) h4. +rails console+ @@ -260,12 +264,12 @@ h4. +rails dbconsole+ h4. +rails plugin+ -The +rails plugin+ command simplifies plugin management; think a miniature version of the Gem utility. Let's walk through installing a plugin. You can call the sub-command *discover*, which sifts through repositories looking for plugins, or call *source* to add a specific repository of plugins, or you can specify the plugin location directly. +The +rails plugin+ command simplifies plugin management; think a miniature version of the Gem utility. Let's walk through installing a plugin. You can call the sub-command +discover+, which sifts through repositories looking for plugins, or call +source+ to add a specific repository of plugins, or you can specify the plugin location directly. + +Let's say you're creating a website for a client who wants a small accounting system. Every event having to do with money must be logged, and must never be deleted. Wouldn't it be great if we could override the behavior of a model to never actually take its record out of the database, but instead, just set a field? -Let's say you're creating a website for a client who wants a small accounting system. Every event having to do with money must be logged, and must never be deleted. Wouldn't it be great if we could override the behavior of a model to never actually take its record out of the database, but *instead*, just set a field? +There is such a thing! The plugin we're installing is called +acts_as_paranoid+, and it lets models implement a +deleted_at+ column that gets set when you call destroy. Later, when calling find, the plugin will tack on a database check to filter out "deleted" things. -There is such a thing! The plugin we're installing is called "acts_as_paranoid", and it lets models implement a "deleted_at" column that gets set when you call destroy. Later, when calling find, the plugin will tack on a database check to filter out "deleted" things. -================================================================================== $ rails plugin install http://svn.techno-weenie.net/projects/plugins/acts_as_paranoid + ./CHANGELOG -- cgit v1.2.3 From b2a2d9f91b62564e30ab6e77a1347f51f90156f2 Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Tue, 6 Apr 2010 08:46:57 +1000 Subject: Further expansion into how Bundler loads the gemfile. --- railties/guides/source/initialization.textile | 51 +++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) (limited to 'railties/guides/source') diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile index 2d64510c2f..1b76034f82 100644 --- a/railties/guides/source/initialization.textile +++ b/railties/guides/source/initialization.textile @@ -2021,7 +2021,7 @@ This sets up a couple of important things initially. If you specify a gem like t gem 'rails', "2.3.4" -This sets +options+ to be an empty hash, but +version+ to be +"2.3.4"+. TODO: How does one pass options and versions? +This sets +options+ to be an empty hash, but +version+ to be +"2.3.4"+. TODO: How does one pass options and versions at the same time? In the Gemfile for a default Rails project, the first +gem+ line is: @@ -2054,7 +2054,54 @@ This line will check that +options+ contains no deprecated options by using the end -+_normalize_hash+ will convert all the keys in the +opts+ hash to strings. ++_normalize_hash+ will convert all the keys in the +opts+ hash to strings. There is neither a +git+ or a +path+ key in the +opts+ hash so the next couple of lines are ignored, then the +source+ and +group+ keys are set up. + +TODO: Maybe it is best to cover what would happen in the case these lines did exist? + +The next line goes about defining a dependency for this gem: + + + @dependencies << Dependency.new(name, version, options) + + +This class is defined like this: + + + module Bundler + class Dependency < Gem::Dependency + attr_reader :autorequire + attr_reader :groups + + def initialize(name, version, options = {}, &blk) + super(name, version) + + @autorequire = nil + @groups = Array(options["group"] || :default).map { |g| g.to_sym } + @source = options["source"] + + if options.key?('require') + @autorequire = Array(options['require'] || []) + end + end + end + end + + +The +initialize+ method in +Gem::Dependency+ is defined: + + + def initialize(name, version_requirements, type=:runtime) + @name = name + unless TYPES.include? type + raise ArgumentError, "Valid types are #{TYPES.inspect}, not #{@type.inspect}" + end + @type = type + @version_requirements = Gem::Requirement.create version_requirements + @version_requirement = nil # Avoid warnings. + end + + + -- cgit v1.2.3 From e35f05cc8e2c9362edb6065d8ad39c8ec3bce349 Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Fri, 9 Apr 2010 06:45:49 +1000 Subject: Mention a way to turn off bundler and begin talking about version_requirements --- railties/guides/source/initialization.textile | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'railties/guides/source') diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile index 1b76034f82..9b6727b740 100644 --- a/railties/guides/source/initialization.textile +++ b/railties/guides/source/initialization.textile @@ -1790,6 +1790,8 @@ Now that Rails has finished loading all the Railties by way of +require 'rails/a Bundler.require :default, Rails.env +NOTE: It is worth mentioning here that you are not tied to using Bundler with Rails 3, but it is (of course) advised that you do. To "turn off" Bundler, comment out or remove the corresponding lines in _config/application.rb_ and _config/boot.rb_. + Bundler was +require+'d back in _config/boot.rb_ and now we'll dive into the internals of Bundler to determine precisely what this line accomplishes. h4. +Bundler.require+ @@ -2101,6 +2103,8 @@ The +initialize+ method in +Gem::Dependency+ is defined: end +The +version_requirements+ that was passed in here + -- cgit v1.2.3 From c93580b48069a98aef1bef658c02bc393f173d99 Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Fri, 9 Apr 2010 14:03:58 +1000 Subject: Further work on the bundler section. Almost there now. --- railties/guides/source/initialization.textile | 117 ++++++++++++++++++++++++-- 1 file changed, 111 insertions(+), 6 deletions(-) (limited to 'railties/guides/source') diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile index 9b6727b740..e256503067 100644 --- a/railties/guides/source/initialization.textile +++ b/railties/guides/source/initialization.textile @@ -1911,15 +1911,13 @@ The next method to be called here would be +definition+ and it is defined like end -We do not have +settings[:disabled_shared_gems]+ set to true so this will execute the code under the +else+. The +ENV["GEM_PATH"]+ will resemble +/usr/local/lib/ruby/gems/1.9.1:/home/you/.gem/ruby/1.9.1:/usr/local/lib/ruby/gems/1.9.1+ - -TODO: Why the duplicates? Added an issue: http://github.com/carlhuda/bundler/issues#issue/249 +We do not have +settings[:disabled_shared_gems]+ set to true so this will execute the code under the +else+. The +ENV["GEM_PATH"]+ will resemble +/usr/local/lib/ruby/gems/1.9.1:/home/you/.gem/ruby/1.9.1+ And +ENV["GEM_HOME"]+ will be the path to the gems installed into your home directory by Bundler, something resembling +/home/you/.bundle/ruby/1.9.1+. After +configure_gem_home_and_path+ is done the +definition+ method goes about creating a +Definition+ from either +Gemfile.lock+ if it exists, or the +gemfile+ previously located. +Gemfile.lock+ only exists if +bundle lock+ has been ran and so far it has not. -+Definition.from_lock+ is defined in _lib/definition.rb_: ++Definition.from_gemfile+ is defined in _lib/bundler/definition.rb_: def self.from_gemfile(gemfile) @@ -1933,7 +1931,7 @@ After +configure_gem_home_and_path+ is done the +definition+ method goes about c end -Now that the +gemfile+ is located +Dsl.evaluate+ goes about loading it. The code for this can be found in _lib/dsl.rb_: +Now that the +gemfile+ is located +Dsl.evaluate+ goes about loading it. The code for this can be found in _lib/bundler/dsl.rb_: def self.evaluate(gemfile) @@ -2103,11 +2101,118 @@ The +initialize+ method in +Gem::Dependency+ is defined: end -The +version_requirements+ that was passed in here +The +version_requirements+ that was passed in here will be inspected by +Gem::Requirement.create+ and return, for our +3.0.0beta2+ version string a +Gem::Requirement+ object: + + + #]]> + + +Going back to +Bundler::Dependency+, the next line simply sets +@autorequire+ to +nil+ and the next line is a little more interesting: + + + @autorequire = nil + @groups = Array(options["group"] || :default).map { |g| g.to_sym } + + +Here, bundler sets the +groups+ variable to be whatever +group+ we've set for this gem and also demonstrates through code that the +group+ option allows for multiple groups, so in the _Gemfile_ we can specify the same gem for multiple groups: + + + group :test, :cucumber do + gem 'faker' + end + + +The final lines in +initialize+ work on the +require+ option which is not passed: + + + if options.key?('require') + @autorequire = Array(options['require'] || []) + end + + +If it were to be used in the _Gemfile_, it would look like this: + + + gem 'thinking-sphinx', :require => "thinking_sphinx" + + +So far, this is what simply loading the _Gemfile_ does. + +h3. Bring forth the gems + +Now that the _Gemfile_ has finished being parsed, the next line is: + + + builder.to_definition + + +This method is defined in _lib/bundler/dsl.rb_ and does this: + + + def to_definition + Definition.new(@dependencies, @sources) + end + + +The +Bundler::Definition#initialize+ method is this: + + + def initialize(dependencies, sources) + @dependencies = dependencies + @sources = sources + end + + +Now Bundler has a +Bundler::Definition+ object to be passed back to the +load+ method from _lib/bundler.rb_: + + + def load(gemfile = default_gemfile) + root = Pathname.new(gemfile).dirname + Runtime.new root, definition(gemfile) + end + + +The +Bundler::Runtime+ class inherits from +Bundler::Environment+ and the reason this is pointed out is because +super+ is used in the +initialize+ method in +Bundler::Runtime+: + + + super + if locked? + write_rb_lock + end + + +Thankfully, the +Bundler::Environment#initialize+ method is nothing too complex: + + + def initialize(root, definition) + @root = root + @definition = definition + end + + +The +locked?+ method checks if the _Gemfile.lock_ or _.bundler/environment.rb_ files exist: + + def locked? + File.exist?("#{root}/Gemfile.lock") || File.exist?("#{root}/.bundle/environment.rb") + end + +And if they do will call +write_rb_lock+: + + def write_rb_lock + shared_helpers = File.read(File.expand_path("../shared_helpers.rb", __FILE__)) + template = File.read(File.expand_path("../templates/environment.erb", __FILE__)) + erb = ERB.new(template, nil, '-') + FileUtils.mkdir_p(rb_lock_file.dirname) + File.open(rb_lock_file, 'w') do |f| + f.puts erb.result(binding) + end + end + +This will write out to _.bundler/environment.rb_ the state of the current environment. h3. Firing it up! -- cgit v1.2.3 From 69d525948058b3a0cc6c3401caa8e05532638c5a Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Fri, 9 Apr 2010 15:34:13 +1000 Subject: Continue expanding on Bundler. --- railties/guides/source/initialization.textile | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'railties/guides/source') diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile index e256503067..7013c3c324 100644 --- a/railties/guides/source/initialization.textile +++ b/railties/guides/source/initialization.textile @@ -2214,6 +2214,25 @@ And if they do will call +write_rb_lock+: This will write out to _.bundler/environment.rb_ the state of the current environment. +Now a quick refresher. Bundler is still evaulating the code for the +require+ in _lib/bundler.rb_, and the +groups+ variable here is an +Array+ containing two elements: +:default+ and the current Rails environment: +development+: + + + def require(*groups) + gemfile = default_gemfile + load(gemfile).require(*groups) + end + + +The second +require+ method here: + + + load(gemfile).require(*groups) + + +Is defined on _bundler/runtime.rb_ + + + h3. Firing it up! -- cgit v1.2.3 From da69c5d8bf5ac4a81de3870eb51a7833bbe79ef5 Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Fri, 9 Apr 2010 17:52:34 +1000 Subject: Expansion on require method from runtime.rb --- railties/guides/source/initialization.textile | 37 ++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) (limited to 'railties/guides/source') diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile index 7013c3c324..d8d119f608 100644 --- a/railties/guides/source/initialization.textile +++ b/railties/guides/source/initialization.textile @@ -2229,9 +2229,44 @@ The second +require+ method here: load(gemfile).require(*groups) -Is defined on _bundler/runtime.rb_ +Is defined on _bundler/runtime.rb_: + + def require(*groups) + groups.map! { |g| g.to_sym } + groups = [:default] if groups.empty? + autorequires = autorequires_for_groups(*groups) + + groups.each do |group| + (autorequires[group] || [[]]).each do |path, explicit| + if explicit + Kernel.require(path) + else + begin + Kernel.require(path) + rescue LoadError + end + end + end + end + end + + +This method does TODO: Describe what magic this undertakes. +The first method to be called here is +autorequires_for_groups+: + + + def autorequires_for_groups(*groups) + groups.map! { |g| g.to_sym } + autorequires = Hash.new { |h,k| h[k] = [] } + + ordered_deps = [] + specs_for(*groups).each do |g| + dep = @definition.dependencies.find{|d| d.name == g.name } + ordered_deps << dep if dep && !ordered_deps.include?(dep) + end + h3. Firing it up! -- cgit v1.2.3 From 3401b9ba6dc4aa148b5e35cc987f243622ad61d6 Mon Sep 17 00:00:00 2001 From: wycats Date: Sat, 10 Apr 2010 04:51:41 -0400 Subject: Update the routing guide for style and to add information on new routing features --- railties/guides/source/routing.textile | 824 ++++++++++++++++----------------- 1 file changed, 390 insertions(+), 434 deletions(-) (limited to 'railties/guides/source') diff --git a/railties/guides/source/routing.textile b/railties/guides/source/routing.textile index cf71e700dc..92d38c4aa7 100644 --- a/railties/guides/source/routing.textile +++ b/railties/guides/source/routing.textile @@ -2,180 +2,111 @@ h2. Rails Routing from the Outside In This guide covers the user-facing features of Rails routing. By referring to this guide, you will be able to: -* Understand the purpose of routing -* Decipher the code in +routes.rb+ -* Construct your own routes, using either the @match@ method or the preferred RESTful style -* Identify how a route will map to a controller and action +* Understand the code in +routes.rb+ +* Construct your own routes, using either the preferred resourceful style or with the @match@ method +* Identify what parameters to expect an action to receive +* Automatically create URLs using route helpers +* Use advanced techniques such as constraints and Rack endpoints endprologue. -h3. The Dual Purpose of Routing +h3. The Purpose of the Rails Router -Rails routing is a two-way piece of machinery - rather as if you could turn trees into paper, and then turn paper back into trees. Specifically, it both connects incoming HTTP requests to the code in your application's controllers, and helps you generate URLs without having to hard-code them as strings. +The Rails router recognizes URLs and dispatches them to a controller's action. It can also generate URLs, avoiding the need to hardcode URL strings in your views. h4. Connecting URLs to Code -When your Rails application receives an incoming HTTP request, say +When your Rails application receives an incoming request -
+
 GET /patients/17
-
- -the routing engine within Rails is the piece of code that dispatches the request to the appropriate spot in your application. In this case, the application would most likely end up running the +show+ action within the +patients+ controller, displaying the details of the patient whose ID is 17. - -h4. Generating URLs from Code + -Routing also works in reverse. If your application contains this code: +it asks the router to match it to a controller action. If the first matching route is -@patient = Patient.find(17) +match "/patients/:id" => "patients#show" - -<%= link_to "Patient Record", patient_path(@patient) %> - - -Then the routing engine is the piece that translates that to a link to a URL such as +http://example.com/patients/17+. By using routing in this way, you can reduce the brittleness of your application as compared to one with hard-coded URLs, and make your code easier to read and understand. - -NOTE: Patient needs to be declared as a Restful resource for this style of translation to be available. +the request is dispatched to the +patients+ controller's +show+ action with { :id => "17" } in +params+. -h3. Quick Tour of +routes.rb+ - -There are two components to routing in Rails: the routing engine itself, which is supplied as part of Rails, and the file +config/routes.rb+, which contains the actual routes that will be used by your application. Learning exactly what you can put in +routes.rb+ is the main topic of this guide, but before we dig in let's get a quick overview. - -h4. Processing the File - -In format, +routes.rb+ is nothing more than one big block sent to +ApplicationName::Application.routes.draw+. Within this block, you can have comments, but it's likely that most of your content will be individual lines of code - each line being a route in your application. You'll find five main types of content in this file: - -* RESTful Routes -* Named Routes -* Nested Routes -* Regular Routes -* Default Routes - -Each of these types of route is covered in more detail later in this guide. - -The +routes.rb+ file is processed from top to bottom when a request comes in. The request will be dispatched to the first matching route, and then proceeds to the next. If there is no matching route, then Rails returns HTTP status 404 to the caller. - -h4. RESTful Routes - -RESTful routes take advantage of the built-in REST orientation of Rails to wrap up a lot of routing information with a single declaration. A RESTful route looks like this: - - -resources :books - - -h4(#quick-tour-named-routes). Named Routes - -Named routes give you very readable links in your code, as well as handling incoming requests. Here's a typical named route: - - -match 'login' => 'sessions#new', :as => 'login' - +h4. Generating URLs from Code -If you're coming from Rails 2, this route will be equivalent to: +You can also generate routes. If your application contains this code: -map.login '/login', :controller => 'sessions', :action => 'new' +@patient = Patient.find(17) -You will also notice that +sessions#new+ is a shorthand for +:controller => 'sessions', :action => 'new'+. By declaring a named route such as this, you can use +login_path+ or +login_url+ in your controllers and views to generate the URLs for this route. A RESTful generates named routes without the need to explicitly generate a named route via +as+ key. + +<%= link_to "Patient Record", patients_path(@patient.id) %> + -h4. Nested Routes +The router will generate the path +/patients/17+. This reduces the brittleness of your view and makes your code easier to understand. -Nested routes let you declare that one resource is contained within another resource. You'll see later on how this translates to URLs and paths in your code. For example, if your application includes parts, each of which belongs to an assembly, you might have this nested route declaration: +h3. Resource Routing: the Rails Default - -resources :assemblies do - resources :parts -end - +Resource routing allows you to quickly declare all of the common routes for a given resourceful controller. Instead of declaring separate routes for your +index+, +show+, +new+, +edit+, +create+, +update+ and +destroy+ actions, a resourceful route declares them in a single line of code. -h4(#quick-tour-regular-routes). Regular Routes +h4. Resources on the Web -In many applications, you'll also see non-RESTful routing, which explicitly connects the parts of a URL to a particular action. For example, +Browsers request pages from Rails by making a request for a URL using a specific HTTP method, such as +GET+, +POST+, +PUT+ and +DELETE+. Each method is a request to perform an operation on the resource. A resource route maps a number of related request to the actions in a single controller. - -match 'parts/:number' => 'inventory#show' - +When your Rails application receives an incoming request for -h4. Default Routes + +DELETE /photos/17 + -The default route is a safety net that catches otherwise-unrouted requests. Many Rails applications will contain this default route: +it asks the router to map it to a controller action. If the first matching route is -match ':controller(/:action(/:id(.:format)))' +resources :photos -In Rails 3, this route is commented out advising to use RESTful routes as much as possible. So if you're using RESTful routing for everything in your application, you will probably want to leave it like that. - -h3. RESTful Routing: the Rails Default - -RESTful routing is the current standard for routing in Rails, and it's the one that you should prefer for new applications. It can take a little while to understand how RESTful routing works, but it's worth the effort; your code will be easier to read and you'll be working with Rails, rather than fighting against it, when you use this style of routing. - -h4. What is REST? - -The foundation of RESTful routing is generally considered to be Roy Fielding's doctoral thesis, "Architectural Styles and the Design of Network-based Software Architectures":http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm. Fortunately, you need not read this entire document to understand how REST works in Rails. REST, an acronym for Representational State Transfer, boils down to two main principles for our purposes: - -* Using resource identifiers (which, for the purposes of discussion, you can think of as URLs) to represent resources -* Transferring representations of the state of that resource between system components. - -For example, to a Rails application a request such as this: - -
-DELETE /photos/17
-
- -would be understood to refer to a photo resource with the ID of 17, and to indicate a desired action - deleting that resource. REST is a natural style for the architecture of web applications, and Rails makes it even more natural by using conventions to shield you from some of the RESTful complexities. +Rails would dispatch that request to the +destroy+ method on the +photos+ controller with { :id => "17" } in +params+. h4. CRUD, Verbs, and Actions -In Rails, a RESTful route provides a mapping between HTTP verbs, controller actions, and (implicitly) CRUD operations in a database. A single entry in the routing file, such as +In Rails, a resourceful route provides a mapping between HTTP verbs and URLs and controller actions. By convention, each action also maps to particular CRUD operations in a database. A single entry in the routing file, such as resources :photos -creates seven different routes in your application: +creates seven different routes in your application, all mapping to the +Photos+ controller: -|_.HTTP verb|_.URL |_.controller|_.action |_.used for| -|GET |/photos |Photos |index |display a list of all photos| -|GET |/photos/new |Photos |new |return an HTML form for creating a new photo| -|POST |/photos |Photos |create |create a new photo| -|GET |/photos/1 |Photos |show |display a specific photo| -|GET |/photos/1/edit |Photos |edit |return an HTML form for editing a photo| -|PUT |/photos/1 |Photos |update |update a specific photo| -|DELETE |/photos/1 |Photos |destroy |delete a specific photo| - -For the specific routes (those that reference just a single resource), the identifier for the resource will be available within the corresponding controller action as +params[:id]+. +|_. Verb |_.URL |_.action |_.used for| +|GET |/photos |index |display a list of all photos| +|GET |/photos/new |new |return an HTML form for creating a new photo| +|POST |/photos |create |create a new photo| +|GET |/photos/:id |show |display a specific photo| +|GET |/photos/:id/edit |edit |return an HTML form for editing a photo| +|PUT |/photos/:id |update |update a specific photo| +|DELETE |/photos/:id |destroy |delete a specific photo| h4. URLs and Paths -Creating a RESTful route will also make available a pile of helpers within your application, something that requires explicit mention otherwise: +Creating a resourceful route will also expose a number of helpers to the controllers in your application. In the case of +resources :photos+: -* +photos_url+ and +photos_path+ map to the path for the index and create actions -* +new_photo_url+ and +new_photo_path+ map to the path for the new action -* +edit_photo_url+ and +edit_photo_path+ map to the path for the edit action -* +photo_url+ and +photo_path+ map to the path for the show, update, and destroy actions +* +photos_path+ returns +/photos+ +* +new_photo_path+ returns +/photos/new+ +* +edit_photo_path+ returns +/photos/edit+ +* +photo_path(id)+ returns +/photos/:id+ (for instance, +photo_path(10)+ returns +/photos/10+) -NOTE: Because routing makes use of the HTTP verb as well as the path in the request to dispatch requests, the seven routes generated by a RESTful routing entry only give rise to four pairs of helpers. +Each of these helpers has a corresponding +_url+ helper (such as +photos_url+) which returns the same path prefixed with the current host, port and path prefix. -In each case, the +_url+ helper generates a string containing the entire URL that the application will understand, while the +_path+ helper generates a string containing the relative path from the root of the application. For example: - - -photos_url # => "http://www.example.com/photos" -photos_path # => "/photos" - +NOTE: Because the router uses the HTTP verb and URL to match inbound requests, four URLs map to seven different actions. h4. Defining Multiple Resources at the Same Time -If you need to create routes for more than one RESTful resource, you can save a bit of typing by defining them all with a single call to +resources+: +If you need to create routes for more than one resource, you can save a bit of typing by defining them all with a single call to +resources+: resources :photos, :books, :videos -This has exactly the same effect as +This works exactly the same as resources :photos @@ -185,205 +116,91 @@ resources :videos h4. Singular Resources -You can also apply RESTful routing to singleton resources within your application. In this case, you use +resource+ instead of +resources+ and the route generation is slightly different. For example, a routing entry of +Sometimes, you have a resource that clients always look up without referencing an ID. A common example, +/profile+ always shows the profile of the currently logged in user. In this case, you can use a singular resource to map +/profile+ (rather than +/profile/:id+) to the +show+ action. resource :geocoder -creates six different routes in your application: - -|_.HTTP verb|_.URL |_.controller|_.action |_.used for| -|GET |/geocoder/new |Geocoders |new |return an HTML form for creating the new geocoder| -|POST |/geocoder |Geocoders |create |create the new geocoder| -|GET |/geocoder |Geocoders |show |display the one and only geocoder resource| -|GET |/geocoder/edit |Geocoders |edit |return an HTML form for editing the geocoder| -|PUT |/geocoder |Geocoders |update |update the one and only geocoder resource| -|DELETE |/geocoder |Geocoders |destroy |delete the geocoder resource| - -NOTE: Even though the name of the resource is singular in +routes.rb+, the matching controller is still plural. - -A singular RESTful route generates an abbreviated set of helpers: - -* +new_geocoder_url+ and +new_geocoder_path+ map to the path for the new action -* +edit_geocoder_url+ and +edit_geocoder_path+ map to the path for the edit action -* +geocoder_url+ and +geocoder_path+ map to the path for the create, show, update, and destroy actions - -h4. Customizing Resources +creates six different routes in your application, all mapping to the +Geocoders+ controller: -Although the conventions of RESTful routing are likely to be sufficient for many applications, there are a number of ways to customize the way that RESTful routes work. These options include: +|_. Verb |_.URL |_.action |_.used for| +|GET |/geocoder/new |new |return an HTML form for creating the geocoder| +|POST |/geocoder |create |create the new geocoder| +|GET |/geocoder |show |display the one and only geocoder resource| +|GET |/geocoder/edit |edit |return an HTML form for editing the geocoder| +|PUT |/geocoder |update |update the one and only geocoder resource| +|DELETE |/geocoder |destroy |delete the geocoder resource| -* +:controller+ -* +:singular+ -* +:constraints+ -* +:as+ -* +:path_names+ -* +:only+ -* +:except+ +NOTE: Because you might want to use the same controller for a singular route (+/account+) and a plural route (+/accounts/45+), singular resources map to plural controllers. -You can also add additional routes via the +member+ and +collection+ blocks, which are discussed later in this guide. +A singular resourceful route generates these helpers: -h5. Using +:controller+ +* +new_geocoder_path+ returns +/geocoder/new+ +* +edit_geocoder_path+ returns +/geocoder/edit+ +* +geocoder_path+ returns +/geocoder+ -The +:controller+ option lets you use a controller name that is different from the public-facing resource name. For example, this routing entry: - - -resources :photos, :controller => "images" - - -will recognize incoming URLs containing +photo+ but route the requests to the Images controller: - -|_.HTTP verb|_.URL |_.controller|_.action |_.used for| -|GET |/photos |Images |index |display a list of all images| -|GET |/photos/new |Images |new |return an HTML form for creating a new image| -|POST |/photos |Images |create |create a new image| -|GET |/photos/1 |Images |show |display a specific image| -|GET |/photos/1/edit |Images |edit |return an HTML form for editing an image| -|PUT |/photos/1 |Images |update |update a specific image| -|DELETE |/photos/1 |Images |destroy |delete a specific image| - -NOTE: The helpers will be generated with the name of the resource, not the name of the controller. So in this case, you'd still get +photos_path+, +new_photo_path+, and so on. +As with plural resources, the same helpers ending in +_url+ will also include the host, port and path prefix. h4. Controller Namespaces and Routing -Rails allows you to group your controllers into namespaces by saving them in folders underneath +app/controllers+. The +:controller+ option provides a convenient way to use these routes. For example, you might have a resource whose controller is purely for admin users in the +admin+ folder: +You may wish to organize groups of controllers under a namespace. Most commonly, you might group a number of administrative controllers under an +Admin::+ namespace. You would place these controllers under the +app/controllers/admin+ directory, and you can group them together in your router: -resources :photos, :controller => "admin/photos" - - -If you use controller namespaces, you need to be aware of a subtlety in the Rails routing code: it always tries to preserve as much of the namespace from the previous request as possible. For example, if you are on a view generated from the +photo_path+ helper, and you follow a link generated with +<%= link_to "show", photo_path(1) %>+ you will end up on the view generated by +admin/photos/show+, but you will also end up in the same place if you have +<%= link_to "show", {:controller => "photos", :action => "show"} %>+ because Rails will generate the show URL relative to the current URL. - -TIP: If you want to guarantee that a link goes to a top-level controller, use a preceding slash to anchor the controller name: +<%= link_to "show", {:controller => "/photos", :action => "show"} %>+ - -You can also specify a controller namespace with the +namespace+ method instead of a path. This can be especially useful when mapping multiple namespaced routes together: - - -namespace :admin do - resources :photos, :videos +namespace "admin" do + resources :posts, :comments end -That would give you routing for +admin/photos+ and +admin/videos+ controllers. - -The difference between generating routes through +namespace+ and the +:controller+ key is that the +namespace+ will add +admin+ to the generated helpers as well, so the above route generates +admin_photos_path+. - -h5. Using +:singular+ - -If for some reason Rails isn't doing what you want in converting the plural resource name to a singular name in member routes, you can override its judgment with the +:singular+ option: - - -resources :teeth, :singular => "tooth" - - -TIP: Depending on the other code in your application, you may prefer to add additional rules to the +Inflector+ class instead. - -h5. Using +:constraints+ - -You can use the +:constraints+ option in a RESTful route to impose a format on the implied parameter in routes. For example: - - -resources :photos, :constraints => {:id => /[A-Z][A-Z][0-9]+/} - - -This declaration constrains the +:id+ parameter to match the supplied regular expression. So, in this case, +/photos/1+ would no longer be recognized by this route, but +/photos/RR27+ would. - -h5. Using +:as+ - -The +:as+ option lets you override the normal naming for the actual generated paths. For example: - - -resources :photos, :as => "images" - - -will recognize incoming URLs containing +image+ but route the requests to the Photos controller: - -|_.HTTP verb|_.URL |_.controller|_.action |_:used for| -|GET |/images |Photos |index |display a list of all photos| -|GET |/images/new |Photos |new |return an HTML form for creating a new photo| -|POST |/images |Photos |create |create a new photo| -|GET |/images/1 |Photos |show |display a specific photo| -|GET |/images/1/edit |Photos |edit |return an HTML form for editing a photo| -|PUT |/images/1 |Photos |update |update a specific photo| -|DELETE |/images/1 |Photos |destroy |delete a specific photo| +This will create a number of routes for each of the +posts+ and +comments+ controller. For +Admin::PostsController+, Rails will create: -NOTE: The helpers will be generated with the name of the resource, not the path name. So in this case, you'd still get +photos_path+, +new_photo_path+, and so on. +|_. Verb |_.URL |_.action |_. helper | +|GET |/admin/photos |index | admin_photos_path | +|GET |/admin/photos/new |new | new_admin_photos_path | +|POST |/admin/photos |create | admin_photos_path | +|GET |/admin/photos/1 |show | admin_photo_path(id) | +|GET |/admin/photos/1/edit |edit | edit_admin_photo_path(id) | +|PUT |/admin/photos/1 |update | admin_photo_path(id) | +|DELETE |/admin/photos/1 |destroy | admin_photo_path(id) | -h5. Using +:path_names+ - -The +:path_names+ option lets you override the automatically-generated "new" and "edit" segments in URLs: +If you want to route +/photos+ (without the prefix +/admin+) to +Admin::PostsController+, you could use -resources :photos, :path_names => { :new => 'make', :edit => 'change' } - - -This would cause the routing to recognize URLs such as - -
-/photos/make
-/photos/1/change
-
- -NOTE: The actual action names aren't changed by this option; the two URLs shown would still route to the new and edit actions. - -TIP: If you find yourself wanting to change this option uniformly for all of your routes, you can set a default in your environment: - - -config.action_controller.resources_path_names = { :new => 'make', :edit => 'change' } +scope :module => "admin" do + resources :posts, :comments +end -h5. Using +:name_prefix+ - -You can use the :name_prefix option to avoid collisions between routes. This is most useful when you have two resources with the same name that use +:path_prefix+ to map differently. For example: +or, for a single case -resources :photos :name_prefix => 'photographer' +resources :posts, :module => "admin" -This combination will give you route helpers such as +photographer_photos_path+ to use in your code. - -NOTE: You can also use +:name_prefix+ with non-RESTful routes. - -h5. Using +:only+ and +:except+ - -By default, Rails creates routes for all seven of the default actions (index, show, new, create, edit, update, and destroy) for every RESTful route in your application. You can use the +:only+ and +:except+ options to fine-tune this behavior. The +:only+ option specifies that only certain routes should be generated: +If you want to route +/admin/photos+ to +PostsController+ (without the +Admin::+ module prefix), you could use -resources :photos, :only => [:index, :show] - - -With this declaration, a +GET+ request to +/photos+ would succeed, but a +POST+ request to +/photos+ (which would ordinarily be routed to the create action) will fail. - -The +:except+ option specifies a route or list of routes that should _not_ be generated: - - -resources :photos, :except => :destroy +scope "/admin" do + resources :posts, :comments +end -In this case, all of the normal routes except the route for +destroy+ (a +DELETE+ request to +/photos/id+) will be generated. - -TIP: If your application has many RESTful routes, using +:only+ and +:except+ to generate only the routes that you actually need can cut down on memory use and speed up the routing process. - -h5. Changing Path Names for Resources - -Using +scope+, we can alter path names generated by resources: +or, for a single case -scope(:resources_path_names => { :new => "neu", :edit => "bearbeiten" }) do - resources :categories, :path => "kategorien" -end +resources :posts, :path => "/admin" -With +scope+ defined, it now generates routes with customized path names. +In each of these cases, the named routes remain the same as if you did not use +scope+. In the last case, the following URLs map to +PostsController+: -|_.HTTP verb|_.URL |_.controller |_.action |_:used for| -|GET |/kategorien |Categories |index |display a list of all categories| -|GET |/kategorien/neu |Categories |new |return an HTML form for creating a new category| -|POST |/kategorien |Categories |create |create a new category| -|GET |/kategorien/1 |Categories |show |display a specific category| -|GET |/kategorien/:id/bearbeiten |Categories |edit |return an HTML form for editing a category| -|PUT |/kategorien/1 |Categories |update |update a specific category| -|DELETE |/kategorien/1 |Categories |destroy |delete a specific category| +|_. Verb |_.URL |_.action |_. helper | +|GET |photos |index | photos_path | +|GET |photos/new |new | photos_path | +|POST |photos |create | photos_path | +|GET |photos/1 |show | photo_path(id) | +|GET |photos/1/edit |edit | dmin_photo_path(id) | +|PUT |photos/1 |update | photo_path(id) | +|DELETE |photos/1 |destroy | photo_path(id) | h4. Nested Resources @@ -399,7 +216,7 @@ class Ad < ActiveRecord::Base end
-Each ad is logically subservient to one magazine. Nested routes allow you to capture this relationship in your routing. In this case, you might include this route declaration: +Nested routes allow you to capture this relationship in your routing. In this case, you could include this route declaration: resources :magazines do @@ -407,31 +224,19 @@ resources :magazines do end -In addition to the routes for magazines, this declaration will also create routes for ads, each of which requires the specification of a magazine in the URL: - -|_.HTTP verb|_.URL |_.controller|_.action |_.used for| -|GET |/magazines/1/ads |Ads |index |display a list of all ads for a specific magazine| -|GET |/magazines/1/ads/new |Ads |new |return an HTML form for creating a new ad belonging to a specific magazine| -|POST |/magazines/1/ads |Ads |create |create a new ad belonging to a specific magazine| -|GET |/magazines/1/ads/1 |Ads |show |display a specific ad belonging to a specific magazine| -|GET |/magazines/1/ads/1/edit |Ads |edit |return an HTML form for editing an ad belonging to a specific magazine| -|PUT |/magazines/1/ads/1 |Ads |update |update a specific ad belonging to a specific magazine| -|DELETE |/magazines/1/ads/1 |Ads |destroy |delete a specific ad belonging to a specific magazine| - +In addition to the routes for magazines, this declaration will also route ads to an +AdsController+. The ad URLs require a magazine: -This will also create routing helpers such as +magazine_ads_url+ and +edit_magazine_ad_path+. +|_.Verb |_.URL |_.action |_.used for| +|GET |/magazines/1/ads |index |display a list of all ads for a specific magazine| +|GET |/magazines/1/ads/new |new |return an HTML form for creating a new ad belonging to a specific magazine| +|POST |/magazines/1/ads |create |create a new ad belonging to a specific magazine| +|GET |/magazines/1/ads/1 |show |display a specific ad belonging to a specific magazine| +|GET |/magazines/1/ads/1/edit |edit |return an HTML form for editing an ad belonging to a specific magazine| +|PUT |/magazines/1/ads/1 |update |update a specific ad belonging to a specific magazine| +|DELETE |/magazines/1/ads/1 |destroy |delete a specific ad belonging to a specific magazine| -h5(#nested-name-prefix). Using +:name_prefix+ - -The +:name_prefix+ option overrides the automatically-generated prefix in nested route helpers. For example, - - -resources :magazines do - resources :ads, :name_prefix => 'periodical' -end - -This will create routing helpers such as +periodical_ads_url+ and +periodical_edit_ad_path+. +This will also create routing helpers such as +magazine_ads_url+ and +edit_magazine_ad_path+. These helpers take an instance of Magazine as the first parameter (+magazine_ads_url(@magazine)+). h5. Limits to Nesting @@ -455,33 +260,9 @@ The corresponding route helper would be +publisher_magazine_photo_url+, requirin TIP: _Resources should never be nested more than 1 level deep._ -h5. Shallow Nesting +h4. Creating URLs From Objects -The +:shallow+ option provides an elegant solution to the difficulties of deeply-nested routes. If you specify this option at any level of routing, then paths for nested resources which reference a specific member (that is, those with an +:id+ parameter) will not use the parent path prefix or name prefix. To see what this means, consider this set of routes: - - -resources :publishers, :shallow => true do - resources :magazines do - resources :photos - end -end - - -This will enable recognition of (among others) these routes: - -
-/publishers/1           ==> publisher_path(1)
-/publishers/1/magazines ==> publisher_magazines_path(1)
-/magazines/2            ==> magazine_path(2)
-/magazines/2/photos     ==> magazines_photos_path(2)
-/photos/3               ==> photo_path(3)
-
- -With shallow nesting, you need only supply enough information to uniquely identify the resource that you want to work with. - -h4. Route Generation from Arrays - -In addition to using the generated routing helpers, Rails can also generate RESTful routes from an array of parameters. For example, suppose you have a set of routes generated with these entries in routes.rb: +In addition to using the routing helpers, Rails can also create URLs from an array of parameters. For example, suppose you have this set of routes: resources :magazines do @@ -489,49 +270,35 @@ resources :magazines do end -Rails will generate helpers such as magazine_ad_path that you can use in building links: +When using +magazine_ad_path+, you can pass in instances of +Magazine+ and +Ad+ instead of the numeric IDs. - + <%= link_to "Ad details", magazine_ad_path(@magazine, @ad) %> - - -Another way to refer to the same route is with an array of objects: - - -<%= link_to "Ad details", [@magazine, @ad] %> - +
-This format is especially useful when you might not know until runtime which of several types of object will be used in a particular link. +You can also use +url_for+ with a set of objects, and Rails will automatically determine which route you want: -h4. Namespaced Resources + +<%= link_to "Ad details", url_for(@magazine, @ad) %> + -It's possible to do some quite complex things by combining +scope+ and +:name_prefix+. For example, you can use the combination of these two options to move administrative resources to their own folder in your application: +In this case, Rails will see that +@magazine+ is a +Magazine+ and +@ad+ is an +Ad+ and will therefore use the +magazine_ad_path+ helper. In helpers like +link_to+, you can specify just the object in place of the full +url_for+ call: - -scope 'admin' do - resources :photos, :name_prefix => "admin", :controller => 'admin/photos' - scope 'photos' do - resources :tags, :name_prefix => 'admin_photo', :controller => 'admin/photo_tags' - resources :ratings, :name_prefix => 'admin_photo', :controller => 'admin/photo_ratings' - end -end - + +<%= link_to "Ad details", [@magazine, @ad] %> + -The good news is that if you find yourself using this level of complexity, you can stop. Rails supports _namespaced resources_ to make placing resources in their own folder a snap. Here's the namespaced version of those same three routes: +If you wanted to link to just a magazine, you could leave out the +Array+: - -namespace :admin do - resources :photos do - resources :tags, :ratings - end -end - + +<%= link_to "Magazine details", @magazine %> + -As you can see, the namespaced version is much more succinct than the one that spells everything out - but it still creates the same routes. For example, you'll get +admin_photos_url+ that expects to find an +Admin::PhotosController+ and that matches +admin/photos+, and +admin_photos_ratings_path+ that matches +/admin/photos/_photo_id_/ratings+, expecting to use +Admin::RatingsController+. Even though you're not specifying +path_prefix+ explicitly, the routing code will calculate the appropriate +path_prefix+ from the route nesting. +This allows you to treat instances of your models as URLs, and is a key advantage to using the resourceful style. h4. Adding More RESTful Actions -You are not limited to the seven routes that RESTful routing creates by default. If you like, you may add additional member routes (those which apply to a single instance of the resource), additional new routes (those that apply to creating a new resource), or additional collection routes (those which apply to the collection of resources as a whole). +You are not limited to the seven routes that RESTful routing creates by default. If you like, you may add additional routes that apply to the collection or individual members of the collection. h5. Adding Member Routes @@ -545,9 +312,9 @@ resources :photos do end -This will enable Rails to recognize URLs such as +/photos/1/preview+ using the GET HTTP verb, and route them to the preview action of the Photos controller. It will also create the +preview_photo_url+ and +preview_photo_path+ route helpers. +This will recognize +/photos/1/preview+ with GET, and route to the +preview+ action of +PhotosController+. It will also create the +preview_photo_url+ and +preview_photo_path+ helpers. -Within the block of member routes, each route name specifies the HTTP verb that it will recognize. You can use +get+, +put+, +post+, or +delete+ here. If you don't have multiple +member+ route, you can also passing +:on+ to the routing. +Within the block of member routes, each route name specifies the HTTP verb that it will recognize. You can use +get+, +put+, +post+, or +delete+ here. If you don't have multiple +member+ routes, you can also passing +:on+ to a route. resources :photos do @@ -557,7 +324,7 @@ end h5. Adding Collection Routes -To add a collection route, use the +:collection+ option: +To add a route to the collection: resources :photos do @@ -567,9 +334,9 @@ resources :photos do end -This will enable Rails to recognize URLs such as +/photos/search+ using the GET HTTP verb, and route them to the search action of the Photos controller. It will also create the +search_photos_url+ and +search_photos_path+ route helpers. +This will enable Rails to recognize URLs such as +/photos/search+ with GET, and route to the +search+ action of +PhotosController+. It will also create the +search_photos_url+ and +search_photos_path+ route helpers. -Just as with member routes, you can passing +:on+ to the routing. +Just as with member routes, you can pass +:on+ to a route. resources :photos do @@ -577,24 +344,17 @@ resources :photos do end -h5. Adding New Routes - -As of writing, Rails 3 has deprecated +:new+ option from routing. You will need to explicit define the route using +match+ method - - -resources :photos -match 'photos/new/upload' => 'photos#upload', :as => 'upload_new_photos' - - h5. A Note of Caution -If you find yourself adding many extra actions to a RESTful route, it's time to stop and ask yourself whether you're disguising the presence of another resource that would be better split off on its own. When the +member+ and +collection+ hashes become a dumping-ground, RESTful routes lose the advantage of easy readability that is one of their strongest points. +If you find yourself adding many extra actions to a resourceful route, it's time to stop and ask yourself whether you're disguising the presence of another resource. -h3. Regular Routes +h3. Non-Resourceful Routes -In addition to RESTful routing, Rails supports regular routing - a way to map URLs to controllers and actions. With regular routing, you don't get the masses of routes automatically generated by RESTful routing. Instead, you must set up each route within your application separately. +In addition to resource routing, Rails has powerful support for routing arbitrary URLs to actions. Here, you don't get groups of routes automatically generated by resourceful routing. Instead, you set up each route within your application separately. -While RESTful routing has become the Rails standard, there are still plenty of places where the simpler regular routing works fine. You can even mix the two styles within a single application. In general, you should prefer RESTful routing _when possible_, because it will make parts of your application easier to write. But there's no need to try to shoehorn every last piece of your application into a RESTful framework if that's not a good fit. +While you should usually use resourceful routing, there are still many places where the simpler routing is more appropriate. There's no need to try to shoehorn every last piece of your application into a resourceful framework if that's not a good fit. + +In particular, simple routing makes it very easy to map legacy URLs to new Rails actions. h4. Bound Parameters @@ -604,80 +364,121 @@ When you set up a regular route, you supply a series of symbols that Rails maps match ':controller(/:action(/:id))' -If an incoming request of +/photos/show/1+ is processed by this route (because it hasn't matched any previous route in the file), then the result will be to invoke the +show+ action of the +Photos+ controller, and to make the final parameter (1) available as +params[:id]+. This route will also route the incoming request of +/photos+ to PhotosController, since +:action+ and +:id+ are optional parameters, denoted by parenthesis. +If an incoming request of +/photos/show/1+ is processed by this route (because it hasn't matched any previous route in the file), then the result will be to invoke the +show+ action of the +PhotosController+, and to make the final parameter +"1"+ available as +params[:id]+. This route will also route the incoming request of +/photos+ to +PhotosController+, since +:action+ and +:id+ are optional parameters, denoted by parentheses. -h4. Wildcard Components +h4. Dynamic Segments -You can set up as many wildcard symbols within a regular route as you like. Anything other than +:controller+ or +:action+ will be available to the matching action as part of the params hash. So, if you set up this route: +You can set up as many dynamic segments within a regular route as you like. Anything other than +:controller+ or +:action+ will be available to the action as part of +params+. If you set up this route: match ':controller/:action/:id/:user_id' -An incoming URL of +/photos/show/1/2+ will be dispatched to the +show+ action of the +Photos+ controller. +params[:id]+ will be set to 1, and +params[:user_id]+ will be set to 2. +An incoming URL of +/photos/show/1/2+ will be dispatched to the +show+ action of the +PhotosController+. +params[:id]+ will be +"1"+, and +params[:user_id]+ will be +"2"+. -h4. Static Text +h4. Static Segments -You can specify static text when creating a route. In this case, the static text is used only for matching the incoming requests: +You can specify static segments when creating a route. match ':controller/:action/:id/with_user/:user_id' -This route would respond to URLs such as +/photos/show/1/with_user/2+. +This route would respond to URLs such as +/photos/show/1/with_user/2+. In this case, +params+ would be { :controller => "photos", :action => "show", :id => "1", :user_id => "2" }. -h4. Querystring Parameters +h4. The Query String -Rails routing automatically picks up querystring parameters and makes them available in the +params+ hash. For example, with this route: +The +params+ will also include any parameters from the query string. For example, with this route: match ':controller/:action/:id -An incoming URL of +/photos/show/1?user_id=2+ will be dispatched to the +show+ action of the +Photos+ controller. +params[:id]+ will be set to 1, and +params[:user_id]+ will be equal to 2. +An incoming URL of +/photos/show/1?user_id=2+ will be dispatched to the +show+ action of the +Photos+ controller. +params+ will be { :controller => "photos", :action => "show", :id => "1", :user_id => "2" }. h4. Defining Defaults -You do not need to explicitly use the +:controller+ and +:action+ symbols within a route. You can supply defaults for these two parameters by putting it after +=>+: +You do not need to explicitly use the +:controller+ and +:action+ symbols within a route. You can supply them as defaults: match 'photos/:id' => 'photos#show' -With this route, an incoming URL of +/photos/12+ would be dispatched to the +show+ action within the +Photos+ controller. +With this route, Rails will match an incoming URL of +/photos/12+ to the +show+ action of +PhotosController+. -You can also define other defaults in a route by supplying a hash for the +:defaults+ option. This even applies to parameters that are not explicitly defined elsewhere in the route. For example: +You can also define other defaults in a route by supplying a hash for the +:defaults+ option. This even applies to parameters that you do not specify as dynamic segments. For example: match 'photos/:id' => 'photos#show', :defaults => { :format => 'jpg' } -With this route, an incoming URL of +photos/12+ would be dispatched to the +show+ action within the +Photos+ controller, and +params[:format]+ will be set to +jpg+. +Rails would match +photos/12+ to the +show+ action of +PhotosController+, and set +params[:format]+ to +"jpg"+. -h4. Named Routes +h4. Naming Routes -Regular routes need not use the +connect+ method. You can use any other name here to create a _named route_. For example, +You can specify a name for any route using the +:as+ option. match 'logout' => 'sessions#destroy', :as => :logout -This will do two things. First, requests to +/logout+ will be sent to the +destroy+ action of the +Sessions+ controller. Second, Rails will maintain the +logout_path+ and +logout_url+ helpers for use within your code. +This will create +logout_path+ and +logout_url+ as named helpers in your application. Calling +logout_path+ will return +/logout+ -h4. Route Constraints +h4. Segment Constraints -You can use the +:constraints+ option to enforce a format for any parameter in a route: +You can use the +:constraints+ option to enforce a format for a dynamic segment: match 'photo/:id' => 'photos#show', :constraints => { :id => /[A-Z]\d{5}/ } -This route would respond to URLs such as +/photo/A12345+. You can more succinctly express the same route this way: +This route would match URLs such as +/photo/A12345+. You can more succinctly express the same route this way: match 'photo/:id' => 'photos#show', :id => /[A-Z]\d{5}/ +h4. Request-Based Constraints + +You can also constrain a route based on any method on the Request object that returns a +String+. + +You specify a request-based constraint the same way that you specify a segment constraint: + + +match "photo", :constraints => {:subdomain => "admin"} + + +You can also specify constrains in a block form: + + +namespace "admin" do + constraints :subdomain => "admin" do + resources :photos + end +end + + +h4. Advanced Constraints + +If you have a more advanced constraint, you can provide an object that responds to +matches?+ that Rails should use. Let's say you wanted to route all users on a blacklist to the +BlacklistController+. You could do: + + +class BlacklistConstraint + def initialize + @ips = Blacklist.retrieve_ips + end + + def matches?(request) + @ips.include?(request.remote_ip) + end +end + +TwitterClone::Application.routes.draw do + match "*path" => "blacklist#index", + :constraints => BlacklistConstraint.new +end + + h4. Route Globbing Route globbing is a way to specify that a particular parameter should be matched to all the remaining parts of a route. For example @@ -686,89 +487,244 @@ Route globbing is a way to specify that a particular parameter should be matched match 'photo/*other' => 'photos#unknown' -This route would match +photo/12+ or +/photo/long/path/to/12+ equally well, creating an array of path segments as the value of +params[:other]+. +This route would match +photo/12+ or +/photo/long/path/to/12+, setting +params[:other]+ to +"12"+ or +"long/path/to/12"+. + +h4. Redirection + +You can redirect any path to another path using the +redirect+ helper in your router: + + +match "/stories" => redirect("/posts") + + +You can also reuse dynamic segments from the match in the path to redirect to: + + +match "/stories/:name" => redirect("/posts/%{name}") + + +You can also provide a block to redirect, which receives the params and (optionally) the request object: -h3. Formats and +respond_to+ + +match "/stories/:name" => redirect {|params| "/posts/#{params[:name].pluralize}" } +match "/stories" => redirect {|p, req| "/posts/#{req.subdomain}" } + + +In all of these cases, if you don't provide the leading host (+http://www.example.com+), Rails will take those details from the current request. -There's one more way in which routing can do different things depending on differences in the incoming HTTP request: by issuing a response that corresponds to what the request specifies that it will accept. In Rails routing, you can control this with the special +:format+ parameter in the route. +h4. Routing to Rack Applications -For instance, consider the second of the default routes in the boilerplate +routes.rb+ file: +Instead of a String, like +"posts#index"+, which corresponds to the +index+ action in the +PostsController+, you can specify any Rack application as the endpoint for a matcher. -match ':controller(/:action(/:id(.:format)))' +match "/application.js" => Sprockets -This route matches requests such as +/photo/edit/1.xml+ or +/photo/show/2.rss+. Within the appropriate action code, you can issue different responses depending on the requested format: +As long as +Sprockets+ responds to +call+ and returns a [status, headers, body], the router won't know the difference between the Rack application and an action. + +NOTE: For the curious, +"posts#index"+ actually expands out to +PostsController.action(:index)+, which returns a valid Rack application. + +h4. Using +root+ + +You can specify what Rails should route +"/"+ to with the +root+ method: -respond_to do |format| - format.html # return the default template for HTML - format.xml { render :xml => @photo.to_xml } +root :to => 'pages#main' + + +You should put the +root+ route at the end of the file. + +h3. Customizing Resourceful Routes + +While the default routes and helpers generated by +resources :posts+ will usually serve you well, you may want to customize them in some way. Rails allows you to customize virtually any generic part of the resourceful helpers. + +h4. Specifying a Controller to Use + +The +:controller+ option lets you explicitly specify a controller to use for the resource. For example: + + +resources :photos, :controller => "images" + + +will recognize incoming URLs beginning with +/photo+ but route to the +Images+ controller: + +|_. Verb |_.URL |_.action | +|GET |/photos |index | +|GET |/photos/new |new | +|POST |/photos |create | +|GET |/photos/1 |show | +|GET |/photos/1/edit |edit | +|PUT |/photos/1 |update | +|DELETE |/photos/1 |destroy | + +NOTE: Use +photos_path+, +new_photos_path+, etc. to generate URLs for this resource. + +h4. Specifying Constraints + +You can use the +:constraints+ option to specify a required format on the implicit +id+. For example: + + +resources :photos, :constraints => {:id => /[A-Z][A-Z][0-9]+/} + + +This declaration constrains the +:id+ parameter to match the supplied regular expression. So, in this case, the router would no longer match +/photos/1+ to this route. Instead, +/photos/RR27+ would match. + +You can specify a single constraint to a apply to a number of routes by using the block form: + + +constraints(:id => /[A-Z][A-Z][0-9]+/) do + resources :photos + resources :accounts +end + + +NOTE: Of course, you can use the more advanced constraints available in non-resourceful routes in this context + +h4. Overriding the Named Helpers + +The +:as+ option lets you override the normal naming for the named route helpers. For example: + + +resources :photos, :as => "images" + + +will recognize incoming URLs beginning with +/photos+ and route the requests to +PhotosController+: + +|_.HTTP verb|_.URL |_.action |_.named helper | +|GET |/photos |index | images_path_ | +|GET |/photos/new |new | new_image_path | +|POST |/photos |create | images_path | +|GET |/photos/1 |show | image_path | +|GET |/photos/1/edit |edit | edit_image_path | +|PUT |/photos/1 |update | image_path | +|DELETE |/photos/1 |destroy | image_path | + +h4. Overriding the +new+ and +edit+ Segments + +The +:path_names+ option lets you override the automatically-generated "new" and "edit" segments in URLs: + + +resources :photos, :path_names => { :new => 'make', :edit => 'change' } + + +This would cause the routing to recognize URLs such as + +
+/photos/make
+/photos/1/change
+
+ +NOTE: The actual action names aren't changed by this option. The two URLs shown would still route to the new and edit actions. + +TIP: If you find yourself wanting to change this option uniformly for all of your routes, you can use a scope: + + +scope :path_names => { :new => "make" } do + # rest of your routes end -h4. Specifying the Format with an HTTP Header +h4. Overriding the Named Helper Prefix -If there is no +:format+ parameter in the route, Rails will automatically look at the HTTP Accept header to determine the desired format. +You can use the :name_prefix option to add a prefix to the named route helpers that Rails generates for a route. You can use this option to prevent collisions between routes using a path scope. -h4. Recognized MIME types + +scope "admin" do + resources :photos, :name_prefix => "admin" +end -By default, Rails recognizes +html+, +text+, +json+, +csv+, +xml+, +rss+, +atom+, and +yaml+ as acceptable response types. If you need types beyond this, you can register them in your environment: +resources :photos + + +This will provide route helpers such as +photographer_photos_path+. + +You could specify a name prefix to use for a group of routes in the scope: -Mime::Type.register "image/jpg", :jpg +scope "admin", :name_prefix => "admin" do + resources :photos, :accounts +end + +resources :photos, :accounts -h3. The Default Routes +NOTE: The +namespace+ scope will automatically add a +:name_prefix+ as well as +:module+ and +:path+ prefixes. + +h4. Restricting the Routes Created -When you create a new Rails application, +routes.rb+ is initialized with a default route: +By default, Rails creates routes for all seven of the default actions (index, show, new, create, edit, update, and destroy) for every RESTful route in your application. You can use the +:only+ and +:except+ options to fine-tune this behavior. The +:only+ option tells Rails to create only the specified routes: -match ':controller(/:action(/:id(.:format)))' +resources :photos, :only => [:index, :show] -These routes provide reasonable defaults for many URLs, if you're not using RESTful routing. +Now, a +GET+ request to +/photos+ would succeed, but a +POST+ request to +/photos+ (which would ordinarily be routed to the +create+ action) will fail. + +The +:except+ option specifies a route or list of routes that Rails should _not_ create: -NOTE: The default routes will make every action of every controller in your application accessible to GET requests. If you've designed your application to make consistent use of RESTful and named routes, you should comment out the default routes to prevent access to your controllers through the wrong verbs. If you've had the default routes enabled during development, though, you need to be sure that you haven't unwittingly depended on them somewhere in your application - otherwise you may find mysterious failures when you disable them. + +resources :photos, :except => :destroy + -h3. The Empty Route +In this case, Rails will create all of the normal routes except the route for +destroy+ (a +DELETE+ request to +/photos/:id+). -Don't confuse the default routes with the empty route. The empty route has one specific purpose: to route requests that come in to the root of the web site. For example, if your site is example.com, then requests to +http://example.com+ or +http://example.com/+ will be handled by the empty route. +TIP: If your application has many RESTful routes, using +:only+ and +:except+ to generate only the routes that you actually need can cut down on memory use and speed up the routing process. -h4. Using +root+ +h4. Translated Paths -The preferred way to set up the empty route is with the +root+ command: +Using +scope+, we can alter path names generated by resources: -root :to => 'pages#main' +scope(:path_names => { :new => "neu", :edit => "bearbeiten" }) do + resources :categories, :path => "kategorien" +end -The use of the +root+ method tells Rails that this route applies to requests for the root of the site. +Rails now creates routes to the +CategoriesControlleR+. -Because of the top-down processing of the file, the named route must be specified _before_ the call to +root+. +|_.HTTP verb|_.URL |_.action | +|GET |/kategorien |index | +|GET |/kategorien/neu |new | +|POST |/kategorien |create | +|GET |/kategorien/1 |show | +|GET |/kategorien/:id/bearbeiten |edit | +|PUT |/kategorien/1 |update | +|DELETE |/kategorien/1 |destroy | -h4. Connecting the Empty String +h4. Overriding the Singular Form -You can also specify an empty route by explicitly connecting the empty string: +If you want to customize the singular name of the route in the named helpers, you can use the +:singular+ option. -match '' => 'pages#main' +resources :teeth, :singular => "tooth" + + +TIP: If you want to define the singular form of a word for your entire application, you should add additional rules to the +Inflector+ instead. + +h4(#nested-name-prefix). Using +:name_prefix+ in Nested Resources + +The +:name_prefix+ option overrides the automatically-generated prefix for the parent resource in nested route helpers. For example, + + +resources :magazines do + resources :ads, :name_prefix => 'periodical' +end -TIP: If the empty route does not seem to be working in your application, make sure that you have deleted the file +public/index.html+ from your Rails tree. +This will create routing helpers such as +periodical_ads_url+ and +periodical_edit_ad_path+. h3. Inspecting and Testing Routes -Routing in your application should not be a "black box" that you never open. Rails offers built-in tools for both inspecting and testing routes. +Rails offers facilities for inspecting and testing your routes. h4. Seeing Existing Routes with +rake+ -If you want a complete list of all of the available routes in your application, run the +rake routes+ command. This will dump all of your routes to the console, in the same order that they appear in +routes.rb+. For each route, you'll see: +If you want a complete list of all of the available routes in your application, run +rake routes+ command. This will print all of your routes, in the same order that they appear in +routes.rb+. For each route, you'll see: * The route name (if any) * The HTTP verb used (if the route doesn't respond to all verbs) -* The URL pattern -* The routing parameters that will be generated by this URL +* The URL pattern to match +* The routing parameters for the route For example, here's a small section of the +rake routes+ output for a RESTful route: @@ -812,7 +768,7 @@ You can supply a +:method+ argument to specify the HTTP verb: assert_recognizes({ :controller => "photos", :action => "create" }, { :path => "photos", :method => :post }) -You can also use the RESTful helpers to test recognition of a RESTful route: +You can also use the resourceful helpers to test recognition of a RESTful route: assert_recognizes new_photo_url, { :path => "photos", :method => :post } -- cgit v1.2.3 From 5087b831a0fa2bc102c52473743b00e5319d857c Mon Sep 17 00:00:00 2001 From: wycats Date: Sat, 10 Apr 2010 04:54:25 -0400 Subject: Updated changelog --- railties/guides/source/routing.textile | 1 + 1 file changed, 1 insertion(+) (limited to 'railties/guides/source') diff --git a/railties/guides/source/routing.textile b/railties/guides/source/routing.textile index 92d38c4aa7..32b1e30502 100644 --- a/railties/guides/source/routing.textile +++ b/railties/guides/source/routing.textile @@ -786,6 +786,7 @@ h3. Changelog "Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/3 +* April 10, 2010: Updated guide to remove outdated and superfluous information, and to provide information about new features, by "Yehuda Katz":http://www.yehudakatz.com * April 2, 2010: Updated guide to match new Routing DSL in Rails 3, by "Rizwan Reza":http://www.rizwanreza.com/ * Febuary 1, 2010: Modifies the routing documentation to match new routing DSL in Rails 3, by Prem Sichanugrist * October 4, 2008: Added additional detail on specifying verbs for resource member/collection routes, by "Mike Gunderloy":credits.html#mgunderloy -- cgit v1.2.3