Skip to content

Commit

Permalink
Merge branch 'master' of github.com:lifo/docrails
Browse files Browse the repository at this point in the history
Conflicts:
	activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
  • Loading branch information
vijaydev committed Sep 9, 2012
2 parents 6107407 + 2db79dc commit cb524dc
Show file tree
Hide file tree
Showing 19 changed files with 149 additions and 74 deletions.
2 changes: 1 addition & 1 deletion actionpack/lib/action_controller/caching/sweeping.rb
@@ -1,6 +1,6 @@
module ActionController #:nodoc:
module Caching
# Sweepers are the terminators of the caching world and responsible for expiring caches when model objects change.
# Sweepers are the terminators of the caching world and responsible for expiring caches when Active Record objects change.
# They do this by being half-observers, half-filters and implementing callbacks for both roles. A Sweeper example:
#
# class ListSweeper < ActionController::Caching::Sweeper
Expand Down
6 changes: 3 additions & 3 deletions activemodel/lib/active_model/validations/validates.rb
Expand Up @@ -94,10 +94,10 @@ module ClassMethods
# validates :token, uniqueness: true, strict: TokenGenerationException
#
#
# Finally, the options +:if+, +:unless+, +:on+, +:allow_blank+, +:allow_nil+
# and +:strict+ can be given to one specific validator, as a hash:
# Finally, the options +:if+, +:unless+, +:on+, +:allow_blank+, +:allow_nil+, +:strict+
# and +:message+ can be given to one specific validator, as a hash:
#
# validates :password, presence: { if: :password_required? }, confirmation: true
# validates :password, presence: { if: :password_required?, message: 'is forgotten.' }, confirmation: true
def validates(*attributes)
defaults = attributes.extract_options!.dup
validations = defaults.slice!(*_validates_default_keys)
Expand Down
Expand Up @@ -494,7 +494,7 @@ def checkout_and_verify(c)
#
# Normally there is only a single ConnectionHandler instance, accessible via
# ActiveRecord::Base.connection_handler. Active Record models use this to
# determine that connection pool that they should use.
# determine the connection pool that they should use.
class ConnectionHandler
def initialize
@owner_to_pool = Hash.new { |h,k| h[k] = {} }
Expand Down
2 changes: 1 addition & 1 deletion activerecord/lib/active_record/store.rb
Expand Up @@ -82,7 +82,7 @@ def initialize_store_attribute(store_attribute)
attribute
end

class IndifferentCoder
class IndifferentCoder # :nodoc:
def initialize(coder_or_class_name)
@coder =
if coder_or_class_name.respond_to?(:load) && coder_or_class_name.respond_to?(:dump)
Expand Down
14 changes: 14 additions & 0 deletions guides/source/4_0_release_notes.textile
Expand Up @@ -116,6 +116,20 @@ h3. Action Mailer

* Asynchronously send messages via the Rails Queue.

* Delivery Options (such as SMTP Settings) can now be set dynamically per mailer action.

Delivery options are set via <tt>:delivery_method_options</tt> key on mail.

<ruby>
def welcome_mailer(user,company)
mail to: user.email,
subject: "Welcome!",
delivery_method_options: {user_name: company.smtp_user,
password: company.smtp_password,
address: company.smtp_server}
end
</ruby>

h3. Action Pack

h4. Action Controller
Expand Down
15 changes: 15 additions & 0 deletions guides/source/action_mailer_basics.textile
Expand Up @@ -410,6 +410,21 @@ end

The above will send a multipart email with an attachment, properly nested with the top level being <tt>multipart/mixed</tt> and the first part being a <tt>multipart/alternative</tt> containing the plain text and HTML email messages.

h5. Sending Emails with Dynamic Delivery Options

If you wish to override the default delivery options (e.g. SMTP credentials) while delivering emails, you can do this using +delivery_method_options+ in the mailer action.

<ruby>
class UserMailer < ActionMailer::Base
def welcome_email(user,company)
@user = user
@url = user_url(@user)
delivery_options = { user_name: company.smtp_user, password: company.smtp_password, address: company.smtp_host }
mail(to: user.email, subject: "Please see the Terms and Conditions attached", delivery_method_options: delivery_options)
end
end
</ruby>

h3. Receiving Emails

Receiving and parsing emails with Action Mailer can be a rather complex endeavor. Before your email reaches your Rails app, you would have had to configure your system to somehow forward emails to your app, which needs to be listening for that. So, to receive emails in your Rails app you'll need to:
Expand Down
2 changes: 1 addition & 1 deletion guides/source/action_view_overview.textile
Expand Up @@ -1211,7 +1211,7 @@ Sample usage (selecting the associated Authors for an instance of Post, +@post+)
collection_check_boxes(:post, :author_ids, Author.all, :id, :name_with_initial)
</ruby>

