aboutsummaryrefslogtreecommitdiffstats
path: root/guides
diff options
context:
space:
mode:
Diffstat (limited to 'guides')
-rw-r--r--guides/source/4_0_release_notes.md8
-rw-r--r--guides/source/active_record_querying.md56
-rw-r--r--guides/source/active_support_core_extensions.md8
-rw-r--r--guides/source/ajax_on_rails.md316
-rw-r--r--guides/source/configuring.md16
-rw-r--r--guides/source/initialization.md2
-rw-r--r--guides/source/migrations.md21
-rw-r--r--guides/source/upgrading_ruby_on_rails.md2
-rw-r--r--guides/source/working_with_javascript.md394
9 files changed, 469 insertions, 354 deletions
diff --git a/guides/source/4_0_release_notes.md b/guides/source/4_0_release_notes.md
index 54fe49252f..6b3680aa2d 100644
--- a/guides/source/4_0_release_notes.md
+++ b/guides/source/4_0_release_notes.md
@@ -95,9 +95,9 @@ Railties
* Load all environments available in `config.paths["config/environments"]`.
-* Add `config.queue_consumer` to allow the default consumer to be configurable.
+* Add `config.queue_consumer` to change the job queue consumer from the default `ActiveSupport::ThreadedQueueConsumer`.
-* Add `Rails.queue` as an interface with a default implementation that consumes jobs in a separate thread.
+* Add `Rails.queue` for processing jobs in the background.
* Remove `Rack::SSL` in favour of `ActionDispatch::SSL`.
@@ -810,6 +810,10 @@ Active Support
* Add `Time#prev_quarter` and `Time#next_quarter` short-hands for `months_ago(3)` and `months_since(3)`.
+* Add `Time#last_week`, `Time#last_month`, `Time#last_year` as aliases for `Time#prev_week`, `Time#prev_month`, and `Time#prev_year`.
+
+* Add `Date#last_week`, `Date#last_month`, `Date#last_year` as aliases for `Date#prev_week`, `Date#prev_month`, and `Date#prev_year`.
+
* Remove obsolete and unused `require_association` method from dependencies.
* Add `:instance_accessor` option for `config_accessor`.
diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md
index 66e6390f67..76548a3397 100644
--- a/guides/source/active_record_querying.md
+++ b/guides/source/active_record_querying.md
@@ -1225,17 +1225,17 @@ WARNING: Up to and including Rails 3.1, when the number of arguments passed to a
Find or build a new object
--------------------------
-It's common that you need to find a record or create it if it doesn't exist. You can do that with the `first_or_create` and `first_or_create!` methods.
+It's common that you need to find a record or create it if it doesn't exist. You can do that with the `find_or_create_by` and `find_or_create_by!` methods.
-### `first_or_create`
+### `find_or_create_by`
-The `first_or_create` method checks whether `first` returns `nil` or not. If it does return `nil`, then `create` is called. This is very powerful when coupled with the `where` method. Let's see an example.
+The `find_or_create_by` method checks whether a record with the attributes exists. If it doesn't, then `create` is called. Let's see an example.
-Suppose you want to find a client named 'Andy', and if there's none, create one and additionally set his `locked` attribute to false. You can do so by running:
+Suppose you want to find a client named 'Andy', and if there's none, create one. You can do so by running:
```ruby
-Client.where(:first_name => 'Andy').first_or_create(:locked => false)
-# => #<Client id: 1, first_name: "Andy", orders_count: 0, locked: false, created_at: "2011-08-30 06:09:27", updated_at: "2011-08-30 06:09:27">
+Client.find_or_create_by(first_name: 'Andy')
+# => #<Client id: 1, first_name: "Andy", orders_count: 0, locked: true, created_at: "2011-08-30 06:09:27", updated_at: "2011-08-30 06:09:27">
```
The SQL generated by this method looks like this:
@@ -1243,27 +1243,39 @@ The SQL generated by this method looks like this:
```sql
SELECT * FROM clients WHERE (clients.first_name = 'Andy') LIMIT 1
BEGIN
-INSERT INTO clients (created_at, first_name, locked, orders_count, updated_at) VALUES ('2011-08-30 05:22:57', 'Andy', 0, NULL, '2011-08-30 05:22:57')
+INSERT INTO clients (created_at, first_name, locked, orders_count, updated_at) VALUES ('2011-08-30 05:22:57', 'Andy', 1, NULL, '2011-08-30 05:22:57')
COMMIT
```
-`first_or_create` returns either the record that already exists or the new record. In our case, we didn't already have a client named Andy so the record is created and returned.
+`find_or_create_by` returns either the record that already exists or the new record. In our case, we didn't already have a client named Andy so the record is created and returned.
The new record might not be saved to the database; that depends on whether validations passed or not (just like `create`).
-It's also worth noting that `first_or_create` takes into account the arguments of the `where` method. In the example above we didn't explicitly pass a `:first_name => 'Andy'` argument to `first_or_create`. However, that was used when creating the new record because it was already passed before to the `where` method.
+Suppose we want to set the 'locked' attribute to true if we're
+creating a new record, but we don't want to include it in the query. So
+we want to find the client named "Andy", or if that client doesn't
+exist, create a client named "Andy" which is not locked.
-You can do the same with the `find_or_create_by` method:
+We can achive this in two ways. The first is to use `create_with`:
```ruby
-Client.find_or_create_by_first_name(:first_name => "Andy", :locked => false)
+Client.create_with(locked: false).find_or_create_by(first_name: 'Andy')
```
-This method still works, but it's encouraged to use `first_or_create` because it's more explicit on which arguments are used to _find_ the record and which are used to _create_, resulting in less confusion overall.
+The second way is using a block:
-### `first_or_create!`
+```ruby
+Client.find_or_create_by(first_name: 'Andy') do |c|
+ c.locked = false
+end
+```
-You can also use `first_or_create!` to raise an exception if the new record is invalid. Validations are not covered on this guide, but let's assume for a moment that you temporarily add
+The block will only be executed if the client is being created. The
+second time we run this code, the block will be ignored.
+
+### `find_or_create_by!`
+
+You can also use `find_or_create_by!` to raise an exception if the new record is invalid. Validations are not covered on this guide, but let's assume for a moment that you temporarily add
```ruby
validates :orders_count, :presence => true
@@ -1272,19 +1284,21 @@ validates :orders_count, :presence => true
to your `Client` model. If you try to create a new `Client` without passing an `orders_count`, the record will be invalid and an exception will be raised:
```ruby
-Client.where(:first_name => 'Andy').first_or_create!(:locked => false)
+Client.find_or_create_by!(first_name: 'Andy')
# => ActiveRecord::RecordInvalid: Validation failed: Orders count can't be blank
```
-As with `first_or_create` there is a `find_or_create_by!` method but the `first_or_create!` method is preferred for clarity.
-
-### `first_or_initialize`
+### `find_or_initialize_by`
-The `first_or_initialize` method will work just like `first_or_create` but it will not call `create` but `new`. This means that a new model instance will be created in memory but won't be saved to the database. Continuing with the `first_or_create` example, we now want the client named 'Nick':
+The `find_or_initialize_by` method will work just like
+`find_or_create_by` but it will call `new` instead of `create`. This
+means that a new model instance will be created in memory but won't be
+saved to the database. Continuing with the `find_or_create_by` example, we
+now want the client named 'Nick':
```ruby
-nick = Client.where(:first_name => 'Nick').first_or_initialize(:locked => false)
-# => <Client id: nil, first_name: "Nick", orders_count: 0, locked: false, created_at: "2011-08-30 06:09:27", updated_at: "2011-08-30 06:09:27">
+nick = Client.find_or_initialize_by(first_name: 'Nick')
+# => <Client id: nil, first_name: "Nick", orders_count: 0, locked: true, created_at: "2011-08-30 06:09:27", updated_at: "2011-08-30 06:09:27">
nick.persisted?
# => false
diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md
index 193cc41d79..c08ad1ee90 100644
--- a/guides/source/active_support_core_extensions.md
+++ b/guides/source/active_support_core_extensions.md
@@ -2871,6 +2871,14 @@ rest = hash.extract!(:a) # => {a: 1}
hash # => {b: 2}
```
+The method `extract!` returns the same subclass of Hash, that the receiver is.
+
+```ruby
+hash = {a: 1, b: 2}.with_indifferent_access
+rest = hash.extract!(:a).class
+# => ActiveSupport::HashWithIndifferentAccess
+```
+
NOTE: Defined in `active_support/core_ext/hash/slice.rb`.
### Indifferent Access
diff --git a/guides/source/ajax_on_rails.md b/guides/source/ajax_on_rails.md
deleted file mode 100644
index 97c56036e8..0000000000
--- a/guides/source/ajax_on_rails.md
+++ /dev/null
@@ -1,316 +0,0 @@
-AJAX on Rails
-=============
-
-This guide covers the built-in Ajax/JavaScript functionality of Rails (and more);
-it will enable you to create rich and dynamic AJAX applications with ease! We will
-cover the following topics:
-
-* Quick introduction to AJAX and related technologies
-* Unobtrusive JavaScript helpers with drivers for Prototype, jQuery etc
-* Testing JavaScript functionality
-
---------------------------------------------------------------------------------
-
-Hello AJAX - a Quick Intro
---------------------------
-
-AJAX is about updating parts of a web page without reloading the page. An AJAX
-call happens as a response to an event, like when the page finished loading or
-when a user clicks on an element. For example, let say you click on a link, which
-would usually take you to a new page, but instead of doing that, an asynchronous
-HTTP request is made and the response is evaluated with JavaScript. That way the
-page is not reloaded and new information can be dynamically included in the page.
-The way that happens is by inserting, removing or changing parts of the DOM. The
-DOM, or Document Object Model, is a convention to represent the HTML document as
-a set of nodes that contain other nodes. For example, a list of names is represented
-as a `ul` element node containing several `li` element nodes. An AJAX call can
-be made to obtain a new list item to include, and append it inside a `li` node to
-the `ul` node.
-
-### Asynchronous JavaScript + XML
-
-AJAX means Asynchronous JavaScript + XML. Asynchronous means that the page is not
-reloaded, the request made is separate from the regular page request. JavaScript
-is used to evaluate the response and the XML part is a bit misleading as XML is
-not required, you respond to the HTTP request with JSON or regular HTML as well.
-
-### The DOM
-
-The DOM (Document Object Model) is a convention to represent HTML (or XML)
-documents, as a set of nodes that act as objects and contain other nodes. You can
-have a `div` element that contains other `div` elements as well as `p` elements
-that contain text.
-
-### Standard HTML communication vs AJAX
-
-In regular HTML comunications, when you click on a link, the browser makes an HTTP
-`GET` request, the server responds with a new HTML document that the browsers renders
-and then replaces the previous one. The same thing happens when you click a button to
-submit a form, except that you make and HTTP `POST` request, but you also get a new
-HTML document that the browser renders and replaces the current one. In AJAX
-communications, the request is separate, and the response is evaluated in JavaScript
-instead of rendered by the browser. That way you can have more control over the content
-that gets returned, and the page is not reloaded.
-
-Built-in Rails Helpers
-----------------------
-
-Rails 4.0 ships with [jQuery](http://jquery.com) as the default JavaScript library.
-The Gemfile contains `gem 'jquery-rails'` which provides the `jquery.js` and
-`jquery_ujs.js` files via the asset pipeline.
-
-You will have to use the `require` directive to tell Sprockets to load `jquery.js`
-and `jquery.js`. For example, a new Rails application includes a default
-`app/assets/javascripts/application.js` file which contains the following lines:
-
-```
-// ...
-//= require jquery
-//= require jquery_ujs
-// ...
-```
-
-The `application.js` file acts like a manifest and is used to tell Sprockets the
-files that you wish to require. In this case, you are requiring the files `jquery.js`
-and `jquery_ujs.js` provided by the `jquery-rails` gem.
-
-If the application is not using the asset pipeline, this can be accessed as:
-
-```ruby
-javascript_include_tag :defaults
-```
-
-By default, `:defaults` loads jQuery.
-
-You can also choose to use Prototype instead of jQuery and specify the option
-using `-j` switch while generating the application.
-
-```bash
-rails new app_name -j prototype
-```
-
-This will add the `prototype-rails` gem to the Gemfile and modify the
-`app/assets/javascripts/application.js` file:
-
-```
-// ...
-//= require prototype
-//= require prototype_ujs
-// ...
-```
-
-You are ready to add some AJAX love to your Rails app!
-
-### Examples
-
-To make them working with AJAX, simply pass the `remote: true` option to
-the original non-remote method.
-
-```ruby
-button_to 'New', action: 'new', form_class: 'new-thing'
-```
-
-will produce
-
-```html
-<form method="post" action="/controller/new" class="new-thing">
- <div><input value="New" type="submit" /></div>
-</form>
-```
-
-```ruby
-button_to 'Create', action: 'create', remote: true, form: { 'data-type' => 'json' }
-```
-
-will produce
-
-```html
-<form method="post" action="/images/create" class="button_to" data-remote="true" data-type="json">
- <div><input value="Create" type="submit" /></div>
-</form>
-```
-
-```ruby
-button_to 'Delete Image', { action: 'delete', id: @image.id },
- method: :delete, data: { confirm: 'Are you sure?' }
-```
-
-will produce
-
-```html
-<form method="post" action="/images/delete/1" class="button_to">
- <div>
- <input type="hidden" name="_method" value="delete" />
- <input data-confirm='Are you sure?' value="Delete" type="submit" />
- </div>
-</form>
-```
-
-```ruby
-button_to 'Destroy', 'http://www.example.com',
- method: 'delete', remote: true, data: { disable_with: 'loading...', confirm: 'Are you sure?' }
-```
-
-will produce
-
-```html
-<form class='button_to' method='post' action='http://www.example.com' data-remote='true'>
- <div>
- <input name='_method' value='delete' type='hidden' />
- <input value='Destroy' type='submit' data-disable-with='loading...' data-confirm='Are you sure?' />
- </div>
-</form>
-```
-
-### The Quintessential AJAX Rails Helper: link_to_remote
-
-Let's start with what is probably the most often used helper: `link_to_remote`. It has an interesting feature from the documentation point of view: the options supplied to `link_to_remote` are shared by all other AJAX helpers, so learning the mechanics and options of `link_to_remote` is a great help when using other helpers.
-
-The signature of `link_to_remote` function is the same as that of the standard `link_to` helper:
-
-```ruby
-def link_to_remote(name, options = {}, html_options = nil)
-```
-
-And here is a simple example of link_to_remote in action:
-
-```ruby
-link_to_remote "Add to cart",
- :url => add_to_cart_url(product.id),
- :update => "cart"
-```
-
-* The very first parameter, a string, is the text of the link which appears on the page.
-* The second parameter, the `options` hash is the most interesting part as it has the AJAX specific stuff:
- * **:url** This is the only parameter that is always required to generate the simplest remote link (technically speaking, it is not required, you can pass an empty `options` hash to `link_to_remote` - but in this case the URL used for the POST request will be equal to your current URL which is probably not your intention). This URL points to your AJAX action handler. The URL is typically specified by Rails REST view helpers, but you can use the `url_for` format too.
- * **:update** Specifying a DOM id of the element we would like to update. The above example demonstrates the simplest way of accomplishing this - however, we are in trouble if the server responds with an error message because that will be injected into the page too! However, Rails has a solution for this situation:
-
- ```ruby
- link_to_remote "Add to cart",
- :url => add_to_cart_url(product),
- :update => { :success => "cart", :failure => "error" }
- ```
-
- If the server returns 200, the output of the above example is equivalent to our first, simple one. However, in case of error, the element with the DOM id `error` is updated rather than the `cart` element.
-
- * **position** By default (i.e. when not specifying this option, like in the examples before) the response is injected into the element with the specified DOM id, replacing the original content of the element (if there was any). You might want to alter this behavior by keeping the original content - the only question is where to place the new content? This can specified by the `position` parameter, with four possibilities:
- * `:before` Inserts the response text just before the target element. More precisely, it creates a text node from the response and inserts it as the left sibling of the target element.
- * `:after` Similar behavior to `:before`, but in this case the response is inserted after the target element.
- * `:top` Inserts the text into the target element, before its original content. If the target element was empty, this is equivalent with not specifying `:position` at all.
- * `:bottom` The counterpart of `:top`: the response is inserted after the target element's original content.
-
- A typical example of using `:bottom` is inserting a new \<li> element into an existing list:
-
- ```ruby
- link_to_remote "Add new item",
- :url => items_url,
- :update => 'item_list',
- :position => :bottom
- ```
-
- * **:method** Most typically you want to use a POST request when adding a remote
-link to your view so this is the default behavior. However, sometimes you'll want to update (PATCH/PUT) or delete/destroy (DELETE) something and you can specify this with the `:method` option. Let's see an example for a typical AJAX link for deleting an item from a list:
-
- ```ruby
- link_to_remote "Delete the item",
- :url => item_url(item),
- :method => :delete
- ```
-
- Note that if we wouldn't override the default behavior (POST), the above snippet would route to the create action rather than destroy.
-
- * **JavaScript filters** You can customize the remote call further by wrapping it with some JavaScript code. Let's say in the previous example, when deleting a link, you'd like to ask for a confirmation by showing a simple modal text box to the user. This is a typical example what you can accomplish with these options - let's see them one by one:
- * `:condition` =&gt; `code` Evaluates `code` (which should evaluate to a boolean) and proceeds if it's true, cancels the request otherwise.
- * `:before` =&gt; `code` Evaluates the `code` just before launching the request. The output of the code has no influence on the execution. Typically used show a progress indicator (see this in action in the next example).
- * `:after` =&gt; `code` Evaluates the `code` after launching the request. Note that this is different from the `:success` or `:complete` callback (covered in the next section) since those are triggered after the request is completed, while the code snippet passed to `:after` is evaluated after the remote call is made. A common example is to disable elements on the page or otherwise prevent further action while the request is completed.
- * `:submit` =&gt; `dom_id` This option does not make sense for `link_to_remote`, but we'll cover it for the sake of completeness. By default, the parent element of the form elements the user is going to submit is the current form - use this option if you want to change the default behavior. By specifying this option you can change the parent element to the element specified by the DOM id `dom_id`.
- * `:with` &gt; `code` The JavaScript code snippet in `code` is evaluated and added to the request URL as a parameter (or set of parameters). Therefore, `code` should return a valid URL query string (like "item_type=8" or "item_type=8&sort=true"). Usually you want to obtain some value(s) from the page - let's see an example:
-
- ```ruby
- link_to_remote "Update record",
- :url => record_url(record),
- :method => :patch,
- :with => "'status=' + 'encodeURIComponent($('status').value) + '&completed=' + $('completed')"
- ```
-
- This generates a remote link which adds 2 parameters to the standard URL generated by Rails, taken from the page (contained in the elements matched by the 'status' and 'completed' DOM id).
-
- * **Callbacks** Since an AJAX call is typically asynchronous, as its name suggests (this is not a rule, and you can fire a synchronous request - see the last option, `:type`) your only way of communicating with a request once it is fired is via specifying callbacks. There are six options at your disposal (in fact 508, counting all possible response types, but these six are the most frequent and therefore specified by a constant):
- * `:loading:` =&gt; `code` The request is in the process of receiving the data, but the transfer is not completed yet.
- * `:loaded:` =&gt; `code` The transfer is completed, but the data is not processed and returned yet
- * `:interactive:` =&gt; `code` One step after `:loaded`: The data is fully received and being processed
- * `:success:` =&gt; `code` The data is fully received, parsed and the server responded with "200 OK"
- * `:failure:` =&gt; `code` The data is fully received, parsed and the server responded with **anything** but "200 OK" (typically 404 or 500, but in general with any status code ranging from 100 to 509)
- * `:complete:` =&gt; `code` The combination of the previous two: The request has finished receiving and parsing the data, and returned a status code (which can be anything).
- * Any other status code ranging from 100 to 509: Additionally you might want to check for other HTTP status codes, such as 404. In this case simply use the status code as a number:
-
- ```ruby
- link_to_remote "Add new item",
- :url => items_url,
- :update => "item_list",
- 404 => "alert('Item not found!')"
- ```
-
- Let's see a typical example for the most frequent callbacks, `:success`, `:failure` and `:complete` in action:
-
- ```ruby
- link_to_remote "Add new item",
- :url => items_url,
- :update => "item_list",
- :before => "$('progress').show()",
- :complete => "$('progress').hide()",
- :success => "display_item_added(request)",
- :failure => "display_error(request)"
- ```
-
- * **:type** If you want to fire a synchronous request for some obscure reason (blocking the browser while the request is processed and doesn't return a status code), you can use the `:type` option with the value of `:synchronous`.
-
-* Finally, using the `html_options` parameter you can add HTML attributes to the generated tag. It works like the same parameter of the `link_to` helper. There are interesting side effects for the `href` and `onclick` parameters though:
- * If you specify the `href` parameter, the AJAX link will degrade gracefully, i.e. the link will point to the URL even if JavaScript is disabled in the client browser
- * `link_to_remote` gains its AJAX behavior by specifying the remote call in the onclick handler of the link. If you supply `html_options[:onclick]` you override the default behavior, so use this with care!
-
-We are finished with `link_to_remote`. I know this is quite a lot to digest for one helper function, but remember, these options are common for all the rest of the Rails view helpers, so we will take a look at the differences / additional parameters in the next sections.
-
-### AJAX Forms
-
-There are three different ways of adding AJAX forms to your view using Rails Prototype helpers. They are slightly different, but striving for the same goal: instead of submitting the form using the standard HTTP request/response cycle, it is submitted asynchronously, thus not reloading the page. These methods are the following:
-
-* `remote_form_for` (and its alias `form_remote_for`) is tied to Rails most tightly of the three since it takes a resource, model or array of resources (in case of a nested resource) as a parameter.
-* `form_remote_tag` AJAXifies the form by serializing and sending its data in the background
-* `submit_to_remote` and `button_to_remote` is more rarely used than the previous two. Rather than creating an AJAX form, you add a button/input
-
-Let's see them in action one by one!
-
-#### `remote_form_for`
-
-#### `form_remote_tag`
-
-#### `submit_to_remote`
-
-### Serving JavaScript
-
-First we'll check out how to send JavaScript to the server manually. You are practically never going to need this, but it's interesting to understand what's going on under the hood.
-
-```ruby
-def javascript_test
- render :text => "alert('Hello, world!')",
- :content_type => "text/javascript"
-end
-```
-
-(Note: if you want to test the above method, create a `link_to_remote` with a single parameter - `:url`, pointing to the `javascript_test` action)
-
-What happens here is that by specifying the Content-Type header variable, we instruct the browser to evaluate the text we are sending over (rather than displaying it as plain text, which is the default behavior).
-
-Testing JavaScript
-------------------
-
-JavaScript testing reminds me the definition of the world 'classic' by Mark Twain: "A classic is something that everybody wants to have read and nobody wants to read." It's similar with JavaScript testing: everyone would like to have it, yet it's not done by too much developers as it is tedious, complicated, there is a proliferation of tools and no consensus/accepted best practices, but we will nevertheless take a stab at it:
-
-* (Fire)Watir
-* Selenium
-* Celerity/Culerity
-* Cucumber+Webrat
-* Mention stuff like screw.unit/jsSpec
-
-Note to self: check out the RailsConf JS testing video
diff --git a/guides/source/configuring.md b/guides/source/configuring.md
index 2131a6c6a8..ab2766054b 100644
--- a/guides/source/configuring.md
+++ b/guides/source/configuring.md
@@ -56,14 +56,6 @@ These configuration methods are to be called on a `Rails::Railtie` object, such
* `config.asset_host` sets the host for the assets. Useful when CDNs are used for hosting assets, or when you want to work around the concurrency constraints builtin in browsers using different domain aliases. Shorter version of `config.action_controller.asset_host`.
-* `config.asset_path` lets you decorate asset paths. This can be a callable, a string, or be `nil` which is the default. For example, the normal path for `blog.js` would be `/javascripts/blog.js`, let that absolute path be `path`. If `config.asset_path` is a callable, Rails calls it when generating asset paths passing `path` as argument. If `config.asset_path` is a string, it is expected to be a `sprintf` format string with a `%s` where `path` will get inserted. In either case, Rails outputs the decorated path. Shorter version of `config.action_controller.asset_path`.
-
- ```ruby
- config.asset_path = proc { |path| "/blog/public#{path}" }
- ```
-
-NOTE. The `config.asset_path` configuration is ignored if the asset pipeline is enabled, which is the default.
-
* `config.autoload_once_paths` accepts an array of paths from which Rails will autoload constants that won't be wiped per request. Relevant if `config.cache_classes` is false, which is the case in development mode by default. Otherwise, all autoloading happens only once. All elements of this array must also be in `autoload_paths`. Default is an empty array.
* `config.autoload_paths` accepts an array of paths from which Rails will autoload constants. Default is all directories under `app`.
@@ -115,9 +107,9 @@ NOTE. The `config.asset_path` configuration is ignored if the asset pipeline is
* `config.middleware` allows you to configure the application's middleware. This is covered in depth in the [Configuring Middleware](#configuring-middleware) section below.
-* `config.queue` configures a different queue implementation for the application. Defaults to `ActiveSupport::SynchronousQueue`. Note that, if the default queue is changed, the default `queue_consumer` is not going to be initialized, it is up to the new queue implementation to handle starting and shutting down its own consumer(s).
+* `config.queue` configures the default job queue for the application. Defaults to `ActiveSupport::Queue.new` which processes jobs in a background thread. If you change the queue, you're responsible for running the jobs as well.
-* `config.queue_consumer` configures a different consumer implementation for the default queue. Defaults to `ActiveSupport::ThreadedQueueConsumer`.
+* `config.queue_consumer` configures a different job consumer for the default queue. Defaults to `ActiveSupport::ThreadedQueueConsumer`. The job consumer must respond to `start`.
* `config.reload_classes_only_on_change` enables or disables reloading of classes only when tracked files change. By default tracks everything on autoload paths and is set to true. If `config.cache_classes` is true, this option is ignored.
@@ -298,8 +290,6 @@ The schema dumper adds one additional configuration option:
* `config.action_controller.asset_host` sets the host for the assets. Useful when CDNs are used for hosting assets rather than the application server itself.
-* `config.action_controller.asset_path` takes a block which configures where assets can be found. Shorter version of `config.action_controller.asset_path`.
-
* `config.action_controller.perform_caching` configures whether the application should perform caching or not. Set to false in development mode, true in production.
* `config.action_controller.default_static_extension` configures the extension used for cached pages. Defaults to `.html`.
@@ -577,8 +567,6 @@ Some parts of Rails can also be configured externally by supplying environment v
* `ENV["RAILS_RELATIVE_URL_ROOT"]` is used by the routing code to recognize URLs when you deploy your application to a subdirectory.
-* `ENV["RAILS_ASSET_ID"]` will override the default cache-busting timestamps that Rails generates for downloadable assets.
-
* `ENV["RAILS_CACHE_ID"]` and `ENV["RAILS_APP_VERSION"]` are used to generate expanded cache keys in Rails' caching code. This allows you to have multiple separate caches from the same application.
diff --git a/guides/source/initialization.md b/guides/source/initialization.md
index c582acd3a3..393bf51863 100644
--- a/guides/source/initialization.md
+++ b/guides/source/initialization.md
@@ -534,7 +534,7 @@ require "rails"
action_controller
action_mailer
rails/test_unit
- sprockets/rails
+ sprockets
).each do |framework|
begin
require "#{framework}/railtie"
diff --git a/guides/source/migrations.md b/guides/source/migrations.md
index 657e872cd0..3eeb45f8c6 100644
--- a/guides/source/migrations.md
+++ b/guides/source/migrations.md
@@ -889,6 +889,27 @@ class AddFuzzToProduct < ActiveRecord::Migration
end
```
+There are other ways in which the above example could have gone badly.
+
+For example, imagine that Alice creates a migration that selectively
+updates the +description+ field on certain products. She runs the
+migration, commits the code, and then begins working on the next feature,
+which is to add a new column +fuzz+ to the products table.
+
+She creates two migrations for this new feature, one which adds the new
+column, and a second which selectively updates the +fuzz+ column based on
+other product attributes.
+
+These migrations run just fine, but when Bob comes back from his vacation
+and calls `rake db:migrate` to run all the outstanding migrations, he gets a
+subtle bug: The descriptions have defaults, and the +fuzz+ column is present,
+but +fuzz+ is nil on all products.
+
+The solution is again to use +Product.reset_column_information+ before
+referencing the Product model in a migration, ensuring the Active Record's
+knowledge of the table structure is current before manipulating data in those
+records.
+
Schema Dumping and You
----------------------
diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md
index 148316d170..d57bb1f8bc 100644
--- a/guides/source/upgrading_ruby_on_rails.md
+++ b/guides/source/upgrading_ruby_on_rails.md
@@ -69,6 +69,8 @@ in the `config/initializers/wrap_parameters.rb` file:
### Action Pack
+Rails 4.0 removed the `ActionController::Base.asset_path` option. Use the assets pipeline feature.
+
Rails 4.0 has deprecated `ActionController::Base.page_cache_extension` option. Use
`ActionController::Base.default_static_extension` instead.
diff --git a/guides/source/working_with_javascript.md b/guides/source/working_with_javascript.md
new file mode 100644
index 0000000000..c33fa8864c
--- /dev/null
+++ b/guides/source/working_with_javascript.md
@@ -0,0 +1,394 @@
+Working With JavaScript
+=======================
+
+This guide covers the built-in Ajax/JavaScript functionality of Rails (and
+more); it will enable you to create rich and dynamic AJAX applications with
+ease! We will cover the following topics:
+
+* An introduction to AJAX
+* Unobtrusive JavaScript
+* Built-in Helpers
+* Server-side concerns
+* Turbolinks
+
+-------------------------------------------------------------------------------
+
+An introduction to AJAX
+------------------------
+
+In order to understand AJAX, you must first understand what a web browser does
+normally.
+
+When you type `http://localhost:3000` into your browser's address bar and hit
+'Go', the browser (your 'client') makes a request to the server. It parses the
+response, then fetches all associated assets, like JavaScript files,
+stylesheets and images. It then assembles the page. If you click a link, it
+does the same process: fetch the page, fetch the assets, put it all together,
+show you the results. This is called the 'Request-Response cycle'.
+
+JavaScript can also make requests to the server, and parse the response. It
+also has the ability to update information on the page. Combining these two
+powers, a JavaScript developer can make a web page that can update just parts of
+itself, without needing to get the full page data from the server. This is a
+powerful technique that we call AJAX, which stands for Asynchronous JavaScript and XML.
+
+Rails ships with CoffeeScript by default, and so the rest of the examples
+in this guide will be in CoffeeScript. All of these lessons, of course, apply
+to vanilla JavaScript as well.
+
+As an example, here's some CoffeeScript code that makes an AJAX request using
+the jQuery library:
+
+```
+$.ajax(url: "/test").done (html) ->
+ $("#results").append html
+```
+
+This code fetches data from "/test", and then appends the result to the `div`
+with an id of `results`.
+
+Rails provides quite a bit of built-in support for building web pages with this
+technique. You rarely have to write this code yourself. The rest of this guide
+will show you how Rails can help you write web sites in this manner, but it's
+all built on top of this fairly simple technique.
+
+Unobtrusive JavaScript
+-------------------------------------
+
+Rails uses a technique called "Unobtrusive JavaScript" to handle attaching
+JavaScript to the DOM. This is generally considered to be a best-practice
+within the frontend community, but you may occasionally read tutorials that
+demonstrate other ways.
+
+Here's the simplest way to write JavaScript. You may see it referred to as
+'inline JavaScript':
+
+```
+<a href="#" onclick="alert('Hello, world.')">Here</a>
+```
+
+When clicked, the alert will trigger. Here's the problem: what happens when
+we have lots of JavaScript we want to execute on a click?
+
+```
+<a href="#" onclick="function fib(n){return n<2?n:fib(n-1)+fib(n-2);};alert('fib of 15 is: ' + fib(15) + '.');">Calculate</a>
+```
+
+Awkward, right? We could pull the function definition out of the click handler,
+and turn it into CoffeeScript:
+
+```
+fib = (n) ->
+ (if n < 2 then n else fib(n - 1) + fib(n - 2))
+```
+
+And then on our page:
+
+```
+<a href="#" onclick="alert('fib of 15 is: ' + fib(15) + '.');">Calculate</a>
+```
+
+That's a little bit better, but what about multiple links that have the same
+effect?
+
+```
+<a href="#" onclick="alert('fib of 16 is: ' + fib(16) + '.');">Calculate</a>
+<a href="#" onclick="alert('fib of 17 is: ' + fib(17) + '.');">Calculate</a>
+<a href="#" onclick="alert('fib of 18 is: ' + fib(18) + '.');">Calculate</a>
+```
+
+Not very DRY, eh? We can fix this by using events instead. We'll add a `data-*`
+attribute to our link, and then bind a handler to the click event of every link
+that has that attribute:
+
+```
+fib = (n) ->
+ (if n < 2 then n else fib(n - 1) + fib(n - 2))
+
+$(document).ready ->
+ $("a[data-fib]").click (e) ->
+ count = $(this).data("fib")
+ alert "fib of #{count} is: #{fib(count)}."
+
+... later ...
+
+<a href="#" data-fib="15">Calculate</a>
+<a href="#" data-fib="16">Calculate</a>
+<a href="#" data-fib="17">Calculate</a>
+```
+
+We call this 'unobtrusive' JavaScript because we're no longer mixing our
+JavaScript into our HTML. We've properly separated our concerns, making future
+changes easier. We can easily add behavior to any link by adding the data
+attribute. We can run all of our JavaScript through a minimizer and
+concatenator. We can serve our entire JavaScript bundle on every page, which
+means that it'll get downloaded on the first page load and then be cached on
+every page after that. Lots of little benefits really add up.
+
+The Rails team strongly encourages you to write your CoffeeScript (and
+JavaScript) in this style, and you can expect that many libraries will also
+follow this pattern.
+
+Built-in Helpers
+----------------------
+
+Rails provides a bunch of view helper methods written in Ruby to assist you
+in generating HTML. Sometimes, you want to add a little AJAX to those elements,
+and Rails has got your back in those cases.
+
+Because of Unobtrusive JavaScript, the Rails AJAX helpers actually consist of two
+parts: the JavaScript part and the Ruby part.
+[rails.js](https://github.com/rails/jquery-ujs/blob/master/src/rails.js)
+provides the JavaScript half, and the regular Ruby view helpers add appropriate
+tags to your DOM. The CoffeeScript in rails.js then listens for these
+attributes, and attaches appropriate handlers.
+
+### form_for
+
+[`form_for`](http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for)
+is a helper that assists with writing forms. `form_for` takes a `:remote`
+option. It works like this:
+
+```
+<%= form_for(@post, remote: true) do |f| %>
+ ...
+<% end %>
+```
+
+This will generate the following HTML:
+
+```
+<form accept-charset="UTF-8" action="/posts" class="new_post" data-remote="true" id="new_post" method="post">
+ ...
+</form>
+```
+
+Note the `data-remote='true'`. Now, the form will be submitted by AJAX rather
+than by the browser's normal submit mechanism.
+
+You probably don't want to just sit there with a filled out `<form>`, though.
+You probably want to do something upon a successful submission. To do that,
+bind to the `ajax:success` event. On failure, use `ajax:error`. Check it out:
+
+```
+<script>
+$(document).ready ->
+ $("#new_post").on("ajax:success", (e, data, status, xhr) ->
+ $("#new_post").append xhr.responseText
+ ).bind "ajax:error", (e, xhr, status, error) ->
+ $("#new_post").append "<p>ERROR</p>"
+</script>
+```
+
+Obviously, you'll want to be a bit more sophisticated than that, but it's a
+start.
+
+### form_tag
+
+[`form_tag`](http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-form_tag)
+is very similar to `form_for`. It has a `:remote` option that you can use like
+this:
+
+```
+<%= form_tag('/posts', remote: true) %>
+```
+
+Everything else is the same as `form_for`. See its documentation for full
+details.
+
+### link_to
+
+[`link_to`](http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to)
+is a helper that assits with generating links. It has a `:remote` option you
+can use like this:
+
+```
+<%= link_to "first post", @post, remote: true %>
+```
+
+which generates
+
+```
+<a href="/posts/1" data-remote="true">a post</a>
+```
+
+You can bind to the same AJAX events as `form_for`. Here's an example. Let's
+assume that we have a resource `/fib/:n` that calculates the `n`th Fibonacci
+number. We would generate some HTML like this:
+
+```
+<%= link_to "Calculate", "/fib/15", remote: true, data: { fib: 15 } %>
+```
+
+and write some CoffeeScript like this:
+
+```
+$(document).ready ->
+ $("a[data-fib]").on "ajax:success", (e, data, status, xhr) ->
+ count = $(this).data("fib")
+ alert "fib of #{count} is: #{data}."
+```
+
+Easy!
+
+### button_to
+
+[`button_to`](http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-button_to) is a helper that helps you create buttons. It has a `:remote` option that you can call like this:
+
+```
+<%= button_to "A post", @post, remote: true %>
+```
+
+this generates
+
+```
+<form action="/posts/1" class="button_to" data-remote="true" method="post">
+</form>
+```
+
+Since it's just a `<form>`, all of the information on `form_for` also applies.
+
+Server-side concerns
+--------------------
+
+AJAX isn't just client-side, you also need to do some work on the server
+side to support it. Often, people like their AJAX requests to return JSON
+rather than HTML. Let's discuss what it takes to make that happen.
+
+### A Simple Example
+
+Imagine you have a series of users that you would like to display and provide a
+form on that same page to create a new user. The index action of your
+controller looks like this:
+
+```
+class UsersController < ApplicationController
+ def index
+ @users = User.all
+ @user = User.new
+ end
+ # ...
+```
+
+The index view (`app/views/users/index.html.erb`) contains:
+
+```
+<b>Users</b>
+
+<ul id="users">
+<% @users.each do |user| %>
+ <%= render user %>
+<% end %>
+</ul>
+
+<br>
+
+<%= form_for(@user, remote: true) do |f| %>
+ <%= f.label :name %><br>
+ <%= f.text_field :name %>
+ <%= f.submit %>
+<% end %>
+```
+
+The `app/views/users/_user.html.erb` partial contains the following:
+
+```
+<li><%= user.name %></li>
+```
+
+The top portion of the index page displays the users. The bottom portion
+provides a form to create a new user.
+
+The bottom form will call the create action on the Users controller. Because
+the form's remote option is set to true, the request will be posted to the
+users controller as an AJAX request, looking for JavaScript. In order to
+service that request, the create action of your controller would look like
+this:
+
+```
+ # app/controllers/users_controller.rb
+ # ......
+ def create
+ @user = User.new(params[:user])
+
+ respond_to do |format|
+ if @user.save
+ format.html { redirect_to @user, notice: 'User was successfully created.' }
+ format.js {}
+ format.json { render json: @user, status: :created, location: @user }
+ else
+ format.html { render action: "new" }
+ format.json { render json: @user.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+```
+
+Notice the format.js in the respond_to block; that allows the controller to
+respond to your AJAX request. You then have a corresponding
+`app/views/users/create.js.erb` view file that generates the actual JavaScript
+code that will be sent and executed on the client side.
+
+```
+$("<%= escape_javascript(render @user) %>").appendTo("#users");
+```
+
+Turbolinks
+----------
+
+Rails 4 ships with the [Turbolinks gem](https://github.com/rails/turbolinks).
+This gem uses AJAX to speed up page rendering in most applications.
+
+### How Turbolinks works
+
+Turbolinks attaches a click handler to all `<a>` on the page. If your browser
+supports
+[PushState](https://developer.mozilla.org/en-US/docs/DOM/Manipulating_the_browser_history#The_pushState(\).C2.A0method),
+Turbolinks will make an AJAX request for the page, parse the response, and
+replace the entire `<body>` of the page with the `<body>` of the response. It
+will then use PushState to change the URL to the correct one, preserving
+refresh semantics and giving you pretty URLs.
+
+The only thing you have to do to enable Turbolinks is have it in your Gemfile,
+and put `//= require turbolinks` in your CoffeeScript manifest, which is usually
+`app/assets/javascripts/application.js`.
+
+If you want to disable Turbolinks for certain links, add a `data-no-turbolink`
+attribute to the tag:
+
+```
+<a href="..." data-no-turbolink>No turbolinks here</a>.
+```
+
+### Page Change events
+
+When writing CoffeeScript, you'll often want to do some sort of processing upon
+page load. With jQuery, you'd write something like this:
+
+```
+$(document).ready ->
+ alert "page has loaded!"
+```
+
+However, because Turbolinks overrides the normal page loading process, the
+event that this relies on will not be fired. If you have code that looks like
+this, you must change your code to do this instead:
+
+```
+$(document).on "page:change", ->
+ alert "page has loaded!"
+```
+
+For more details, including other events you can bind to, check out [the
+Turbolinks
+README](https://github.com/rails/turbolinks/blob/ec9ca4d6cf9626e03a672f3b9e7968c816aff94e/README.md).
+
+Other resources
+---------------
+
+Here are some helpful links to help you learn even more:
+
+* [jquery-ujs wiki](https://github.com/rails/jquery-ujs/wiki)
+* [jquery-ujs list of external articles](https://github.com/rails/jquery-ujs/wiki/External-articles)
+* [Rails 3 Remote Links and Forms: A Definitive Guide](http://www.alfajango.com/blog/rails-3-remote-links-and-forms/)
+* [Railscasts: Unobtrusive JavaScript](http://railscasts.com/episodes/205-unobtrusive-javascript)