diff options
Diffstat (limited to 'railties/guides')
19 files changed, 267 insertions, 120 deletions
diff --git a/railties/guides/assets/javascripts/code_highlighter.js b/railties/guides/assets/javascripts/code_highlighter.js index ce983dad52..ce983dad52 100755..100644 --- a/railties/guides/assets/javascripts/code_highlighter.js +++ b/railties/guides/assets/javascripts/code_highlighter.js diff --git a/railties/guides/assets/javascripts/guides.js b/railties/guides/assets/javascripts/guides.js index c4e4d459ea..c4e4d459ea 100755..100644 --- a/railties/guides/assets/javascripts/guides.js +++ b/railties/guides/assets/javascripts/guides.js diff --git a/railties/guides/assets/stylesheets/print.css b/railties/guides/assets/stylesheets/print.css index 628da105d4..628da105d4 100755..100644 --- a/railties/guides/assets/stylesheets/print.css +++ b/railties/guides/assets/stylesheets/print.css diff --git a/railties/guides/assets/stylesheets/reset.css b/railties/guides/assets/stylesheets/reset.css index cb14fbcc55..cb14fbcc55 100755..100644 --- a/railties/guides/assets/stylesheets/reset.css +++ b/railties/guides/assets/stylesheets/reset.css diff --git a/railties/guides/assets/stylesheets/style.css b/railties/guides/assets/stylesheets/style.css index 89b2ab885a..89b2ab885a 100755..100644 --- a/railties/guides/assets/stylesheets/style.css +++ b/railties/guides/assets/stylesheets/style.css diff --git a/railties/guides/source/action_controller_overview.textile b/railties/guides/source/action_controller_overview.textile index 9d8426b5de..038ca903c1 100644 --- a/railties/guides/source/action_controller_overview.textile +++ b/railties/guides/source/action_controller_overview.textile @@ -338,6 +338,25 @@ end Note that while for session values you set the key to +nil+, to delete a cookie value you should use +cookies.delete(:key)+. +h3. Rendering xml and json data + +ActionController makes it extremely easy to render +xml+ or +json+ data. If you generate a controller using scaffold then your controller would look something like this. + +<ruby> +class UsersController < ApplicationController + def index + @users = User.all + respond_to do |format| + format.html # index.html.erb + format.xml { render :xml => @users} + end + end +end +</ruby> + +Notice that in the above case code is <tt>render :xml => @users</tt> and not <tt>render :xml => @users.to_xml</tt>. That is because if the input is not string then rails automatically invokes +to_xml+ . + + h3. Filters Filters are methods that are run before, after or "around" a controller action. diff --git a/railties/guides/source/active_record_basics.textile b/railties/guides/source/active_record_basics.textile index d81e461e63..e6ef2cdd20 100644 --- a/railties/guides/source/active_record_basics.textile +++ b/railties/guides/source/active_record_basics.textile @@ -32,16 +32,16 @@ Active Record gives us several mechanisms, the most important being the ability * Validate models before they get persisted to the database * Perform database operations in an object-oriented fashion. -h3. Convention over Configuration in ActiveRecord +h3. Convention over Configuration in Active Record -When writing applications using other programming languages or frameworks, it may be necessary to write a lot of configuration code. This is particularly true for ORM frameworks in general. However, if you follow the conventions adopted by Rails, you'll need to write very little configuration (in some case no configuration at all) when creating ActiveRecord models. The idea is that if you configure your applications in the very same way most of the times then this should be the default way. In this cases, explicit configuration would be needed only in those cases where you can't follow the conventions for any reason. +When writing applications using other programming languages or frameworks, it may be necessary to write a lot of configuration code. This is particularly true for ORM frameworks in general. However, if you follow the conventions adopted by Rails, you'll need to write very little configuration (in some case no configuration at all) when creating Active Record models. The idea is that if you configure your applications in the very same way most of the times then this should be the default way. In this cases, explicit configuration would be needed only in those cases where you can't follow the conventions for any reason. h4. Naming Conventions -By default, ActiveRecord uses some naming conventions to find out how the mapping between models and database tables should be created. Rails will pluralize your class names to find the respective database table. So, for a class +Book+, you should have a database table called *books*. The Rails pluralization mechanisms are very powerful, being capable to pluralize (and singularize) both regular and irregular words. When using class names composed of two or more words, the model class name should follow the Ruby conventions, using the camelCase form, while the table name must contain the words separated by underscores. Examples: +By default, Active Record uses some naming conventions to find out how the mapping between models and database tables should be created. Rails will pluralize your class names to find the respective database table. So, for a class +Book+, you should have a database table called *books*. The Rails pluralization mechanisms are very powerful, being capable to pluralize (and singularize) both regular and irregular words. When using class names composed of two or more words, the model class name should follow the Ruby conventions, using the camelCase form, while the table name must contain the words separated by underscores. Examples: -* Database Table - Plural with underscores separating words i.e. (book_clubs) -* Model Class - Singular with the first letter of each word capitalized i.e. (BookClub) +* Database Table - Plural with underscores separating words (e.g., book_clubs) +* Model Class - Singular with the first letter of each word capitalized (e.g., BookClub) |_.Model / Class |_.Table / Schema | |Post |posts| @@ -53,30 +53,32 @@ By default, ActiveRecord uses some naming conventions to find out how the mappin h4. Schema Conventions -ActiveRecord uses naming conventions for the columns in database tables, depending on the purpose of these columns. +Active Record uses naming conventions for the columns in database tables, depending on the purpose of these columns. -* *Foreign keys* - These fields should be named following the pattern table_id i.e. (item_id, order_id). These are the fields that ActiveRecord will look for when you create associations between your models. -* *Primary keys* - By default, ActiveRecord will use an integer column named "id" as the table's primary key. When using "Rails Migrations":migrations.html to create your tables, this column will be automatically created. +* *Foreign keys* - These fields should be named following the pattern table_id (e.g., item_id, order_id). These are the fields that Active Record will look for when you create associations between your models. +* *Primary keys* - By default, Active Record will use an integer column named "id" as the table's primary key. When using "Rails Migrations":migrations.html to create your tables, this column will be automatically created. -There are also some optional column names that will create additional features to ActiveRecord instances: +There are also some optional column names that will create additional features to Active Record instances: -* *created_at / created_on* - ActiveRecord will store the current date and time to this field when creating the record. -* *updated_at / updated_on* - ActiveRecord will store the current date and times to this field when updating the record. +* *created_at* - Automatically gets set to the current date and time when the record is first created. +* *created_on* - Automatically gets set to the current date when the record is first created. +* *updated_at* - Automatically gets set to the current date and time whenever the record is updated. +* *updated_on* - Automatically gets set to the current date whenever the record is updated. * *lock_version* - Adds "optimistic locking":http://api.rubyonrails.com/classes/ActiveRecord/Locking.html to a model. * *type* - Specifies that the model uses "Single Table Inheritance":http://api.rubyonrails.com/classes/ActiveRecord/Base.html * *(table_name)_count* - Used to cache the number of belonging objects on associations. For example, a +comments_count+ column in a +Post+ class that has many instances of +Comment+ will cache the number of existent comments for each post. -NOTE: While these column names are optional they are in fact reserved by ActiveRecord. Steer clear of reserved keywords unless you want the extra functionality. For example, "type" is a reserved keyword used to designate a table using Single Table Inheritance. If you are not using STI, try an analogous keyword like "context", that may still accurately describe the data you are modeling. +NOTE: While these column names are optional they are in fact reserved by Active Record. Steer clear of reserved keywords unless you want the extra functionality. For example, "type" is a reserved keyword used to designate a table using Single Table Inheritance. If you are not using STI, try an analogous keyword like "context", that may still accurately describe the data you are modeling. -h3. Creating ActiveRecord Models +h3. Creating Active Record Models -It's very easy to create ActiveRecord models. All you have to do is to subclass the ActiveRecord::Base class and you're good to go: +It's very easy to create Active Record models. All you have to do is to subclass the +ActiveRecord::Base+ class and you're good to go: <ruby> class Product < ActiveRecord::Base; end </ruby> -This will create a +Product+ model, mapped to a *products* table at the database. By doing this you'll also have the ability to map the columns of each row in that table with the attributes of the instances of your model. So, suppose that the *products* table was created using a SQL sentence like: +This will create a +Product+ model, mapped to a *products* table at the database. By doing this you'll also have the ability to map the columns of each row in that table with the attributes of the instances of your model. So, suppose that the *products* table was created using an SQL sentence like: <sql> CREATE TABLE products ( @@ -99,12 +101,15 @@ h3. Overriding the Naming Conventions What if you need to follow a different naming convention or need to use your Rails application with a legacy database? No problem, you can easily override the default conventions. You can use the +ActiveRecord::Base.set_table_name+ method to specify the table name that should be used: + <ruby> class Product < ActiveRecord::Base set_table_name "PRODUCT" end </ruby> + If you do so, you will have to define manually the class name that is hosting the fixtures (class_name.yml) using the +set_fixture_class+ method in your test definition: + <ruby> class FunnyJoke < ActiveSupport::TestCase set_fixture_class :funny_jokes => 'Joke' @@ -113,7 +118,8 @@ class FunnyJoke < ActiveSupport::TestCase end </ruby> -It's also possible to override the column that should be used as the table's primary key. Use the +ActiveRecord::Base.set_primary_key+ method for that: +It's also possible to override the column that should be used as the table's primary key using the +ActiveRecord::Base.set_primary_key+ method: + <ruby> class Product < ActiveRecord::Base set_primary_key "product_id" @@ -122,7 +128,7 @@ end h3. Reading and Writing Data -CRUD is an acronym for the four verbs we use to operate on data: Create, Read, Update, Delete. Active Record automatically creates methods to allow an application to read and manipulate data stored within its tables. +CRUD is an acronym for the four verbs we use to operate on data: *C*reate, *R*ead, *U*pdate and *D*elete. Active Record automatically creates methods to allow an application to read and manipulate data stored within its tables. h4. Create @@ -155,7 +161,7 @@ Finally, passing a block to either create or new will return a new User object: h4. Read -ActiveRecord provides a rich API for accessing data within a database. Below are a few examples of different data access methods provided by ActiveRecord. +Active Record provides a rich API for accessing data within a database. Below are a few examples of different data access methods provided by Active Record. <ruby> # return all records @@ -163,7 +169,7 @@ ActiveRecord provides a rich API for accessing data within a database. Below are </ruby> <ruby> - # return first record + # return the first record user = User.first </ruby> @@ -201,11 +207,11 @@ Likewise, once retrieved an Active Record object can be destroyed which removes h3. Validations -Active Record allows you to validate the state of a model before it gets written into the database. There are several methods that you can use to check your models and validate that an attribute value is not empty, is unique and not already in the database, follows a specific format and many more. You can learn more about validations in the "Active Record Validations and Callbacks guide":activerecord_validations_callbacks.html#validations-overview. +Active Record allows you to validate the state of a model before it gets written into the database. There are several methods that you can use to check your models and validate that an attribute value is not empty, is unique and not already in the database, follows a specific format and many more. You can learn more about validations in the "Active Record Validations and Callbacks guide":active_record_validations_callbacks.html#validations-overview. h3. Callbacks -Active Record callbacks allow you to attach code to certain events in the life-cycle of your models. This enables you to add behavior to your models by transparently executing code when those events occur, like when you create a new record, update it, destroy it and so on. You can learn more about callbacks in the "Active Record Validations and Callbacks guide":activerecord_validations_callbacks.html#callbacks-overview. +Active Record callbacks allow you to attach code to certain events in the life-cycle of your models. This enables you to add behavior to your models by transparently executing code when those events occur, like when you create a new record, update it, destroy it and so on. You can learn more about callbacks in the "Active Record Validations and Callbacks guide":active_record_validations_callbacks.html#callbacks-overview. h3. Migrations diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index 73f3ebafbe..f5e70aef41 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -51,7 +51,7 @@ Active Record will perform queries on the database for you and is compatible wit h3. Retrieving Objects from the Database -To retrieve objects from the database, Active Record provides several finder methods. These methods allows you to pass arguments into it to perform certain queries on your database without the need of writing raw SQL. +To retrieve objects from the database, Active Record provides several finder methods. Each finder method allows you to pass arguments into it to perform certain queries on your database without writing raw SQL. The methods are: * +where+ @@ -66,7 +66,7 @@ The methods are: * +readonly+ * +from+ -All of these methods return a Relation +All of the above methods return an instance of <tt>ActiveRecord::Relation</tt>. Primary operation of <tt>Model.find(options)</tt> can be summarized as: diff --git a/railties/guides/source/activerecord_validations_callbacks.textile b/railties/guides/source/active_record_validations_callbacks.textile index 1f9bc1279a..cfd4ae55cc 100644 --- a/railties/guides/source/activerecord_validations_callbacks.textile +++ b/railties/guides/source/active_record_validations_callbacks.textile @@ -16,7 +16,7 @@ endprologue. h3. The Object Lifecycle -During the normal operation of a Rails application objects may be created, updated, and destroyed. Active Record provides hooks into this <em>object lifecycle</em> so that you can control your application and its data. +During the normal operation of a Rails application, objects may be created, updated, and destroyed. Active Record provides hooks into this <em>object lifecycle</em> so that you can control your application and its data. Validations allow you to ensure that only valid data is stored in your database. Callbacks and observers allow you to trigger logic before or after an alteration of an object's state. @@ -71,7 +71,7 @@ The following methods trigger validations, and will save the object to the datab * +update_attributes+ * +update_attributes!+ -The bang versions (e.g. +save!+) raise an exception if the record is invalid. The non-bang versions don't: +save+ and +update_attributes+ return +false+, +create+ and +update+ just return the object/s. +The bang versions (e.g. +save!+) raise an exception if the record is invalid. The non-bang versions don't: +save+ and +update_attributes+ return +false+, +create+ and +update+ just return the objects. h4. Skipping Validations @@ -240,9 +240,9 @@ class Account < ActiveRecord::Base end </ruby> -The +validates_exclusion_of+ helper has an option +:in+ that receives the set of values that will not be accepted for the validated attributes. The +:in+ option has an alias called +:within+ that you can use for the same purpose, if you'd like to. This example uses the +:message+ option to show how you can include the attribute's value. +The +validates_exclusion_of+ helper has an option +:in+ that receives the set of values that will not be accepted for the validated attributes. The +:in+ option has an alias called +:within+ that you can use for the same purpose, if you'd like to. This example uses the +:message+ option to show how you can include the attribute's value. -The default error message for +validates_exclusion_of+ is "_is reserved_". +The default error message for +validates_exclusion_of+ is "_is reserved_". h4. +validates_format_of+ @@ -270,7 +270,7 @@ end The +validates_inclusion_of+ helper has an option +:in+ that receives the set of values that will be accepted. The +:in+ option has an alias called +:within+ that you can use for the same purpose, if you'd like to. The previous example uses the +:message+ option to show how you can include the attribute's value. -The default error message for +validates_inclusion_of+ is "_is not included in the list_". +The default error message for +validates_inclusion_of+ is "_is not included in the list_". h4. +validates_length_of+ @@ -343,7 +343,7 @@ Besides +:only_integer+, the +validates_numericality_of+ helper also accepts the * +:greater_than_or_equal_to+ - Specifies the value must be greater than or equal to the supplied value. The default error message for this option is "_must be greater than or equal to %{count}_". * +:equal_to+ - Specifies the value must be equal to the supplied value. The default error message for this option is "_must be equal to %{count}_". * +:less_than+ - Specifies the value must be less than the supplied value. The default error message for this option is "_must be less than %{count}_". -* +:less_than_or_equal_to+ - Specifies the value must be less than or equal the supplied value. The default error message for this option is "_must be less or equal to %{count}_". +* +:less_than_or_equal_to+ - Specifies the value must be less than or equal the supplied value. The default error message for this option is "_must be less than or equal to %{count}_". * +:odd+ - Specifies the value must be an odd number if set to true. The default error message for this option is "_must be odd_". * +:even+ - Specifies the value must be an even number if set to true. The default error message for this option is "_must be even_". @@ -374,7 +374,7 @@ The default error message for +validates_presence_of+ is "_can't be empty_". h4. +validates_uniqueness_of+ -This helper validates that the attribute's value is unique right before the object gets saved. It does not create a uniqueness constraint in the database, so it may happen that two different database connections create two records with the same value for a column that you intend to be unique. To avoid that, you must create an unique index in your database. +This helper validates that the attribute's value is unique right before the object gets saved. It does not create a uniqueness constraint in the database, so it may happen that two different database connections create two records with the same value for a column that you intend to be unique. To avoid that, you must create a unique index in your database. <ruby> class Account < ActiveRecord::Base @@ -423,14 +423,14 @@ class GoodnessValidator < ActiveRecord::Validator end </ruby> -The +validates_with+ helper takes a class, or a list of classes to use for validation. There is no default error message for +validates_with+. You must manually add errors to the record's errors collection in the validator class. +The +validates_with+ helper takes a class, or a list of classes to use for validation. There is no default error message for +validates_with+. You must manually add errors to the record's errors collection in the validator class. The validator class has two attributes by default: * +record+ - the record to be validated * +options+ - the extra options that were passed to +validates_with+ -Like all other validations, +validates_with+ takes the +:if+, +:unless+ and +:on+ options. If you pass any other options, it will send those options to the validator class as +options+: +Like all other validations, +validates_with+ takes the +:if+, +:unless+ and +:on+ options. If you pass any other options, it will send those options to the validator class as +options+: <ruby> class Person < ActiveRecord::Base @@ -494,7 +494,7 @@ As you've already seen, the +:message+ option lets you specify the message that h4. +:on+ -The +:on+ option lets you specify when the validation should happen. The default behavior for all the built-in validation helpers is to be ran on save (both when you're creating a new record and when you're updating it). If you want to change it, you can use +:on => :create+ to run the validation only when a new record is created or +:on => :update+ to run the validation only when a record is updated. +The +:on+ option lets you specify when the validation should happen. The default behavior for all the built-in validation helpers is to be run on save (both when you're creating a new record and when you're updating it). If you want to change it, you can use +:on => :create+ to run the validation only when a new record is created or +:on => :update+ to run the validation only when a record is updated. <ruby> class Person < ActiveRecord::Base @@ -573,7 +573,7 @@ class Invoice < ActiveRecord::Base end </ruby> -You can even create your own validation helpers and reuse them in several different models. For example, an application that manages surveys may find useful to express that a certain field corresponds to a set of choices: +You can even create your own validation helpers and reuse them in several different models. For example, an application that manages surveys may find it useful to express that a certain field corresponds to a set of choices: <ruby> ActiveRecord::Base.class_eval do @@ -599,7 +599,7 @@ The following is a list of the most commonly used methods. Please refer to the + h4(#working_with_validation_errors-errors). +errors+ -Returns an OrderedHash with all errors. Each key is the attribute name and value is an array of strings with all errors. +Returns an OrderedHash with all errors. Each key is the attribute name and the value is an array of strings with all errors. <ruby> class Person < ActiveRecord::Base @@ -619,7 +619,7 @@ person.errors # => [] h4(#working_with_validation_errors-errors-2). +errors[]+ -+errors[]+ is used when you want to check the error messages for a specific attribute. It returns an array of strings with all error messages for the given attribute, each string with one error message. If there are no errors related to the attribute returns an empty array. ++errors[]+ is used when you want to check the error messages for a specific attribute. It returns an array of strings with all error messages for the given attribute, each string with one error message. If there are no errors related to the attribute, it returns an empty array. <ruby> class Person < ActiveRecord::Base @@ -681,7 +681,7 @@ Another way to do this is using +[]=+ setter h4. +errors[:base]+ -You can add errors messages that are related to the object's state as a whole, instead of being related to a specific attribute. You can use this method when you want to say that the object is invalid, no matter the values of its attributes. Since +errors[:base]+ is an array, you can simply add a string to the array and uses it as the error message. +You can add error messages that are related to the object's state as a whole, instead of being related to a specific attribute. You can use this method when you want to say that the object is invalid, no matter the values of its attributes. Since +errors[:base]+ is an array, you can simply add a string to the array and uses it as the error message. <ruby> class Person < ActiveRecord::Base @@ -789,7 +789,7 @@ Both the +form.error_messages+ and the +error_messages_for+ helpers accept optio :header_tag => :h3 %> </erb> -Which results in the following content +Which results in the following content: !images/customized_error_messages.png(Customized error messages)! diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index 1c17609b0a..844b9428bd 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -24,7 +24,7 @@ h5. Cherry-picking a Definition The most lightweight way to get +blank?+ is to cherry-pick the file that defines it. -For every single method defined as a core extension this guide has a note that says where is such a method defined. In the case of +blank?+ the note reads: +For every single method defined as a core extension this guide has a note that says where such a method is defined. In the case of +blank?+ the note reads: NOTE: Defined in +active_support/core_ext/object/blank.rb+. @@ -124,7 +124,7 @@ NOTE: Defined in +active_support/core_ext/object/blank.rb+. h4. +duplicable?+ -A few fundamental objects in Ruby are singletons. For example, in the whole live of a program the integer 1 refers always to the same instance: +A few fundamental objects in Ruby are singletons. For example, in the whole life of a program the integer 1 refers always to the same instance: <ruby> 1.object_id # => 3 @@ -159,7 +159,7 @@ NOTE: Defined in +active_support/core_ext/object/duplicable.rb+. h4. +returning+ -The method +returning+ yields its argument to a block and returns it. You tipically use it with a mutable object that gets modified in the block: +The method +returning+ yields its argument to a block and returns it. You typically use it with a mutable object that gets modified in the block: <ruby> def html_options_for_form(url_for_options, options, *parameters_for_url) @@ -187,7 +187,7 @@ def log_info(sql, name, ms) end </ruby> -You can shorten that using +Object#try+. This method is a synonim for +Object#send+ except that it returns +nil+ if sent to +nil+. The previous example could then be rewritten as: +You can shorten that using +Object#try+. This method is a synonym for +Object#send+ except that it returns +nil+ if sent to +nil+. The previous example could then be rewritten as: <ruby> def log_info(sql, name, ms) @@ -209,8 +209,7 @@ String.singleton_class # => #<Class:String> String.new.singleton_class # => #<Class:#<String:0x17a1d1c>> </ruby> -WARNING: Fixnums and symbols have no singleton classes, +singleton_class+ -raises +TypeError+ on them. Moreover, the singleton classes of +nil+, +true+, and +false+, are +NilClass+, +TrueClass+, and +FalseClass+, respectively. +WARNING: Fixnums and symbols have no singleton classes, +singleton_class+ raises +TypeError+ on them. Moreover, the singleton classes of +nil+, +true+, and +false+, are +NilClass+, +TrueClass+, and +FalseClass+, respectively. NOTE: Defined in +active_support/core_ext/kernel/singleton_class.rb+. @@ -256,7 +255,7 @@ NOTE: Defined in +active_support/core_ext/object/acts_like.rb+. h4. +to_param+ -All objects in Rails respond to the method +to_param+, which is meant to return something that represents them as values in a query string, or as a URL fragments. +All objects in Rails respond to the method +to_param+, which is meant to return something that represents them as values in a query string, or as URL fragments. By default +to_param+ just calls +to_s+: @@ -294,7 +293,7 @@ we get: user_path(@user) # => "/users/357-john-smith" </ruby> -WARNING. Controllers need to be aware of any redifinition of +to_param+ because when a request like that comes in "357-john-smith" is the value of +params[:id]+. +WARNING. Controllers need to be aware of any redefinition of +to_param+ because when a request like that comes in "357-john-smith" is the value of +params[:id]+. NOTE: Defined in +active_support/core_ext/object/to_param.rb+. @@ -332,7 +331,7 @@ Arrays return the result of applying +to_query+ to each element with <tt>_key_[] # => "sample%5B%5D=3.4&sample%5B%5D=-45.6" </ruby> -Hashes also respond to +to_query+ but with a different signature. If no argument is passed a call generates a sorted series of key/value assigments calling +to_query(key)+ on its values. Then it joins the result with "&": +Hashes also respond to +to_query+ but with a different signature. If no argument is passed a call generates a sorted series of key/value assignments calling +to_query(key)+ on its values. Then it joins the result with "&": <ruby> {:c => 3, :b => 2, :a => 1}.to_query # => "a=1&b=2&c=3" @@ -656,9 +655,9 @@ h5. Internal Attributes When you are defining an attribute in a class that is meant to be subclassed name collisions are a risk. That's remarkably important for libraries. -Active Support defines the macros +attr_internal_reader+, +attr_internal_writer+, and +attr_internal_accessor+. They behave like their Ruby builtin +attr_*+ counterparts, except they name the unerlying instace variable in a way that makes collisions less likely. +Active Support defines the macros +attr_internal_reader+, +attr_internal_writer+, and +attr_internal_accessor+. They behave like their Ruby builtin +attr_*+ counterparts, except they name the underlying instance variable in a way that makes collisions less likely. -The macro +attr_internal+ is a synonim for +attr_internal_accessor+: +The macro +attr_internal+ is a synonym for +attr_internal_accessor+: <ruby> # library @@ -721,7 +720,7 @@ h4. Method Delegation The class method +delegate+ offers an easy way to forward methods. -For example, if +User+ has some details like the age factored out to +Profile+, it could be handy to still be able to acces such attribute directly, <tt>user.age</tt>, instead of having to explicit the chain <tt>user.profile.age</tt>. +For example, if +User+ has some details like the age factored out to +Profile+, it could be handy to still be able to access such attributes directly, <tt>user.age</tt>, instead of having to explicit the chain <tt>user.profile.age</tt>. That can be accomplished by hand: @@ -935,7 +934,7 @@ NOTE: Defined in +active_support/core_ext/module/synchronization.rb+. h4. Reachable -A named module is reachable if it is stored in its correspoding constant. It means you can reach the module object via the constant. +A named module is reachable if it is stored in its corresponding constant. It means you can reach the module object via the constant. That is what ordinarily happens, if a module is called "M", the +M+ constant exists and holds it: @@ -1016,7 +1015,7 @@ h3. Extensions to +Class+ h4. Class Attributes -The method +Class#class_attribute+ declares one or more inheritable class attributes that can be overriden at any level down the hierarchy: +The method +Class#class_attribute+ declares one or more inheritable class attributes that can be overridden at any level down the hierarchy: <ruby> class A @@ -1088,7 +1087,7 @@ NOTE: Defined in +active_support/core_ext/class/attribute_accessors.rb+. h4. Class Inheritable Attributes -Class variables are shared down the inheritance tree. Class instance variables are not shared, but they are not inherited either. The macros +class_inheritable_reader+, +class_inheritable_writer+, and +class_inheritable_accessor+ provide accesors for class-level data which is inherited but not shared with children: +Class variables are shared down the inheritance tree. Class instance variables are not shared, but they are not inherited either. The macros +class_inheritable_reader+, +class_inheritable_writer+, and +class_inheritable_accessor+ provide accessors for class-level data which is inherited but not shared with children: <ruby> module ActionController @@ -1204,7 +1203,7 @@ s.html_safe? # => true s # => "<script>...</script>" </ruby> -It is your responsability to ensure calling +html_safe+ on a particular string is fine. +It is your responsibility to ensure calling +html_safe+ on a particular string is fine. NOTE: For performance reasons safe strings are implemented in a way that cannot offer an in-place +html_safe!+ variant. @@ -1377,7 +1376,7 @@ The method +pluralize+ returns the plural of its receiver: "equipment".pluralize # => "equipment" </ruby> -As the previous example shows, Active Support knows some irregular plurals and uncountable nouns. Builtin rules can be extended in +config/initializers/inflections.rb+. That file is generated by the +rails+ command and has instructions in comments. +As the previous example shows, Active Support knows some irregular plurals and uncountable nouns. Built-in rules can be extended in +config/initializers/inflections.rb+. That file is generated by the +rails+ command and has instructions in comments. Active Record uses this method to compute the default table name that corresponds to a model: @@ -1697,6 +1696,90 @@ foreign_key = options[:foreign_key] || reflection.active_record.name.foreign_key NOTE: Defined in +active_support/core_ext/string/inflections.rb+. +h4. Conversions + +h5. +constantize+ + +The method +constantize+ expects the receiver to contain the name of a constant, and tries to get you the object stored in there, assuming it is defined: + +<ruby> +"ActiveRecord::Base".constantize # => ActiveRecord::Base +</ruby> + +The name is assumed to be top-level, no matter whether it starts with "::" or not. No lexical context is taken into account: + +<ruby> +C = 1 +module M + C = 2 + "C".constantize # => 1, same as "::C".constantize +end +</ruby> + +NOTE: Defined in +active_support/core_ext/string/conversions.rb+. + +h5. +ord+ + +Ruby 1.9 defines +ord+ to be the codepoint of the first character of the receiver. Active Support backports +ord+ for single-byte encondings like ASCII or ISO-8859-1 in Ruby 1.8: + +<ruby> +"a".ord # => 97 +"à".ord # => 224, in ISO-8859-1 +</ruby> + +In Ruby 1.8 +ord+ doesn't work in general in UTF8 strings, use the multibyte support in Active Support for that: + +<ruby> +"a".mb_chars.ord # => 97 +"à".mb_chars.ord # => 224, in UTF8 +</ruby> + +Note that the 224 is different in both examples. In ISO-8859-1 "à" is represented as a single byte, 224. Its single-character representattion in UTF8 has two bytes, namely 195 and 160, but its Unicode codepoint is 224. If we call +ord+ on the UTF8 string "à" the return value will be 195 in Ruby 1.8. That is not an error, because UTF8 is unsupported, the call itself would be bogus. + +INFO: +ord+ is equivalent to +getbyte(0)+. + +NOTE: Defined in +active_support/core_ext/string/conversions.rb+. + +h5. +getbyte+ + +Active Support backports +getbyte+ from Ruby 1.9: + +<ruby> +"foo".getbyte(0) # => 102, same as "foo".ord +"foo".getbyte(1) # => 111 +"foo".getbyte(9) # => nil +"foo".getbyte(-1) # => 111 +</ruby> + +INFO: +getbyte+ is equivalent to +[]+. + +NOTE: Defined in +active_support/core_ext/string/conversions.rb+. + +h5. +to_date+, +to_time+, +to_datetime+ + +The methods +to_date+, +to_time+, and +to_datetime+ are basically convenience wrappers around +Date._parse+: + +<ruby> +"2010-07-27".to_date # => Tue, 27 Jul 2010 +"2010-07-27 23:37:00".to_time # => Tue Jul 27 23:37:00 UTC 2010 +"2010-07-27 23:37:00".to_datetime # => Tue, 27 Jul 2010 23:37:00 +0000 +</ruby> + ++to_time+ receives an optional argument +:utc+ or +:local+, to indicate which time zone you want the time in: + +<ruby> +"2010-07-27 23:42:00".to_time(:utc) # => Tue Jul 27 23:42:00 UTC 2010 +"2010-07-27 23:42:00".to_time(:local) # => Tue Jul 27 23:42:00 +0200 2010 +</ruby> + +Default is +:utc+. + +Please refer to the documentation of +Date._parse+ for further details. + +INFO: The three of them return +nil+ for blank receivers. + +NOTE: Defined in +active_support/core_ext/string/conversions.rb+. + h3. Extensions to +Numeric+ h4. Bytes @@ -1760,7 +1843,7 @@ h3. Extensions to +Float+ h4. +round+ -The builtin method +Float#round+ rounds a float to the nearest integer. Active Support adds an optional parameter to let you specify a precision: +The built-in method +Float#round+ rounds a float to the nearest integer. Active Support adds an optional parameter to let you specify a precision: <ruby> Math::E.round(4) # => 2.7183 @@ -1925,7 +2008,7 @@ Similarly, +from+ returns the tail from the element at the passed index on: [].from(0) # => [] </ruby> -The methods +second+, +third+, +fourth+, and +fifth+ return the corresponding element (+first+ is builtin). Thanks to social wisdom and positive constructiveness all around, +forty_two+ is also available. +The methods +second+, +third+, +fourth+, and +fifth+ return the corresponding element (+first+ is built-in). Thanks to social wisdom and positive constructiveness all around, +forty_two+ is also available. NOTE: Defined in +active_support/core_ext/array/access.rb+. @@ -2120,7 +2203,7 @@ NOTE: Defined in +active_support/core_ext/array/conversions.rb+. h4. Wrapping -The class method +Array.wrap+ behaves like the function +Array()+ except that it does not try to call +to_a+ on its argument. That changes the behaviour for enumerables: +The class method +Array.wrap+ behaves like the function +Array()+ except that it does not try to call +to_a+ on its argument. That changes the behavior for enumerables: <ruby> Array.wrap(:foo => :bar) # => [{:foo => :bar}] @@ -2282,7 +2365,7 @@ NOTE: Defined in +active_support/core_ext/hash/conversions.rb+. h4. Merging -Ruby has a builtin method +Hash#merge+ that merges two hashes: +Ruby has a built-in method +Hash#merge+ that merges two hashes: <ruby> {:a => 1, :b => 1}.merge(:a => 0, :c => 2) @@ -2511,7 +2594,7 @@ NOTE: Defined in +active_support/core_ext/hash/keys.rb+. h4. Slicing -Ruby has builtin support for taking slices out of strings and arrays. Active Support extends slicing to hashes: +Ruby has built-in support for taking slices out of strings and arrays. Active Support extends slicing to hashes: <ruby> {:a => 1, :b => 2, :c => 3}.slice(:a, :c) @@ -2625,7 +2708,7 @@ Active Support extends this method so that the argument may be another range in (1...9).include?(3..9) # => false </ruby> -WARNING: The orginal +Range#include?+ is still the one aliased to +Range#===+. +WARNING: The original +Range#include?+ is still the one aliased to +Range#===+. NOTE: Defined in +active_support/core_ext/range/include_range.rb+. @@ -3080,7 +3163,7 @@ Active Support adds +missing_name?+ to +NameError+, which tests whether the exce The name may be given as a symbol or string. A symbol is tested against the bare constant name, a string is against the fully-qualified constant name. -TIP: A symbol can represent a fully-qualified constant name as in +:"ActiveRecord::Base"+, so the behaviour for symbols is defined for convenience, not because it has to be that way technically. +TIP: A symbol can represent a fully-qualified constant name as in +:"ActiveRecord::Base"+, so the behavior for symbols is defined for convenience, not because it has to be that way technically. For example, when an action of +PostsController+ is called Rails tries optimistically to use +PostsHelper+. It is OK that the helper module does not exist, so if an exception for that constant name is raised it should be silenced. But it could be the case that +posts_helper.rb+ raises a +NameError+ due to an actual unknown constant. That should be reraised. The method +missing_name?+ provides a way to distinguish both cases: diff --git a/railties/guides/source/form_helpers.textile b/railties/guides/source/form_helpers.textile index 515b3aad39..1f1b7d076e 100644 --- a/railties/guides/source/form_helpers.textile +++ b/railties/guides/source/form_helpers.textile @@ -205,7 +205,7 @@ Upon form submission the value entered by the user will be stored in +params[:pe WARNING: You must pass the name of an instance variable, i.e. +:person+ or +"person"+, not an actual instance of your model object. -Rails provides helpers for displaying the validation errors associated with a model object. These are covered in detail by the "Active Record Validations and Callbacks":./activerecord_validations_callbacks.html#displaying-validation-errors-in-the-view guide. +Rails provides helpers for displaying the validation errors associated with a model object. These are covered in detail by the "Active Record Validations and Callbacks":./active_record_validations_callbacks.html#displaying-validation-errors-in-the-view guide. h4. Binding a Form to an Object diff --git a/railties/guides/source/generators.textile b/railties/guides/source/generators.textile index 704a8793b2..c5b41673e1 100644 --- a/railties/guides/source/generators.textile +++ b/railties/guides/source/generators.textile @@ -1,21 +1,21 @@ -h2. Creating and customizing Rails Generators +h2. Creating and Customizing Rails Generators Rails generators are an essential tool if you plan to improve your workflow and in this guide you will learn how to create and customize already existing generators. In this guide you will: -* Learn how to see which generators are available in your application; -* Create a generator using templates; -* Learn how Rails searches for generators before invoking them; -* Customize your scaffold by creating new generators; -* Customize your scaffold by changing generators templates; -* Learn how to use fallbacks to avoid overwriting a huge set of generators; +* Learn how to see which generators are available in your application +* Create a generator using templates +* Learn how Rails searches for generators before invoking them +* Customize your scaffold by creating new generators +* Customize your scaffold by changing generator templates +* Learn how to use fallbacks to avoid overwriting a huge set of generators endprologue. NOTE: This guide is about Rails generators for versions >= 3.0. Rails generators from previous versions are not supported. -h3. First contact +h3. First Contact When you create an application using the +rails+ command, you are in fact using a Rails generator. After that, you can get a list of all available generators by just invoking +rails generate+: @@ -25,15 +25,15 @@ $ cd myapp $ rails generate </shell> -You will get a list of all generators that comes with Rails. If you need a detailed description, for instance about the helper generator, you can simply do: +You will get a list of all generators that comes with Rails. If you need a detailed description of the helper generator, for example, you can simply do: <shell> $ rails generate helper --help </shell> -h3. Creating your first generator +h3. Creating Your First Generator -Since Rails 3.0, generators are built on top of "Thor":http://github.com/wycats/thor. Thor has a powerful options parsing and a great API for manipulating files. For instance, let's build a generator that creates an initializer file named +initializer.rb+ inside +config/initializers+. +Since Rails 3.0, generators are built on top of "Thor":http://github.com/wycats/thor. Thor provides powerful options parsing and a great API for manipulating files. For instance, let's build a generator that creates an initializer file named +initializer.rb+ inside +config/initializers+. The first step is to create a file at +RAILS_APP/lib/generators/initializer_generator.rb+ with the following content: @@ -45,7 +45,7 @@ class InitializerGenerator < Rails::Generators::Base end </ruby> -Our new generator is quite simple: it inherits from +Rails::Generators::Base+ and have one method definition. Each public method in the generator is executed when a generator is invoked. Finally, we invoke the +create_file+ method that will create a file at the given destination with the given content. If you are familiar with Rails Application Templates API, you are at home with new generators API. +Our new generator is quite simple: it inherits from +Rails::Generators::Base+ and has one method definition. Each public method in the generator is executed when a generator is invoked. Finally, we invoke the +create_file+ method that will create a file at the given destination with the given content. If you are familiar with the Rails Application Templates API, you'll feel right at home with the new generators API. To invoke our new generator, we just need to do: @@ -59,7 +59,7 @@ Before we go on, let's see our brand new generator description: $ rails generate initializer --help </shell> -Rails usually is able to generate good descriptions if a generator is namespaced, as +ActiveRecord::Generators::ModelGenerator+, but not in this particular case. We can solve this problem in two ways. The first one is calling +desc+ inside our generator: +Rails is usually able to generate good descriptions if a generator is namespaced, as +ActiveRecord::Generators::ModelGenerator+, but not in this particular case. We can solve this problem in two ways. The first one is calling +desc+ inside our generator: <ruby> class InitializerGenerator < Rails::Generators::Base @@ -70,9 +70,9 @@ class InitializerGenerator < Rails::Generators::Base end </ruby> -Now we can see the new description by invoking +--help+ in the new generator. The second way to add a description is by creating a file named +USAGE+ in the same directory as our generator. We are going to do that in the next step. +Now we can see the new description by invoking +--help+ on the new generator. The second way to add a description is by creating a file named +USAGE+ in the same directory as our generator. We are going to do that in the next step. -h3. Creating generators with generators +h3. Creating Generators with Generators A faster way to create a generator is using the generator's generator: @@ -84,7 +84,7 @@ $ rails generate generator initializer create lib/generators/initializer/templates </shell> -And it will create a new generator as follow: +And it will create a new generator as follows: <ruby> class InitializerGenerator < Rails::Generators::NamedBase @@ -92,7 +92,7 @@ class InitializerGenerator < Rails::Generators::NamedBase end </ruby> -At first, we can notice that we are inheriting from +Rails::Generators::NamedBase+ instead of +Rails::Generators::Base+. This means that our generator expects as least one argument, which will be the name of the initializer. +First, notice that we are inheriting from +Rails::Generators::NamedBase+ instead of +Rails::Generators::Base+. This means that our generator expects as least one argument, which will be the name of the initializer. We can see that by invoking the description of this new generator (don't forget to delete the old generator file): @@ -127,13 +127,13 @@ And let's execute our generator: $ rails generate initializer foo </shell> -We can see that now a initializer named foo was created at +config/initializers/foo.rb+ with the contents of our template. That means that copy_file copied a file in our source root to the destination path we gave. The method +file_name+ is automatically created when we inherit from +Rails::Generators::NamedBase+. +We can see that now a initializer named foo was created at +config/initializers/foo.rb+ with the contents of our template. That means that +copy_file+ copied a file in our source root to the destination path we gave. The method +file_name+ is automatically created when we inherit from +Rails::Generators::NamedBase+. -h3. Generators lookup +h3. Generators Lookup -With our first generator created, we must discuss briefly generators lookup. The way Rails finds generators is exactly the same way Ruby find files, i.e. using +$LOAD_PATHS+. +Now that we've created our first generator, we need to briefly discuss generator lookup. The way Rails finds generators is exactly the same way Ruby find files, i.e. using +$LOAD_PATHS+. -For instance, when you say +rails g initializer foo+, rails knows you want to invoke the initializer generator and then search for the following generators in the $LOAD_PATHS: +For instance, when you say +rails generate initializer foo+, Rails knows you want to invoke the initializer generator and then search for the following generators in the $LOAD_PATHS: <shell> rails/generators/initializer/initializer_generator.rb @@ -144,7 +144,7 @@ generators/initializer_generator.rb If none of them is found, it raises an error message. -h3. Customizing your workflow +h3. Customizing Your Workflow Rails generators are flexible enough to let you customize your scaffold the way you want. In your +config/application.rb+ there is a section just for generators: @@ -156,7 +156,7 @@ config.generators do |g| end </ruby> -Before we customize our workflow, let's first see how our scaffold looks like: +Before we customize our workflow, let's first see what our scaffold looks like: <shell> $ rails generate scaffold User name:string @@ -186,7 +186,7 @@ $ rails generate scaffold User name:string create public/stylesheets/scaffold.css </shell> -Looking at this output, is easy to understand how generators work on Rails 3.0 and above. The scaffold generator actually doesn't generate anything, it just invokes others to do the work. This allows us to add/replace/remove any of those invocations. For instance, the scaffold generator invokes the scaffold_controller generator, which invokes erb, test_unit and helper generators. Since each generator has a single responsibility, they are easy to reuse, avoiding code duplication. +Looking at this output, it's easy to understand how generators work on Rails 3.0 and above. The scaffold generator doesn't actually generate anything, it just invokes others to do the work. This allows us to add/replace/remove any of those invocations. For instance, the scaffold generator invokes the scaffold_controller generator, which invokes erb, test_unit and helper generators. Since each generator has a single responsibility, they are easy to reuse, avoiding code duplication. Our first customization on the workflow will be to stop generating stylesheets and test fixtures on scaffold. We can achieve that by changing our application to the following: @@ -199,15 +199,15 @@ config.generators do |g| end </ruby> -If we generate another resource on scaffold, we can notice that neither stylesheets nor fixtures are created anymore. If you want to customize it further, for example to use +Datamapper+ and +Rspec+ instead of +ActiveRecord+ and +TestUnit+, is just a matter of adding their gems to your application and configuring your generators. +If we generate another resource on scaffold, we can notice that neither stylesheets nor fixtures are created anymore. If you want to customize it further, for example to use +Datamapper+ and +RSpec+ instead of +ActiveRecord+ and +TestUnit+, it's just a matter of adding their gems to your application and configuring your generators. -To show that, we are going to create a new helper generator that simply adds some instance variable readers. First, we create a generator: +To demonstrate this, we are going to create a new helper generator that simply adds some instance variable readers. First, we create a generator: <shell> $ rails generate generator my_helper </shell> -After that, we can delete both templates directory and the +source_root+ class method from our new generators, because we are not going to need them. So our new generator looks like the following: +After that, we can delete both the +templates+ directory and the +source_root+ class method from our new generators, because we are not going to need them. So our new generator looks like the following: <ruby> class MyHelperGenerator < Rails::Generators::NamedBase @@ -227,7 +227,7 @@ We can try out our new generator by creating a helper for users: $ rails generate my_helper users </shell> -And it will generate the following helper file in app/helpers: +And it will generate the following helper file in +app/helpers+: <ruby> module UsersHelper @@ -258,7 +258,7 @@ $ rails generate scaffold Post body:text We can notice on the output that our new helper was invoked instead of the Rails default. However one thing is missing, which is tests for our new generator and to do that, we are going to reuse old helpers test generators. -Since Rails 3.0, this is easy to do due to the hooks concept. Our new helper does not need to be focused in one specific test framework, it can simply provide a hook and a test framework just need to implement this hook in order to be compatible. +Since Rails 3.0, this is easy to do due to the hooks concept. Our new helper does not need to be focused in one specific test framework, it can simply provide a hook and a test framework just needs to implement this hook in order to be compatible. To do that, we can change your generator to the following: @@ -276,7 +276,7 @@ end end </ruby> -Now, when the helper generator is invoked and let's say test unit is configured as test framework, it will try to invoke both +MyHelper::Generators::TestUnitGenerator+ and +TestUnit::Generators::MyHelperGenerator+. Since none of those are defined, we can tell our generator to invoke +TestUnit::Generators::HelperGenerator+ instead, which is defined since it's a Rails generator. To do that, we just need to add: +Now, when the helper generator is invoked and TestUnit is configured as the test framework, it will try to invoke both +MyHelper::Generators::TestUnitGenerator+ and +TestUnit::Generators::MyHelperGenerator+. Since none of those are defined, we can tell our generator to invoke +TestUnit::Generators::HelperGenerator+ instead, which is defined since it's a Rails generator. To do that, we just need to add: <ruby> # Search for :helper instead of :my_helper @@ -285,11 +285,11 @@ Now, when the helper generator is invoked and let's say test unit is configured And now you can re-run scaffold for another resource and see it generating tests as well! -h3. Customizing your workflow by changing generators templates +h3. Customizing Your Workflow by Changing Generators Templates In the step above, we simply wanted to add a line to the generated helper, without adding any extra functionality. There is a simpler way to do that, and it's by replacing the templates of already existing generators. -In Rails 3.0 and above, generators does not look only in the source root for templates, they also search for templates in other paths. And one of them is inside +RAILS_APP/lib/templates+. Since we want to customize +Rails::Generators::HelperGenerator+, we can do that by simple making a template copy inside +RAILS_APP/lib/templates/rails/helper+ with the name +helper.rb+. So let's create such file with the following content: +In Rails 3.0 and above, generators don't just look in the source root for templates, they also search for templates in other paths. And one of them is inside +RAILS_APP/lib/templates+. Since we want to customize +Rails::Generators::HelperGenerator+, we can do that by simply making a template copy inside +RAILS_APP/lib/templates/rails/helper+ with the name +helper.rb+. So let's create that file with the following content: <erb> module <%= class_name %>Helper @@ -310,9 +310,9 @@ end If you generate another resource, you can see that we got exactly the same result! This is useful if you want to customize your scaffold templates and/or layout by just creating +edit.html.erb+, +index.html.erb+ and so on inside +RAILS_APP/lib/templates/erb/scaffold+. -h3. Adding generators fallbacks +h3. Adding Generators Fallbacks -One last feature about generators which is quite useful for plugin generators is fallbacks. For example, imagine that you want to add a feature on top of TestUnit test framework, like "shoulda":http://github.com/thoughtbot/shoulda does. Since TestUnit already implements all generators required by Rails and shoulda just want to overwrite part of it, there is no need for shoulda to reimplement some generators again, they can simply tell Rails to use a +TestUnit+ generator if none was found under +Shoulda+ namespace. +One last feature about generators which is quite useful for plugin generators is fallbacks. For example, imagine that you want to add a feature on top of TestUnit test framework, like "shoulda":http://github.com/thoughtbot/shoulda does. Since TestUnit already implements all generators required by Rails and shoulda just wants to overwrite part of it, there is no need for shoulda to reimplement some generators again, it can simply tell Rails to use a +TestUnit+ generator if none was found under the +Shoulda+ namespace. We can easily simulate this behavior by changing our +config/application.rb+ once again: @@ -324,11 +324,11 @@ config.generators do |g| g.stylesheets false # Add a fallback! - g.fallbacks[:should] = :test_unit + g.fallbacks[:shoulda] = :test_unit end </ruby> -Now, if create a Comment scaffold, you will see that shoulda generators are being invoked, and at the end, they are just falling back to test unit generators: +Now, if you create a Comment scaffold, you will see that the shoulda generators are being invoked, and at the end, they are just falling back to test unit generators: <shell> $ rails generate scaffold Comment body:text @@ -357,7 +357,7 @@ $ rails generate scaffold Comment body:text create test/unit/helpers/comments_helper_test.rb </shell> -Such tool allows your generators to have single responsibility, increasing the code reuse and reducing the amount of duplication. +Fallbacks allow your generators to have a single responsibility, increasing code reuse and reducing the amount of duplication. h3. Changelog diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index 7b4f1ca471..6abb3ed9f4 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -227,7 +227,7 @@ development: timeout: 5000 </yaml> -NOTE: In this guide we are using an SQLite3 database for data storage, this is because it is a zero configuration database that just works. Rails also supports MySQL and PostgreSQL "out of the box", and has plugins for many database systems, if you are using a database in a production environment, Rails most likely has an adapter for it. +NOTE: In this guide we are using an SQLite3 database for data storage, because it is a zero configuration database that just works. Rails also supports MySQL and PostgreSQL "out of the box", and has plugins for many database systems. If you are using a database in a production environment Rails most likely has an adapter for it. h5. Configuring a MySQL Database diff --git a/railties/guides/source/index.html.erb b/railties/guides/source/index.html.erb index 5a715cf9f7..be077fcd2f 100644 --- a/railties/guides/source/index.html.erb +++ b/railties/guides/source/index.html.erb @@ -47,7 +47,7 @@ Ruby on Rails Guides <p>This guide covers how you can use Active Record migrations to alter your database in a structured and organized manner.</p> <% end %> -<%= guide("Active Record Validations and Callbacks", 'activerecord_validations_callbacks.html') do %> +<%= guide("Active Record Validations and Callbacks", 'active_record_validations_callbacks.html') do %> <p>This guide covers how you can use Active Record validations and callbacks.</p> <% end %> diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile index bc3a2d0f0b..e458413b35 100644 --- a/railties/guides/source/initialization.textile +++ b/railties/guides/source/initialization.textile @@ -148,7 +148,7 @@ Here the only two gems we need are +rails+ and +sqlite3-ruby+, so it seems. This * mime-types-1.16.gem * polyglot-0.3.1.gem * rack-1.1.0.gem -* rack-mount-0.6.4.gem +* rack-mount-0.6.5.gem * rack-test-0.5.4.gem * rails-3.0.0.beta4.gem * railties-3.0.0.beta4.gem diff --git a/railties/guides/source/layout.html.erb b/railties/guides/source/layout.html.erb index f1727166ba..501d8fef6d 100644 --- a/railties/guides/source/layout.html.erb +++ b/railties/guides/source/layout.html.erb @@ -50,7 +50,7 @@ <dd><a href="getting_started.html">Getting Started with Rails</a></dd> <dt>Models</dt> <dd><a href="migrations.html">Rails Database Migrations</a></dd> - <dd><a href="activerecord_validations_callbacks.html">Active Record Validations and Callbacks</a></dd> + <dd><a href="active_record_validations_callbacks.html">Active Record Validations and Callbacks</a></dd> <dd><a href="association_basics.html">Active Record Associations</a></dd> <dd><a href="active_record_querying.html">Active Record Query Interface</a></dd> <dt>Views</dt> diff --git a/railties/guides/source/rails_application_templates.textile b/railties/guides/source/rails_application_templates.textile index 1af6f56957..1bf9cfec33 100644 --- a/railties/guides/source/rails_application_templates.textile +++ b/railties/guides/source/rails_application_templates.textile @@ -51,11 +51,11 @@ h4. gem(name, options = {}) Adds a +config.gem+ entry for the supplied gem to the generated application’s +config/environment.rb+. -For example, if your application depends on the gems +bj+ and +hpricot+ : +For example, if your application depends on the gems +bj+ and +nokogiri+ : <ruby> gem "bj" -gem "hpricot", :version => '0.6', :source => "http://code.whytheluckystiff.net" +gem "nokogiri" </ruby> Please note that this will NOT install the gems for you. So you may want to run the +rake gems:install+ task too : diff --git a/railties/guides/source/routing.textile b/railties/guides/source/routing.textile index 54af42a03f..9ff06856c3 100644 --- a/railties/guides/source/routing.textile +++ b/railties/guides/source/routing.textile @@ -32,7 +32,7 @@ the request is dispatched to the +patients+ controller's +show+ action with <tt> h4. Generating URLs from Code -You can also generate routes. If your application contains this code: +You can also generate URLs. If your application contains this code: <ruby> @patient = Patient.find(17) @@ -308,7 +308,7 @@ You are not limited to the seven routes that RESTful routing creates by default. h5. Adding Member Routes -To add a member route, just add +member+ block into resource block: +To add a member route, just add a +member+ block into the resource block: <ruby> resources :photos do @@ -318,9 +318,9 @@ resources :photos do end </ruby> -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. +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+ routes, you can also passing +:on+ to a route. +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 pass +:on+ to a route, eliminating the block: <ruby> resources :photos do @@ -340,9 +340,9 @@ resources :photos do end </ruby> -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. +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 pass +:on+ to a route. +Just as with member routes, you can pass +:on+ to a route: <ruby> resources :photos do @@ -384,7 +384,7 @@ An incoming URL of +/photos/show/1/2+ will be dispatched to the +show+ action of h4. Static Segments -You can specify static segments when creating a route. +You can specify static segments when creating a route: <ruby> match ':controller/:action/:id/with_user/:user_id' @@ -444,6 +444,21 @@ This route would match URLs such as +/photo/A12345+. You can more succinctly exp match 'photo/:id' => 'photos#show', :id => /[A-Z]\d{5}/ </ruby> ++:constraints+ takes regular expression. However note that regexp anchors can't be used within constraints. For example following route will not work: + +<ruby> +match '/:id' => 'posts#show', :constraints => {:id => /^\d/} +</ruby> + +However, note that you don't need to use anchors because all routes are anchored at the start. + +For example, the following routes would allow for +posts+ with +to_param+ values like +1-hello-world+ that always begin with a number and +users+ with +to_param+ values like +david+ that never begin with a number to share the root namespace: + +<ruby> +match '/:id' => 'posts#show', :constraints => { :id => /\d.+/ } +match '/:username' => 'users#show' +</ruby> + h4. Request-Based Constraints You can also constrain a route based on any method on the <a href="action_controller_overview.html#the-request-object">Request</a> object that returns a +String+. @@ -575,7 +590,7 @@ 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: +You can specify a single constraint to apply to a number of routes by using the block form: <ruby> constraints(:id => /[A-Z][A-Z][0-9]+/) do diff --git a/railties/guides/w3c_validator.rb b/railties/guides/w3c_validator.rb index b55645a7a9..4da48bf3fb 100644 --- a/railties/guides/w3c_validator.rb +++ b/railties/guides/w3c_validator.rb @@ -35,23 +35,27 @@ module RailsGuides def validate validator = MarkupValidator.new + STDOUT.sync = true + errors_on_guides = {} guides_to_validate.each do |f| - puts "Validating #{f}" results = validator.validate_file(f) - if !results.validity - puts "#{f} FAILED W3C validation with #{results.errors.size} error(s):" - results.errors.each do |error| - puts error.to_s - end + if results.validity + print "." + else + print "E" + errors_on_guides[f] = results.errors end end + + show_results(errors_on_guides) end private def guides_to_validate guides = Dir["./guides/output/*.html"] + guides.delete("./guides/output/layout.html") ENV.key?('ONLY') ? select_only(guides) : guides end @@ -61,6 +65,26 @@ module RailsGuides prefixes.any? {|p| guide.start_with?("./guides/output/#{p}")} end end + + def show_results(error_list) + if error_list.size == 0 + puts "\n\nAll checked guides validate OK!" + else + error_summary = error_detail = "" + + error_list.each_pair do |name, errors| + error_summary += "\n #{name}" + error_detail += "\n\n #{name} has #{errors.size} validation error(s):\n" + errors.each do |error| + error_detail += "\n "+error.to_s.gsub("\n", "") + end + end + + puts "\n\nThere are #{error_list.size} guides with validation errors:\n" + error_summary + puts "\nHere are the detailed errors for each guide:" + error_detail + end + end + end end |