If <tt>@post.author_ids</tt> is [1], this would return:
If <tt>@post.author_ids</tt> is <tt><notextile>[1]</notextile></tt>, this would return:

<html>
<input id="post_author_ids_1" name="post[author_ids][]" type="checkbox" value="1" checked="checked" />
Expand Down
38 changes: 31 additions & 7 deletions guides/source/active_record_querying.textile
Expand Up @@ -266,7 +266,7 @@ SELECT * FROM clients WHERE (clients.id IN (1,10))

WARNING: <tt>Model.find(array_of_primary_key)</tt> will raise an +ActiveRecord::RecordNotFound+ exception unless a matching record is found for <strong>all</strong> of the supplied primary keys.

h5. take
h5(#take-n-objects). take

<tt>Model.take(limit)</tt> retrieves the first number of records specified by +limit+ without any explicit ordering:

Expand All @@ -282,7 +282,7 @@ The SQL equivalent of the above is:
SELECT * FROM clients LIMIT 2
</sql>

h5. first
h5(#first-n-objects). first

<tt>Model.first(limit)</tt> finds the first number of records specified by +limit+ ordered by primary key:

Expand All @@ -298,7 +298,7 @@ The SQL equivalent of the above is:
SELECT * FROM clients LIMIT 2
</sql>

h5. last
h5(#last-n-objects). last

<tt>Model.last(limit)</tt> finds the number of records specified by +limit+ ordered by primary key in descending order:

Expand Down Expand Up @@ -1144,30 +1144,54 @@ category.posts.created_before(time)

h4. Applying a default scope

If we wish for a scope to be applied across all queries to the model we can use the +default_scope+ method within the model itself.
If we wish for a scope to be applied across all queries to the model we can use the
+default_scope+ method within the model itself.

<ruby>
class Client < ActiveRecord::Base
default_scope { where("removed_at IS NULL") }
end
</ruby>

When queries are executed on this model, the SQL query will now look something like this:
When queries are executed on this model, the SQL query will now look something like
this:

<sql>
SELECT * FROM clients WHERE removed_at IS NULL
</sql>

If you need to do more complex things with a default scope, you can alternatively
define it as a class method:

<ruby>
class Client < ActiveRecord::Base
def self.default_scope
# Should return an ActiveRecord::Relation.
end
end
</ruby>

h4. Removing all scoping

If we wish to remove scoping for any reason we can use the +unscoped+ method. This is especially useful if a +default_scope+ is specified in the model and should not be applied for this particular query.
If we wish to remove scoping for any reason we can use the +unscoped+ method. This is
especially useful if a +default_scope+ is specified in the model and should not be
applied for this particular query.

<ruby>
Client.unscoped.all
</ruby>

This method removes all scoping and will do a normal query on the table.

Note that chaining +unscoped+ with a +scope+ does not work. In these cases, it is
recommended that you use the block form of +unscoped+:

<ruby>
Client.unscoped {
Client.created_before(Time.zome.now)
}
</ruby>

h3. Dynamic Finders

For every field (also known as an attribute) you define in your table, Active Record provides a finder method. If you have a field called +first_name+ on your +Client+ model for example, you get +find_by_first_name+ and +find_all_by_first_name+ for free from Active Record. If you have a +locked+ field on the +Client+ model, you also get +find_by_locked+ and +find_all_by_locked+ methods.
Expand Down Expand Up @@ -1218,7 +1242,7 @@ Client.find_or_create_by_first_name(:first_name => "Andy", :locked => false)

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.

h4. +first_or_create!+
h4(#first_or_create_bang). +first_or_create!+

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

Expand Down
2 changes: 2 additions & 0 deletions guides/source/association_basics.textile
Expand Up @@ -88,6 +88,8 @@ end

!images/belongs_to.png(belongs_to Association Diagram)!

NOTE: +belongs_to+ associations _must_ use the singular term. If you used the pluralized form in the above example for the +customer+ association in the +Order+ model, you would be told that there was an "uninitialized constant Order::Customers". This is because Rails automatically infers the class name from the association name. If the association name is wrongly pluralized, then the inferred class will be wrongly pluralized too.

h4. The +has_one+ Association

A +has_one+ association also sets up a one-to-one connection with another model, but with somewhat different semantics (and consequences). This association indicates that each instance of a model contains or possesses one instance of another model. For example, if each supplier in your application has only one account, you'd declare the supplier model like this:
Expand Down
19 changes: 16 additions & 3 deletions guides/source/caching_with_rails.textile
Expand Up @@ -173,7 +173,9 @@ expire_fragment('all_available_products')

h4. Sweepers

Cache sweeping is a mechanism which allows you to get around having a ton of +expire_{page,action,fragment}+ calls in your code. It does this by moving all the work required to expire cached content into an +ActionController::Caching::Sweeper+ subclass. This class is an observer and looks for changes to an object via callbacks, and when a change occurs it expires the caches associated with that object in an around or after filter.
Cache sweeping is a mechanism which allows you to get around having a ton of +expire_{page,action,fragment}+ calls in your code. It does this by moving all the work required to expire cached content into an +ActionController::Caching::Sweeper+ subclass. This class is an observer and looks for changes to an Active Record object via callbacks, and when a change occurs it expires the caches associated with that object in an around or after filter.

TIP: Sweepers rely on the use of Active Record and Active Record Observers. The object you are observing must be an Active Record model.

Continuing with our Product controller example, we could rewrite it with a sweeper like this:

Expand Down Expand Up @@ -353,7 +355,7 @@ Note that the cache will grow until the disk is full unless you periodically cle

h4. ActiveSupport::Cache::MemCacheStore

This cache store uses Danga's +memcached+ server to provide a centralized cache for your application. Rails uses the bundled +memcache-client+ gem by default. This is currently the most popular cache store for production websites. It can be used to provide a single, shared cache cluster with very a high performance and redundancy.
This cache store uses Danga's +memcached+ server to provide a centralized cache for your application. Rails uses the bundled +dalli+ gem by default. This is currently the most popular cache store for production websites. It can be used to provide a single, shared cache cluster with very a high performance and redundancy.

When initializing the cache, you need to specify the addresses for all memcached servers in your cluster. If none is specified, it will assume memcached is running on the local host on the default port, but this is not an ideal set up for larger sites.

Expand Down Expand Up @@ -439,7 +441,7 @@ class ProductsController < ApplicationController

# If the request is stale according to the given timestamp and etag value
# (i.e. it needs to be processed again) then execute this block
if stale?(:last_modified => @product.updated_at.utc, :etag => @product)
if stale?(:last_modified => @product.updated_at.utc, :etag => @product.cache_key)
respond_to do |wants|
# ... normal response processing
end
Expand All @@ -453,6 +455,17 @@ class ProductsController < ApplicationController
end
</ruby>

Instead of a options hash, you can also simply pass in a model, Rails will use the +updated_at+ and +cache_key+ methods for setting +last_modified+ and +etag+:

<ruby>
class ProductsController < ApplicationController
def show
@product = Product.find(params[:id])
respond_with(@product) if stale?(@product)
end
end
</ruby>

If you don't have any special response processing and are using the default rendering mechanism (i.e. you're not using respond_to or calling render yourself) then you’ve got an easy helper in fresh_when:

<ruby>
Expand Down
2 changes: 1 addition & 1 deletion guides/source/configuring.textile
Expand Up @@ -388,7 +388,7 @@ And can reference in the view with the following code:

<erb>
<%= render @post %>
<erb>
</erb>

The default setting is +true+, which uses the partial at +/admin/posts/_post.erb+. Setting the value to +false+ would render +/posts/_post.erb+, which is the same behavior as rendering from a non-namespaced controller such as +PostsController+.

Expand Down
11 changes: 11 additions & 0 deletions guides/source/debugging_rails_applications.textile
Expand Up @@ -191,6 +191,17 @@ Completed in 0.01224 (81 reqs/sec) | DB: 0.00044 (3%) | 302 Found [http://localh

Adding extra logging like this makes it easy to search for unexpected or unusual behavior in your logs. If you add extra logging, be sure to make sensible use of log levels, to avoid filling your production logs with useless trivia.

h4. Tagged Logging

When running multi-user, multi-account applications, it’s often useful to be able to filter the logs using some custom rules. +TaggedLogging+ in Active Support helps in doing exactly that by stamping log lines with subdomains, request ids, and anything else to aid debugging such applications.

<ruby>
logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
logger.tagged("BCX") { logger.info "Stuff" } # Logs "[BCX] Stuff"
logger.tagged("BCX", "Jason") { logger.info "Stuff" } # Logs "[BCX] [Jason] Stuff"
logger.tagged("BCX") { logger.tagged("Jason") { logger.info "Stuff" } } # Logs "[BCX] [Jason] Stuff"
</ruby>

h3. Debugging with the +debugger+ gem

When your code is behaving in unexpected ways, you can try printing to logs or the console to diagnose the problem. Unfortunately, there are times when this sort of error tracking is not effective in finding the root cause of a problem. When you actually need to journey into your running source code, the debugger is your best companion.
Expand Down

0 comments on commit cb524dc

Please sign in to comment.