diff --git a/actionpack/lib/abstract_controller/callbacks.rb b/actionpack/lib/abstract_controller/callbacks.rb index 14c984e41fb50f36972d416a66daf1c26149030f..7004e607a179ec6ec071b40316621238892e6a86 100644 --- a/actionpack/lib/abstract_controller/callbacks.rb +++ b/actionpack/lib/abstract_controller/callbacks.rb @@ -177,7 +177,7 @@ def #{filter}_filter(*names, &blk) def prepend_#{filter}_filter(*names, &blk) # def prepend_before_filter(*names, &blk) _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options| options[:if] = (Array.wrap(options[:if]) << "!halted") if #{filter == :after} # options[:if] = (Array.wrap(options[:if]) << "!halted") if false - set_callback(:process_action, :#{filter}, name, options.merge(:prepend => true)) # set_callback(:process_action, :#{filter}, name, options.merge(:prepend => true)) + set_callback(:process_action, :#{filter}, name, options.merge(:prepend => true)) # set_callback(:process_action, :before, name, options.merge(:prepend => true)) end # end end # end @@ -185,7 +185,7 @@ def prepend_#{filter}_filter(*names, &blk) # for details on the allowed parameters. def skip_#{filter}_filter(*names, &blk) # def skip_before_filter(*names, &blk) _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options| - skip_callback(:process_action, :#{filter}, name, options) # skip_callback(:process_action, :#{filter}, name, options) + skip_callback(:process_action, :#{filter}, name, options) # skip_callback(:process_action, :before, name, options) end # end end # end diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index b1acdd189a82aeb41bd2a81a0cc6b9d7dc149425..81d73c4ccc5bbba4d5bdec9cd4cfef3611145c3b 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -13,7 +13,7 @@ endprologue. WARNING. This Guide is based on Rails 3.0. Some of the code shown here will not work in other versions of Rails. -If you're used to using raw SQL to find database records then, generally, you will find that there are better ways to carry out the same operations in Rails. Active Record insulates you from the need to use SQL in most cases. +If you're used to using raw SQL to find database records, then you will generally find that there are better ways to carry out the same operations in Rails. Active Record insulates you from the need to use SQL in most cases. Code examples throughout this guide will refer to one or more of the following models: @@ -69,16 +69,16 @@ The methods are: All of the above methods return an instance of ActiveRecord::Relation. -Primary operation of Model.find(options) can be summarized as: +The primary operation of Model.find(options) can be summarized as: * Convert the supplied options to an equivalent SQL query. * Fire the SQL query and retrieve the corresponding results from the database. * Instantiate the equivalent Ruby object of the appropriate model for every resulting row. -* Run +after_find+ callbacks if any. +* Run +after_find+ callbacks, if any. h4. Retrieving a Single Object -Active Record lets you retrieve a single object using five different ways. +Active Record provides five different ways of retrieving a single object. h5. Using a Primary Key @@ -87,10 +87,10 @@ Using Model.find(primary_key), you can retrieve the object correspondin # Find the client with primary key (id) 10. client = Client.find(10) -=> # "Ryan"> +# => # -SQL equivalent of the above is: +The SQL equivalent of the above is: SELECT * FROM clients WHERE (clients.id = 10) @@ -100,14 +100,14 @@ SELECT * FROM clients WHERE (clients.id = 10) h5. +first+ -Model.first finds the first record matched by the supplied options. For example: +Model.first finds the first record matched by the supplied options, if any. For example: client = Client.first -=> # +# => # -SQL equivalent of the above is: +The SQL equivalent of the above is: SELECT * FROM clients LIMIT 1 @@ -121,10 +121,10 @@ h5. +last+ client = Client.last -=> # +# => # -SQL equivalent of the above is: +The SQL equivalent of the above is: SELECT * FROM clients ORDER BY clients.id DESC LIMIT 1 @@ -138,10 +138,10 @@ h5(#first_1). +first!+ client = Client.first! -=> # +# => # -SQL equivalent of the above is: +The SQL equivalent of the above is: SELECT * FROM clients LIMIT 1 @@ -155,10 +155,10 @@ h5(#last_1). +last!+ client = Client.last! -=> # +# => # -SQL equivalent of the above is: +The SQL equivalent of the above is: SELECT * FROM clients ORDER BY clients.id DESC LIMIT 1 @@ -174,11 +174,11 @@ h5. Using Multiple Primary Keys # Find the clients with primary keys 1 and 10. -client = Client.find(1, 10) # Or even Client.find([1, 10]) -=> [# "Lifo">, # "Ryan">] +client = Client.find([1, 10]) # Or even Client.find(1, 10) +# => [#, #] -SQL equivalent of the above is: +The SQL equivalent of the above is: SELECT * FROM clients WHERE (clients.id IN (1,10)) @@ -190,7 +190,7 @@ h4. Retrieving Multiple Objects in Batches Sometimes you need to iterate over a large set of records. For example to send a newsletter to all users, to export some data, etc. -The following may seem very straight forward at first: +The following may seem very straightforward, at first: # Very inefficient when users table has thousands of rows. @@ -199,9 +199,9 @@ User.all.each do |user| end -But if the total number of rows in the table is very large, the above approach may vary from being under performant to just plain impossible. +But if the total number of rows in the table is very large, the above approach may vary from being underperforming to being plain impossible. -This is because +User.all.each+ makes Active Record fetch _the entire table_, build a model object per row, and keep the entire array in the memory. Sometimes that is just too many objects and demands too much memory. +This is because +User.all.each+ makes Active Record fetch _the entire table_, build a model object per row, and keep the entire array of model objects in memory. Sometimes that is just too many objects and requires too much memory. h5. +find_each+ @@ -215,9 +215,9 @@ end *Configuring the batch size* -Behind the scenes +find_each+ fetches rows in batches of +1000+ and yields them one by one. The size of the underlying batches is configurable via the +:batch_size+ option. +Behind the scenes, +find_each+ fetches rows in batches of 1000 and yields them one by one. The size of the underlying batches is configurable via the +:batch_size+ option. -To fetch +User+ records in batch size of +5000+: +To fetch +User+ records in batches of 5000, we can use: User.find_each(:batch_size => 5000) do |user| @@ -227,9 +227,9 @@ end *Starting batch find from a specific primary key* -Records are fetched in ascending order on the primary key, which must be an integer. The +:start+ option allows you to configure the first ID of the sequence if the lowest is not the one you need. This may be useful for example to be able to resume an interrupted batch process if it saves the last processed ID as a checkpoint. +Records are fetched in ascending order of the primary key, which must be an integer. The +:start+ option allows you to configure the first ID of the sequence whenever the lowest ID is not the one you need. This may be useful, for example, to be able to resume an interrupted batch process, provided it saves the last processed ID as a checkpoint. -To send newsletters only to users with the primary key starting from +2000+: +To send newsletters only to users with the primary key starting from 2000, we can use: User.find_each(:batch_size => 5000, :start => 2000) do |user| @@ -252,7 +252,9 @@ Invoice.find_in_batches(:include => :invoice_lines) do |invoices| end -The above will yield the supplied block with +1000+ invoices every time. +The above will each time yield to the supplied block an array of 1000 invoices (or the remaining invoices, if less than 1000). + +NOTE: The +:include+ option allows you to name associations that should be loaded alongside with the models. h3. Conditions @@ -911,14 +913,14 @@ end To call this +published+ scope we can call it on either the class: -Post.published => [published posts] +Post.published # => [published posts] Or on an association consisting of +Post+ objects: category = Category.first -category.posts.published => [published posts belonging to this category] +category.posts.published # => [published posts belonging to this category] h4. Working with times @@ -1030,7 +1032,7 @@ Suppose you want to find a client named 'Andy', and if there's none, create one Client.where(:first_name => 'Andy').first_or_create(:locked => false) -# => +# => # The SQL generated by this method looks like this: diff --git a/railties/guides/source/active_record_validations_callbacks.textile b/railties/guides/source/active_record_validations_callbacks.textile index 2a1e9bfc0cb8f0026ece5511e4626d20c99e9a81..781b9001b67f375bdfe825c488153c868e0d003c 100644 --- a/railties/guides/source/active_record_validations_callbacks.textile +++ b/railties/guides/source/active_record_validations_callbacks.textile @@ -46,7 +46,7 @@ end We can see how it works by looking at some +rails console+ output: - + >> p = Person.new(:name => "John Doe") => # >> p.new_record? @@ -55,7 +55,7 @@ We can see how it works by looking at some +rails console+ output: => true >> p.new_record? => false - + Creating and saving a new record will send an SQL +INSERT+ operation to the database. Updating an existing record will send an SQL +UPDATE+ operation instead. Validations are typically run before these commands are sent to the database. If any validations fail, the object will be marked as invalid and Active Record will not perform the +INSERT+ or +UPDATE+ operation. This helps to avoid storing an invalid object in the database. You can choose to have specific validations run when an object is created, saved, or updated. diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index 5aee0015457becfe42e8aa456af46ebea9e5557d..addf5f78be2665cac9f6f4c4140808b6cb1c3b43 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -719,9 +719,9 @@ X.local_constants # => ["X2", "X1", "Y"], assumes Ruby 1.8 X::Y.local_constants # => ["X1", "Y1"], assumes Ruby 1.8 -The names are returned as strings in Ruby 1.8, and as symbols in Ruby 1.9. The method +local_constant_names+ returns always strings. +The names are returned as strings in Ruby 1.8, and as symbols in Ruby 1.9. The method +local_constant_names+ always returns strings. -WARNING: This method is exact if running under Ruby 1.9. In previous versions it may miss some constants if their value in some ancestor stores the exact same object than in the receiver. +WARNING: This method returns precise results in Ruby 1.9. In older versions of Ruby, however, it may miss some constants in case the same constant exists in the receiver module as well as in any of its ancestors and both constants point to the same object (objects are compared using +Object#object_id+). NOTE: Defined in +active_support/core_ext/module/introspection.rb+. diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index f2eade6bc68ca558970e791740456c7723254f11..ef01cd32ac5a661c514b4ca9b2d63cea3c4525db 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -120,7 +120,7 @@ All subdirectories that exist within these three locations are added to the sear You can add additional (fully qualified) paths to the pipeline in +config/application.rb+. For example: -config.assets.paths << "#{Rails.root}/app/assets/flash" +config.assets.paths << Rails.root.join("app", "assets", "flash") h4. Coding Links to Assets @@ -232,7 +232,7 @@ There's also a default +app/assets/stylesheets/application.css+ file which conta The directives that work in the JavaScript files also work in stylesheets, obviously including stylesheets rather than JavaScript files. The +require_tree+ directive here works the same way as the JavaScript one, requiring all stylesheets from the current directory. -In this example +require_self+ is used. This puts the CSS contained within the file (if any) at the top of any other CSS in this file unless +require_self+ is specified after another +require+ directive. +In this example +require_self+ is used. This puts the CSS contained within the file (if any) at the precise location of the +require_self+ call. If +require_self+ is called more than once, only the last call is respected. You can have as many manifest files as you need. For example the +admin.css+ and +admin.js+ manifest could contain the JS and CSS files that are used for the admin section of an application. diff --git a/railties/guides/source/caching_with_rails.textile b/railties/guides/source/caching_with_rails.textile index 19378d63cec75427f0d33950a2066ae242e800c1..4273d0dd64ff16eca5d8884d534337cae880cf9c 100644 --- a/railties/guides/source/caching_with_rails.textile +++ b/railties/guides/source/caching_with_rails.textile @@ -188,7 +188,7 @@ end You may notice that the actual product gets passed to the sweeper, so if we were caching the edit action for each product, we could add an expire method which specifies the page we want to expire: - expire_action(:controller => 'products', :action => 'edit', :id => product) +expire_action(:controller => 'products', :action => 'edit', :id => product.id) Then we add it to our controller to tell it to call the sweeper when certain actions are called. So, if we wanted to expire the cached content for the list and edit actions when the create action was called, we could do the following: diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile index ce1d759d5be6babf8e4cdfa80932118383e4ac94..baf944cf8d85af75c3b271fbe6b6bb9068f1ce29 100644 --- a/railties/guides/source/configuring.textile +++ b/railties/guides/source/configuring.textile @@ -461,12 +461,31 @@ Rails has 5 initialization events which can be hooked into (listed in the order * +before_initialize+: This is run directly before the initialization process of the application occurs with the +:bootstrap_hook+ initializer near the beginning of the Rails initialization process. -* +to_prepare+: Run after the initializers are ran for all Railties (including the application itself), but before eager loading and the middleware stack is built. +* +to_prepare+: Run after the initializers are ran for all Railties (including the application itself), but before eager loading and the middleware stack is built. More importantly, will run upon every request in +development+, but only once (during boot-up) in +production+ and +test+. * +before_eager_load+: This is run directly before eager loading occurs, which is the default behaviour for the _production_ environment and not for the +development+ environment. * +after_initialize+: Run directly after the initialization of the application, but before the application initializers are run. +To define an event for these hooks, use the block syntax within a +Rails::Aplication+, +Rails::Railtie+ or +Rails::Engine+ subclass: + + +module YourApp + class Application < Rails::Application + config.before_initialize do + # initialization code goes here + end + end +end + + +Alternatively, you can also do it through the +config+ method on the +Rails.application+ object: + + +Rails.application.config.before_initialize do + # initialization code goes here +end + WARNING: Some parts of your application, notably observers and routing, are not yet set up at the point where the +after_initialize+ block is called. diff --git a/railties/guides/source/engines.textile b/railties/guides/source/engines.textile index dc87ac4095fb88820260be34cb92a9fd703a3cf4..ddd2e50a6cbd47d4fec4917e85a824b1e1fa1c5e 100644 --- a/railties/guides/source/engines.textile +++ b/railties/guides/source/engines.textile @@ -12,13 +12,50 @@ endprologue. h3. What are engines? -Engines can be considered miniature applications that provide functionality to their host applications. A Rails application is actually just a "supercharged" engine, with the `Rails::Application` class inheriting from `Rails::Engine`. Therefore, engines and applications share common functionality but are at the same time two separate beasts. +Engines can be considered miniature applications that provide functionality to their host applications. A Rails application is actually just a "supercharged" engine, with the +Rails::Application+ class inheriting from +Rails::Engine+. Therefore, engines and applications share common functionality but are at the same time two separate beasts. Engines and applications also share a common structure, as you'll see later in this guide. + +Engines are also closely related to plugins where the two share a common +lib+ directory structure and are both generated using the +rails plugin new+ generator. + +The engine that will be generated for this guide will be called "blorgh". The engine will provide blogging functionality to its host applications, allowing for new posts and comments to be created. For now, you will be working solely within the engine itself and in later sections you'll see how to hook it into an application. + +Engines can also be isolated from their host applications. This means that an application is able to have a path provided by a routing helper such as +posts_path+ and use an engine also that provides a path also called +posts_path+, and the two would not clash. Along with this, controllers, models and table names are also namespaced. You'll see how to do this later in this guide. + +To see demonstrations of other engines, check out "Devise":https://github.com/plataformatec/devise, an engine that provides authentication for its parent applications, or "Forem":https://github.com/radar/forem, an engine that provides forum functionality. h3. Generating an engine -TODO: The engine that will be generated for this guide will be called "blorgh". It's a blogging engine that provides posts and comments and that's it. +To generate an engine with Rails 3.1, you will need to run the plugin generator and pass it the +--mountable+ option. To generate the beginnings of the "blorgh" engine you will need to run this command in a terminal: + + +$ rails plugin new blorgh --mountable + + +The +--mountable+ option tells the plugin generator that you want to create an engine (which is a mountable plugin, hence the option name), creating the basic directory structure of an engine by providing things such as the foundations of an +app+ folder, as well a +config/routes.rb+ file. This generator also provides a file at +lib/blorgh/engine.rb+ which is identical in function to an application's +config/application.rb+ file. + +Inside the +app+ directory there lives the standard +assets+, +controllers+, +helpers+, +mailers+, +models+ and +views+ directories that you should be familiar with from an application. + +At the root of the engine's directory, lives a +blorgh.gemspec+ file. When you include the engine into the application later on, you will do so with this line in a Rails application's +Gemfile+: + + + gem 'blorgh', :path => "vendor/engines/blorgh" + + +By specifying it as a gem within the +Gemfile+, Bundler will load it as such, parsing this +blorgh.gemspec+ file and requiring a file within the +lib+ directory called +lib/blorgh.rb+. This file requires the +blorgh/engine.rb+ file (located at +lib/blorgh/engine.rb+) and defines a base module called +Blorgh+. + + +require "blorgh/engine" + +module Blorgh +end + + +Within +lib/blorgh/engine.rb+ is the base class for the engine: + + + TODO: lib/blorgh/engine.rb + -TODO: Describe here the process of generating an engine and what an engine comes with. +Within the +app/controllers+ directory there is a +blorgh+ directory and inside that a file called +application_controller.rb+. This file will provide any common functionality for the controllers of the engine. The +blorgh+ directory is where the other controllers for the engine will go. By placing them within this namespaced directory, you prevent them from possibly clashing with identically-named controllers within other engines or even within the application. h3. Providing engine functionality diff --git a/railties/guides/source/migrations.textile b/railties/guides/source/migrations.textile index 9c92d567d312c1cddc05dbf12229197a04a5eca6..23e36b39f9e81b34db9c75ed9db5beef9586ac0b 100644 --- a/railties/guides/source/migrations.textile +++ b/railties/guides/source/migrations.textile @@ -628,7 +628,7 @@ There is no need (and it is error prone) to deploy a new instance of an app by r For example, this is how the test database is created: the current development database is dumped (either to +db/schema.rb+ or +db/development.sql+) and then loaded into the test database. -Schema files are also useful if you want a quick look at what attributes an Active Record object has. This information is not in the model's code and is frequently spread across several migrations but is all summed up in the schema file. The "annotate_models":http://agilewebdevelopment.com/plugins/annotate_models plugin, which automatically adds (and updates) comments at the top of each model summarizing the schema, may also be of interest. +Schema files are also useful if you want a quick look at what attributes an Active Record object has. This information is not in the model's code and is frequently spread across several migrations, but is summed up in the schema file. The "annotate_models":https://github.com/ctran/annotate_models gem automatically adds and updates comments at the top of each model summarizing the schema if you desire that functionality. h4. Types of Schema Dumps diff --git a/railties/guides/source/routing.textile b/railties/guides/source/routing.textile index 0a9f1e83888eff49268dfa5df5653bed02cda4f2..f281009fee13eccd5220956979c46a819cdf303b 100644 --- a/railties/guides/source/routing.textile +++ b/railties/guides/source/routing.textile @@ -596,6 +596,8 @@ match "/stories/:name" => redirect {|params| "/posts/#{params[:name].pluralize}" match "/stories" => redirect {|p, req| "/posts/#{req.subdomain}" } +Please note that this redirection is a 301 "Moved Permanently" redirect. Keep in mind that some web browsers or proxy servers will cache this type of redirect, making the old page inaccessible. + 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. h4. Routing to Rack Applications