diff options
Diffstat (limited to 'guides/source')
22 files changed, 283 insertions, 171 deletions
diff --git a/guides/source/action_mailer_basics.md b/guides/source/action_mailer_basics.md index c31b50fcfc..c39cd34e9a 100644 --- a/guides/source/action_mailer_basics.md +++ b/guides/source/action_mailer_basics.md @@ -326,7 +326,7 @@ key. The list of emails can be an array of email addresses or a single string with the addresses separated by commas. ```ruby -class AdminMailer < ActionMailer::Base +class AdminMailer < ApplicationMailer default to: Proc.new { Admin.pluck(:email) }, from: 'notification@example.com' @@ -759,6 +759,9 @@ config.action_mailer.smtp_settings = { authentication: 'plain', enable_starttls_auto: true } ``` +Note: As of July 15, 2014, Google increased [its security measures](https://support.google.com/accounts/answer/6010255) and now blocks attempts from apps it deems less secure. +You can change your gmail settings [here](https://www.google.com/settings/security/lesssecureapps) to allow the attempts or +use another ESP to send email by replacing 'smpt.gmail.com' above with the address of your provider. Mailer Testing -------------- diff --git a/guides/source/action_view_overview.md b/guides/source/action_view_overview.md index 98c6cbd540..db7eeed19a 100644 --- a/guides/source/action_view_overview.md +++ b/guides/source/action_view_overview.md @@ -15,7 +15,7 @@ After reading this guide, you will know: What is Action View? -------------------- -Action View and Action Controller are the two major components of Action Pack. In Rails, web requests are handled by Action Pack, which splits the work into a controller part (performing the logic) and a view part (rendering a template). Typically, Action Controller will be concerned with communicating with the database and performing CRUD actions where necessary. Action View is then responsible for compiling the response. +In Rails, web requests are handled by [Action Controller](action_controller_overview.html) and Action View. Typically, Action Controller will be concerned with communicating with the database and performing CRUD actions where necessary. Action View is then responsible for compiling the response. Action View templates are written using embedded Ruby in tags mingled with HTML. To avoid cluttering the templates with boilerplate code, a number of helper classes provide common behavior for forms, dates, and strings. It's also easy to add new helpers to your application as it evolves. diff --git a/guides/source/active_job_basics.md b/guides/source/active_job_basics.md index dd545b56f5..cb25a4c5f3 100644 --- a/guides/source/active_job_basics.md +++ b/guides/source/active_job_basics.md @@ -280,6 +280,19 @@ UserMailer.welcome(@user).deliver_later ``` +Internationalization +-------------------- + +Each job uses the `I18n.locale` set when the job was created. Useful if you send +emails asynchronously: + +```ruby +I18n.locale = :eo + +UserMailer.welcome(@user).deliver_later # Email will be localized to Esparanto. +``` + + GlobalID -------- diff --git a/guides/source/active_model_basics.md b/guides/source/active_model_basics.md index 4b2bfaee2f..81e2a69504 100644 --- a/guides/source/active_model_basics.md +++ b/guides/source/active_model_basics.md @@ -8,12 +8,12 @@ classes. Active Model allows for Action Pack helpers to interact with plain Ruby objects. Active Model also helps build custom ORMs for use outside of the Rails framework. -After reading this guide, you will be able to add to plain Ruby objects: +After reading this guide, you will know: -* The ability to behave like an Active Record model. -* Callbacks and validations like Active Record. -* Serializers. -* Integration with the Rails internationalization (i18n) framework. +* How an Active Record model behaves. +* How Callbacks and validations work. +* How serializers work. +* The Rails internationalization (i18n) framework. -------------------------------------------------------------------------------- @@ -319,9 +319,8 @@ person.serializable_hash # => {"name"=>"Bob"} #### ActiveModel::Serializers -Rails provides two serializers `ActiveModel::Serializers::JSON` and -`ActiveModel::Serializers::Xml`. Both of these modules automatically include -the `ActiveModel::Serialization`. +Rails provides a `ActiveModel::Serializers::JSON` serializer. +This module automatically include the `ActiveModel::Serialization`. ##### ActiveModel::Serializers::JSON @@ -379,62 +378,6 @@ person.from_json(json) # => #<Person:0x00000100c773f0 @name="Bob"> person.name # => "Bob" ``` -##### ActiveModel::Serializers::Xml - -To use the `ActiveModel::Serializers::Xml` you only need to change from -`ActiveModel::Serialization` to `ActiveModel::Serializers::Xml`. - -```ruby -class Person - include ActiveModel::Serializers::Xml - - attr_accessor :name - - def attributes - {'name' => nil} - end -end -``` - -With the `to_xml` you have an XML representing the model. - -```ruby -person = Person.new -person.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<person>\n <name nil=\"true\"/>\n</person>\n" -person.name = "Bob" -person.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<person>\n <name>Bob</name>\n</person>\n" -``` - -From an XML string you define the attributes of the model. -You need to have the `attributes=` method defined on your class: - -```ruby -class Person - include ActiveModel::Serializers::Xml - - attr_accessor :name - - def attributes=(hash) - hash.each do |key, value| - send("#{key}=", value) - end - end - - def attributes - {'name' => nil} - end -end -``` - -Now it is possible to create an instance of person and set the attributes using `from_xml`. - -```ruby -xml = { name: 'Bob' }.to_xml -person = Person.new -person.from_xml(xml) # => #<Person:0x00000100c773f0 @name="Bob"> -person.name # => "Bob" -``` - ### Translation `ActiveModel::Translation` provides integration between your object and the Rails diff --git a/guides/source/active_record_basics.md b/guides/source/active_record_basics.md index a227b54040..f4baf92228 100644 --- a/guides/source/active_record_basics.md +++ b/guides/source/active_record_basics.md @@ -260,7 +260,7 @@ david = User.find_by(name: 'David') ```ruby # find all users named David who are Code Artists and sort by created_at in reverse chronological order -users = User.where(name: 'David', occupation: 'Code Artist').order('created_at DESC') +users = User.where(name: 'David', occupation: 'Code Artist').order(created_at: :desc) ``` You can learn more about querying an Active Record model in the [Active Record diff --git a/guides/source/active_record_migrations.md b/guides/source/active_record_migrations.md index ce605c912e..4e5902fb3d 100644 --- a/guides/source/active_record_migrations.md +++ b/guides/source/active_record_migrations.md @@ -357,8 +357,8 @@ will append `ENGINE=BLACKHOLE` to the SQL statement used to create the table ### Creating a Join Table -Migration method `create_join_table` creates an HABTM join table. A typical use -would be: +The migration method `create_join_table` creates an HABTM (has and belongs to +many) join table. A typical use would be: ```ruby create_join_table :products, :categories @@ -367,23 +367,21 @@ create_join_table :products, :categories which creates a `categories_products` table with two columns called `category_id` and `product_id`. These columns have the option `:null` set to `false` by default. This can be overridden by specifying the `:column_options` -option. +option: ```ruby -create_join_table :products, :categories, column_options: {null: true} +create_join_table :products, :categories, column_options: { null: true } ``` -will create the `product_id` and `category_id` with the `:null` option as -`true`. - -You can pass the option `:table_name` when you want to customize the table -name. For example: +By default, the name of the join table comes from the union of the first two +arguments provided to create_join_table, in alphabetical order. +To customize the name of the table, provide a `:table_name` option: ```ruby create_join_table :products, :categories, table_name: :categorization ``` -will create a `categorization` table. +creates a `categorization` table. `create_join_table` also accepts a block, which you can use to add indices (which are not created by default) or additional columns: @@ -1006,7 +1004,10 @@ such features, the `execute` method can be used to execute arbitrary SQL. Migrations and Seed Data ------------------------ -Some people use migrations to add data to the database: +The main purpose of Rails' migration feature is to issue commands that modify the +schema using a consistent process. Migrations can also be used +to add or modify data. This is useful in an existing database that can't be destroyed +and recreated, such as a production database. ```ruby class AddInitialProducts < ActiveRecord::Migration @@ -1022,9 +1023,11 @@ class AddInitialProducts < ActiveRecord::Migration end ``` -However, Rails has a 'seeds' feature that should be used for seeding a database -with initial data. It's a really simple feature: just fill up `db/seeds.rb` -with some Ruby code, and run `rake db:seed`: +To add initial data after a database is created, Rails has a built-in +'seeds' feature that makes the process quick and easy. This is especially +useful when reloading the database frequently in development and test environments. +It's easy to get started with this feature: just fill up `db/seeds.rb` with some +Ruby code, and run `rake db:seed`: ```ruby 5.times do |i| diff --git a/guides/source/active_record_postgresql.md b/guides/source/active_record_postgresql.md index fe112a4708..9d495dfacb 100644 --- a/guides/source/active_record_postgresql.md +++ b/guides/source/active_record_postgresql.md @@ -252,7 +252,7 @@ extension to use uuid. ```ruby # db/migrate/20131220144913_create_revisions.rb create_table :revisions do |t| - t.column :identifier, :uuid + t.uuid :identifier end # app/models/revision.rb diff --git a/guides/source/active_support_instrumentation.md b/guides/source/active_support_instrumentation.md index e49abc41f4..cd44c685ba 100644 --- a/guides/source/active_support_instrumentation.md +++ b/guides/source/active_support_instrumentation.md @@ -244,14 +244,6 @@ INFO. The adapters will add their own data as well. } ``` -### identity.active_record - -| Key | Value | -| ---------------- | ----------------------------------------- | -| `:line` | Primary Key of object in the identity map | -| `:name` | Record's class | -| `:connection_id` | `self.object_id` | - ### instantiation.active_record | Key | Value | diff --git a/guides/source/asset_pipeline.md b/guides/source/asset_pipeline.md index 4a610e8458..fc7dd3a6c6 100644 --- a/guides/source/asset_pipeline.md +++ b/guides/source/asset_pipeline.md @@ -403,13 +403,13 @@ When using the asset pipeline, paths to assets must be re-written and underscored in Ruby) for the following asset classes: image, font, video, audio, JavaScript and stylesheet. -* `image-url("rails.png")` becomes `url(/assets/rails.png)` -* `image-path("rails.png")` becomes `"/assets/rails.png"`. +* `url(/assets/rails.png)` becomes `image-url("rails.png")` +* `"/assets/rails.png"` becomes `image-path("rails.png")` . The more generic form can also be used: -* `asset-url("rails.png")` becomes `url(/assets/rails.png)` -* `asset-path("rails.png")` becomes `"/assets/rails.png"` +* `url(/assets/rails.png)` becomes `asset-url("rails.png")` +* `"/assets/rails.png"` becomes `asset-path("rails.png")` #### JavaScript/CoffeeScript and ERB diff --git a/guides/source/association_basics.md b/guides/source/association_basics.md index c0fa3cfd04..1191f5edfe 100644 --- a/guides/source/association_basics.md +++ b/guides/source/association_basics.md @@ -622,6 +622,19 @@ end We pass `id: false` to `create_table` because that table does not represent a model. That's required for the association to work properly. If you observe any strange behavior in a `has_and_belongs_to_many` association like mangled model IDs, or exceptions about conflicting IDs, chances are you forgot that bit. +You can also use the method `create_join_table` + +```ruby +class CreateAssembliesPartsJoinTable < ActiveRecord::Migration + def change + create_join_table :assemblies, :parts do |t| + t.index :assembly_id + t.index :part_id + end + end +end +``` + ### Controlling Association Scope By default, associations look for objects only within the current module's scope. This can be important when you declare Active Record models within a module. For example: diff --git a/guides/source/caching_with_rails.md b/guides/source/caching_with_rails.md index 20f11c2bc2..9a56233e4a 100644 --- a/guides/source/caching_with_rails.md +++ b/guides/source/caching_with_rails.md @@ -3,12 +3,24 @@ Caching with Rails: An Overview =============================== -This guide is an introduction to speeding up your Rails app with caching. +This guide is an introduction to speeding up your Rails application with caching. + +Caching means to store content generated during the request-response cycle and +to reuse it when responding to similar requests. + +Caching is often the most effective way to boost an application's performance. +Through caching, web sites running on a single server with a single database +can sustain a load of thousands of concurrent users. + +Rails provides a set of caching features out of the box. This guide will teach +you the scope and purpose of each one of them. Master these techniques and your +Rails applications can serve millions of views without exorbitant response times +or server bills. After reading this guide, you will know: -* Page and action caching. * Fragment and Russian doll caching. +* How to manage the caching dependencies. * Alternative cache stores. * Conditional GET support. @@ -32,7 +44,7 @@ config.action_controller.perform_caching = true ``` NOTE: Changing the value of `config.action_controller.perform_caching` will -only have an effect on the caching provided by the Action Controller component. +only have an effect on the caching provided by the Action Controller component. For instance, it will not impact low-level caching, that we address [below](#low-level-caching). @@ -103,6 +115,30 @@ If you want to cache a fragment under certain conditions, you can use <% end %> ``` +#### Collection caching + +The `render` helper can also cache individual templates rendered for a collection. +It can even one up the previous example with `each` by reading all cache +templates at once instead of one by one. This is done automatically if the template +rendered by the collection includes a `cache` call. Take a collection that renders +a `products/_product.html.erb` partial for each element: + +```ruby +render products +``` + +If `products/_product.html.erb` starts with a `cache` call like so: + +```html+erb +<% cache product do %> + <%= product.name %> +<% end %> +``` + +All the cached templates from previous renders will be fetched at once with much +greater speed. There's more info on how to make your templates [eligible for +collection caching](http://api.rubyonrails.org/classes/ActionView/Template/Handlers/ERB.html#method-i-resource_cache_call_pattern). + ### Russian Doll Caching You may want to nest cached fragments inside other cached fragments. This is @@ -152,6 +188,93 @@ With `touch` set to true, any action which changes `updated_at` for a game record will also change it for the associated product, thereby expiring the cache. +### Managing dependencies + +In order to correctly invalidate the cache, you need to properly define the +caching dependencies. Rails is clever enough to handle common cases so you don't +have to specify anything. However, sometimes, when you're dealing with custom +helpers for instance, you need to explicitly define them. + +#### Implicit dependencies + +Most template dependencies can be derived from calls to `render` in the template +itself. Here are some examples of render calls that `ActionView::Digestor` knows +how to decode: + +```ruby +render partial: "comments/comment", collection: commentable.comments +render "comments/comments" +render 'comments/comments' +render('comments/comments') + +render "header" => render("comments/header") + +render(@topic) => render("topics/topic") +render(topics) => render("topics/topic") +render(message.topics) => render("topics/topic") +``` + +On the other hand, some calls need to be changed to make caching work properly. +For instance, if you're passing a custom collection, you'll need to change: + +```ruby +render @project.documents.where(published: true) +``` + +to: + +```ruby +render partial: "documents/document", collection: @project.documents.where(published: true) +``` + +#### Explicit dependencies + +Sometimes you'll have template dependencies that can't be derived at all. This +is typically the case when rendering happens in helpers. Here's an example: + +```html+erb +<%= render_sortable_todolists @project.todolists %> +``` + +You'll need to use a special comment format to call those out: + +```html+erb +<%# Template Dependency: todolists/todolist %> +<%= render_sortable_todolists @project.todolists %> +``` + +In some cases, like a single table inheritance setup, you might have a bunch of +explicit dependencies. Instead of writing every template out, you can use a +wildcard to match any template in a directory: + +```html+erb +<%# Template Dependency: events/* %> +<%= render_categorizable_events @person.events %> +``` + +As for collection caching, if the partial template doesn't start with a clean +cache call, you can still benefit from collection caching by adding a special +comment format anywhere in the template, like: + +```html+erb +<%# Template Collection: notification %> +<% my_helper_that_calls_cache(some_arg, notification) do %> + <%= notification.name %> +<% end %> +``` + +#### External dependencies + +If you use a helper method, for example, inside a cached block and you then update +that helper, you'll have to bump the cache as well. It doesn't really matter how +you do it, but the md5 of the template file must change. One recommendation is to +simply be explicit in a comment, like: + +```html+erb +<%# Helper Dependency Updated: Jul 28, 2015 at 7pm %> +<%= some_helper_method(person) %> +``` + ### Low-Level Caching Sometimes you need to cache a particular value or query result instead of caching view fragments. Rails' caching mechanism works great for storing __any__ kind of information. @@ -207,16 +330,17 @@ persistent fashion, you can with low level caching. Cache Stores ------------ -Rails provides different stores for the cached data created by **action** and **fragment** caches. - -TIP: Page caches are always stored on disk. +Rails provides different stores for the cached data (apart from SQL and page +caching). ### Configuration -You can set up your application's default cache store by calling `config.cache_store=` in the Application definition inside your `config/application.rb` file or in an Application.configure block in an environment specific configuration file (i.e. `config/environments/*.rb`). The first argument will be the cache store to use and the rest of the argument will be passed as arguments to the cache store constructor. +You can set up your application's default cache store by setting the +`config.cache_store` configuration option. Other parameters can be passed as +arguments to the cache store's constructor: ```ruby -config.cache_store = :memory_store +config.cache_store = :memory_store, { size: 64.megabytes } ``` NOTE: Alternatively, you can call `ActionController::Base.cache_store` outside of a configuration block. @@ -241,6 +365,19 @@ There are some common options used by all cache implementations. These can be pa * `:race_condition_ttl` - This option is used in conjunction with the `:expires_in` option. It will prevent race conditions when cache entries expire by preventing multiple processes from simultaneously regenerating the same entry (also known as the dog pile effect). This option sets the number of seconds that an expired entry can be reused while a new value is being regenerated. It's a good practice to set this value if you use the `:expires_in` option. +#### Custom Cache Stores + +You can create your own custom cache store by simply extending +`ActiveSupport::Cache::Store` and implementing the appropriate methods. This way, +you can swap in any number of caching technologies into your Rails application. + +To use a custom cache store, simply set the cache store to a new instance of your +custom class. + +```ruby +config.cache_store = MyCacheStore.new +``` + ### ActiveSupport::Cache::MemoryStore This cache store keeps entries in memory in the same Ruby process. The cache @@ -292,36 +429,6 @@ The `write` and `fetch` methods on this cache accept two additional options that config.cache_store = :mem_cache_store, "cache-1.example.com", "cache-2.example.com" ``` -### ActiveSupport::Cache::EhcacheStore - -If you are using JRuby you can use Terracotta's Ehcache as the cache store for your application. Ehcache is an open source Java cache that also offers an enterprise version with increased scalability, management, and commercial support. You must first install the jruby-ehcache-rails3 gem (version 1.1.0 or later) to use this cache store. - -```ruby -config.cache_store = :ehcache_store -``` - -When initializing the cache, you may use the `:ehcache_config` option to specify the Ehcache config file to use (where the default is "ehcache.xml" in your Rails config directory), and the :cache_name option to provide a custom name for your cache (the default is rails_cache). - -In addition to the standard `:expires_in` option, the `write` method on this cache can also accept the additional `:unless_exist` option, which will cause the cache store to use Ehcache's `putIfAbsent` method instead of `put`, and therefore will not overwrite an existing entry. Additionally, the `write` method supports all of the properties exposed by the [Ehcache Element class](http://ehcache.org/apidocs/net/sf/ehcache/Element.html) , including: - -| Property | Argument Type | Description | -| --------------------------- | ------------------- | ----------------------------------------------------------- | -| elementEvictionData | ElementEvictionData | Sets this element's eviction data instance. | -| eternal | boolean | Sets whether the element is eternal. | -| timeToIdle, tti | int | Sets time to idle | -| timeToLive, ttl, expires_in | int | Sets time to Live | -| version | long | Sets the version attribute of the ElementAttributes object. | - -These options are passed to the `write` method as Hash options using either camelCase or underscore notation, as in the following examples: - -```ruby -Rails.cache.write('key', 'value', time_to_idle: 60.seconds, timeToLive: 600.seconds) -caches_action :index, expires_in: 60.seconds, unless_exist: true -``` - -For more information about Ehcache, see [http://ehcache.org/](http://ehcache.org/) . -For more information about Ehcache for JRuby and Rails, see [http://ehcache.org/documentation/jruby.html](http://ehcache.org/documentation/jruby.html) - ### ActiveSupport::Cache::NullStore This cache store implementation is meant to be used only in development or test environments and it never stores anything. This can be very useful in development when you have code that interacts directly with `Rails.cache` but caching may interfere with being able to see the results of code changes. With this cache store, all `fetch` and `read` operations will result in a miss. @@ -330,19 +437,13 @@ This cache store implementation is meant to be used only in development or test config.cache_store = :null_store ``` -### Custom Cache Stores - -You can create your own custom cache store by simply extending `ActiveSupport::Cache::Store` and implementing the appropriate methods. In this way, you can swap in any number of caching technologies into your Rails application. - -To use a custom cache store, simply set the cache store to a new instance of the class. - -```ruby -config.cache_store = MyCacheStore.new -``` - -### Cache Keys +Cache Keys +---------- -The keys used in a cache can be any object that responds to either `:cache_key` or `:to_param`. You can implement the `:cache_key` method on your classes if you need to generate custom keys. Active Record will generate keys based on the class name and record id. +The keys used in a cache can be any object that responds to either `cache_key` or +`to_param`. You can implement the `cache_key` method on your classes if you need +to generate custom keys. Active Record will generate keys based on the class name +and record id. You can use Hashes and Arrays of values as cache keys. @@ -351,7 +452,12 @@ You can use Hashes and Arrays of values as cache keys. Rails.cache.read(site: "mysite", owners: [owner_1, owner_2]) ``` -The keys you use on `Rails.cache` will not be the same as those actually used with the storage engine. They may be modified with a namespace or altered to fit technology backend constraints. This means, for instance, that you can't save values with `Rails.cache` and then try to pull them out with the `memcache-client` gem. However, you also don't need to worry about exceeding the memcached size limit or violating syntax rules. +The keys you use on `Rails.cache` will not be the same as those actually used with +the storage engine. They may be modified with a namespace or altered to fit +technology backend constraints. This means, for instance, that you can't save +values with `Rails.cache` and then try to pull them out with the `dalli` gem. +However, you also don't need to worry about exceeding the memcached size limit or +violating syntax rules. Conditional GET support ----------------------- diff --git a/guides/source/command_line.md b/guides/source/command_line.md index 0f5a9e4e39..cd265331d6 100644 --- a/guides/source/command_line.md +++ b/guides/source/command_line.md @@ -260,7 +260,13 @@ $ bin/rake db:migrate == CreateHighScores: migrated (0.0019s) ====================================== ``` -INFO: Let's talk about unit tests. Unit tests are code that tests and makes assertions about code. In unit testing, we take a little part of code, say a method of a model, and test its inputs and outputs. Unit tests are your friend. The sooner you make peace with the fact that your quality of life will drastically increase when you unit test your code, the better. Seriously. We'll make one in a moment. +INFO: Let's talk about unit tests. Unit tests are code that tests and makes assertions +about code. In unit testing, we take a little part of code, say a method of a model, +and test its inputs and outputs. Unit tests are your friend. The sooner you make +peace with the fact that your quality of life will drastically increase when you unit +test your code, the better. Seriously. Please visit +[the testing guide](http://guides.rubyonrails.org/testing.html) for an in-depth +look at unit testing. Let's see the interface Rails created for us. diff --git a/guides/source/configuring.md b/guides/source/configuring.md index 9c80e73c73..47c275609e 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -414,7 +414,7 @@ encrypted cookies salt value. Defaults to `'signed encrypted cookie'`. `config.action_view` includes a small number of configuration settings: -* `config.action_view.field_error_proc` provides an HTML generator for displaying errors that come from Active Record. The default is +* `config.action_view.field_error_proc` provides an HTML generator for displaying errors that come from Active Model. The default is ```ruby Proc.new do |html_tag, instance| diff --git a/guides/source/credits.html.erb b/guides/source/credits.html.erb index 61ea0b44ef..1d995581fa 100644 --- a/guides/source/credits.html.erb +++ b/guides/source/credits.html.erb @@ -28,7 +28,7 @@ Ruby on Rails Guides: Credits <h3 class="section">Rails Guides Authors</h3> <%= author('Ryan Bigg', 'radar', 'radar.png') do %> - Ryan Bigg works as the Community Manager at <a href="http://spreecommerce.com">Spree Commerce</a> and has been working with Rails since 2006. He's the author of <a href="https://leanpub.com/multi-tenancy-rails">Multi Tenancy With Rails</a> and co-author of <a href="http://manning.com/bigg2">Rails 4 in Action</a>. He's written many gems which can be seen on <a href="https://github.com/radar">his GitHub page</a> and he also tweets prolifically as <a href="http://twitter.com/ryanbigg">@ryanbigg</a>. + Ryan Bigg works as a Rails developer at <a href="http://marketplacer.com">Marketplacer</a> and has been working with Rails since 2006. He's the author of <a href="https://leanpub.com/multi-tenancy-rails">Multi Tenancy With Rails</a> and co-author of <a href="http://manning.com/bigg2">Rails 4 in Action</a>. He's written many gems which can be seen on <a href="https://github.com/radar">his GitHub page</a> and he also tweets prolifically as <a href="http://twitter.com/ryanbigg">@ryanbigg</a>. <% end %> <%= author('Oscar Del Ben', 'oscardelben', 'oscardelben.jpg') do %> diff --git a/guides/source/debugging_rails_applications.md b/guides/source/debugging_rails_applications.md index dc1df8f229..44434c164b 100644 --- a/guides/source/debugging_rails_applications.md +++ b/guides/source/debugging_rails_applications.md @@ -502,7 +502,7 @@ current context: (byebug) instance_variables [:@_action_has_layout, :@_routes, :@_headers, :@_status, :@_request, - :@_response, :@_env, :@_prefixes, :@_lookup_context, :@_action_name, + :@_response, :@_prefixes, :@_lookup_context, :@_action_name, :@_response_body, :@marked_for_same_origin_verification, :@_config] ``` @@ -533,7 +533,7 @@ And then ask again for the instance_variables: ``` (byebug) instance_variables [:@_action_has_layout, :@_routes, :@_headers, :@_status, :@_request, - :@_response, :@_env, :@_prefixes, :@_lookup_context, :@_action_name, + :@_response, :@_prefixes, :@_lookup_context, :@_action_name, :@_response_body, :@marked_for_same_origin_verification, :@_config, :@articles] ``` diff --git a/guides/source/documents.yaml b/guides/source/documents.yaml index 9145aee009..4473eba478 100644 --- a/guides/source/documents.yaml +++ b/guides/source/documents.yaml @@ -122,6 +122,10 @@ url: autoloading_and_reloading_constants.html description: This guide documents how autoloading and reloading constants work. - + name: "Caching with Rails: An Overview" + url: caching_with_rails.html + description: This guide is an introduction to speeding up your Rails application with caching. + - name: Active Support Instrumentation work_in_progress: true url: active_support_instrumentation.html diff --git a/guides/source/form_helpers.md b/guides/source/form_helpers.md index 8f7d97844e..84a8d695cb 100644 --- a/guides/source/form_helpers.md +++ b/guides/source/form_helpers.md @@ -211,9 +211,8 @@ IMPORTANT: The search, telephone, date, time, color, datetime, datetime-local, month, week, URL, email, number and range inputs are HTML5 controls. If you require your app to have a consistent experience in older browsers, you will need an HTML5 polyfill (provided by CSS and/or JavaScript). -There is definitely [no shortage of solutions for this](https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills), although a couple of popular tools at the moment are -[Modernizr](http://www.modernizr.com/) and [yepnope](http://yepnopejs.com/), -which provide a simple way to add functionality based on the presence of +There is definitely [no shortage of solutions for this](https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills), although a popular tool at the moment is +[Modernizr](http://www.modernizr.com/), which provides a simple way to add functionality based on the presence of detected HTML5 features. TIP: If you're using password input fields (for any purpose), you might want to configure your application to prevent those parameters from being logged. You can learn about this in the [Security Guide](security.html#logging). diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md index 400383cfb5..ef66b75ec1 100644 --- a/guides/source/getting_started.md +++ b/guides/source/getting_started.md @@ -23,10 +23,12 @@ application from scratch. It does not assume that you have any prior experience with Rails. However, to get the most out of it, you need to have some prerequisites installed: -* The [Ruby](https://www.ruby-lang.org/en/downloads) language version 2.2.2 or newer. -* Right version of [Development Kit](http://rubyinstaller.org/downloads/), if you are using Windows -* The [RubyGems](https://rubygems.org) packaging system, which is installed with Ruby - versions 1.9 and later. To learn more about RubyGems, please read the [RubyGems Guides](http://guides.rubygems.org). +* The [Ruby](https://www.ruby-lang.org/en/downloads) language version 2.2.2 or newer. +* Right version of [Development Kit](http://rubyinstaller.org/downloads/), if you + are using Windows. +* The [RubyGems](https://rubygems.org) packaging system, which is installed with + Ruby by default. To learn more about RubyGems, please read the + [RubyGems Guides](http://guides.rubygems.org). * A working installation of the [SQLite3 Database](https://www.sqlite.org). Rails is a web application framework running on the Ruby programming language. @@ -35,7 +37,6 @@ curve diving straight into Rails. There are several curated lists of online reso for learning Ruby: * [Official Ruby Programming Language website](https://www.ruby-lang.org/en/documentation/) -* [reSRC's List of Free Programming Books](http://resrc.io/list/10/list-of-free-programming-books/#ruby) Be aware that some resources, while still excellent, cover versions of Ruby as old as 1.6, and commonly 1.8, and will not include some syntax that you will see in day-to-day @@ -90,17 +91,17 @@ Open up a command line prompt. On Mac OS X open Terminal.app, on Windows choose dollar sign `$` should be run in the command line. Verify that you have a current version of Ruby installed: +```bash +$ ruby -v +ruby 2.2.2p95 +``` + TIP: A number of tools exist to help you quickly install Ruby and Ruby on Rails on your system. Windows users can use [Rails Installer](http://railsinstaller.org), while Mac OS X users can use [Tokaido](https://github.com/tokaido/tokaidoapp). For more installation methods for most Operating Systems take a look at [ruby-lang.org](https://www.ruby-lang.org/en/documentation/installation/). -```bash -$ ruby -v -ruby 2.2.2p95 -``` - Many popular UNIX-like OSes ship with an acceptable version of SQLite3. On Windows, if you installed Rails through Rails Installer, you already have SQLite installed. Others can find installation instructions @@ -164,7 +165,7 @@ of the files and folders that Rails created by default: | File/Folder | Purpose | | ----------- | ------- | |app/|Contains the controllers, models, views, helpers, mailers and assets for your application. You'll focus on this folder for the remainder of this guide.| -|bin/|Contains the rails script that starts your app and can contain other scripts you use to setup, deploy or run your application.| +|bin/|Contains the rails script that starts your app and can contain other scripts you use to setup, update, deploy or run your application.| |config/|Configure your application's routes, database, and more. This is covered in more detail in [Configuring Rails Applications](configuring.html).| |config.ru|Rack configuration for Rack based servers used to start the application.| |db/|Contains your current database schema, as well as the database migrations.| diff --git a/guides/source/routing.md b/guides/source/routing.md index 52f11f92bd..e4799d93fa 100644 --- a/guides/source/routing.md +++ b/guides/source/routing.md @@ -83,7 +83,9 @@ Rails would dispatch that request to the `destroy` method on the `photos` contro ### CRUD, Verbs, and Actions -In Rails, a resourceful route provides a mapping between HTTP verbs and URLs to controller actions. By convention, each action also maps to particular CRUD operations in a database. A single entry in the routing file, such as: +In Rails, a resourceful route provides a mapping between HTTP verbs and URLs to +controller actions. By convention, each action also maps to a specific CRUD +operation in a database. A single entry in the routing file, such as: ```ruby resources :photos @@ -615,6 +617,8 @@ get 'photos/:id', to: 'photos#show', defaults: { format: 'jpg' } Rails would match `photos/12` to the `show` action of `PhotosController`, and set `params[:format]` to `"jpg"`. +NOTE: You cannot override defaults via query parameters - this is for security reasons. The only defaults that can be overridden are dynamic segments via substitution in the URL path. + ### Naming Routes You can specify a name for any route using the `:as` option: @@ -793,7 +797,11 @@ get '/stories/:name', to: redirect { |path_params, req| "/articles/#{path_params get '/stories', to: redirect { |path_params, req| "/articles/#{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. +Please note that default 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. You can use the `:status` option to change the response status: + +```ruby +get '/stories/:name', to: redirect('/articles/%{name}', status: 302) +``` 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. @@ -1087,6 +1095,20 @@ edit_videos GET /videos/:identifier/edit(.:format) videos#edit Video.find_by(identifier: params[:identifier]) ``` +You can override `ActiveRecord::Base#to_param` of a related model to construct +an URL: + +```ruby +class Video < ActiveRecord::Base + def to_param + identifier + end +end + +video = Video.find_by(identifier: "Roman-Holiday") +edit_videos_path(video) # => "/videos/Roman-Holiday" +``` + Inspecting and Testing Routes ----------------------------- diff --git a/guides/source/security.md b/guides/source/security.md index 485b108d12..c701027479 100644 --- a/guides/source/security.md +++ b/guides/source/security.md @@ -93,9 +93,16 @@ Rails 2 introduced a new default session storage, CookieStore. CookieStore saves * Cookies imply a strict size limit of 4kB. This is fine as you should not store large amounts of data in a session anyway, as described before. _Storing the current user's database id in a session is usually ok_. -* The client can see everything you store in a session, because it is stored in clear-text (actually Base64-encoded, so not encrypted). So, of course, _you don't want to store any secrets here_. To prevent session hash tampering, a digest is calculated from the session with a server-side secret and inserted into the end of the cookie. +* The client can see everything you store in a session, because it is stored in clear-text (actually Base64-encoded, so not encrypted). So, of course, _you don't want to store any secrets here_. To prevent session hash tampering, a digest is calculated from the session with a server-side secret (`secrets.secret_token`) and inserted into the end of the cookie. -That means the security of this storage depends on this secret (and on the digest algorithm, which defaults to SHA1, for compatibility). So _don't use a trivial secret, i.e. a word from a dictionary, or one which is shorter than 30 characters_. +However, since Rails 4, the default store is EncryptedCookieStore. With +EncryptedCookieStore the session is encrypted before being stored in a cookie. +This prevents the user from accessing and tampering the content of the cookie. +Thus the session becomes a more secure place to store data. The encryption is +done using a server-side secret key `secrets.secret_key_base` stored in +`config/secrets.yml`. + +That means the security of this storage depends on this secret (and on the digest algorithm, which defaults to SHA1, for compatibility). So _don't use a trivial secret, i.e. a word from a dictionary, or one which is shorter than 30 characters, use `rake secret` instead_. `secrets.secret_key_base` is used for specifying a key which allows sessions for the application to be verified against a known secure key to prevent tampering. Applications get `secrets.secret_key_base` initialized to a random key present in `config/secrets.yml`, e.g.: diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md index 17309d4b47..743241d7a0 100644 --- a/guides/source/upgrading_ruby_on_rails.md +++ b/guides/source/upgrading_ruby_on_rails.md @@ -75,7 +75,7 @@ warning by adding the following configuration to your `config/application.rb`: See [#17227](https://github.com/rails/rails/pull/17227) for more details. -### ActiveJob jobs now inherent from ApplicationJob by default +### ActiveJob jobs now inherit from ApplicationJob by default In Rails 4.2 an ActiveJob inherits from `ActiveJob::Base`. In Rails 5.0 this behavior has changed to now inherit from `ApplicationJob`. diff --git a/guides/source/working_with_javascript_in_rails.md b/guides/source/working_with_javascript_in_rails.md index f3d3a83afc..1c42ff2914 100644 --- a/guides/source/working_with_javascript_in_rails.md +++ b/guides/source/working_with_javascript_in_rails.md @@ -258,7 +258,7 @@ this generates ```html <form action="/articles/1" class="button_to" data-remote="true" method="post"> - <div><input type="submit" value="An article"></div> + <input type="submit" value="An article" /> </form> ``` @@ -357,7 +357,7 @@ This gem uses Ajax to speed up page rendering in most applications. Turbolinks attaches a click handler to all `<a>` on the page. If your browser supports -[PushState](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history#The_pushState()_method), +[PushState](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history#The_pushState%28%29_method), 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 |