Merge branch 'master' of github.com:lifo/docrails

Conflicts:
	activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
This commit is contained in:
Vijay Dev 2012-09-09 17:38:47 +05:30
commit cb524dc1d7
19 changed files with 149 additions and 74 deletions

View File

@ -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

View File

@ -94,10 +94,10 @@ module ActiveModel
# 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)

View File

@ -494,7 +494,7 @@ module ActiveRecord
#
# 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] = {} }

View File

@ -82,7 +82,7 @@ module ActiveRecord
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)

View File

@ -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

View File

@ -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:

View File

@ -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" />

View File

@ -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:
@ -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:
@ -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:
@ -1144,7 +1144,8 @@ 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
@ -1152,15 +1153,29 @@ class Client < ActiveRecord::Base
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
@ -1168,6 +1183,15 @@ Client.unscoped.all
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.
@ -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

View File

@ -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:

View File

@ -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:
@ -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.
@ -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
@ -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 youve got an easy helper in fresh_when:
<ruby>

View File

@ -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+.

View File

@ -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, its 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.

View File

@ -26,7 +26,7 @@ It's important to keep in mind at all times that the application should *always*
To see demonstrations of other engines, check out "Devise":https://github.com/plataformatec/devise, an engine that provides authentication for its parent applications, or "Forem":https://github.com/radar/forem, an engine that provides forum functionality. There's also "Spree":https://github.com/spree/spree which provides an e-commerce platform, and "RefineryCMS":https://github.com/resolve/refinerycms, a CMS engine.
Finally, engines would not have be possible without the work of James Adam, Piotr Sarnacki, the Rails Core Team, and a number of other people. If you ever meet them, don't forget to say thanks!
Finally, engines would not have been possible without the work of James Adam, Piotr Sarnacki, the Rails Core Team, and a number of other people. If you ever meet them, don't forget to say thanks!
h3. Generating an engine
@ -42,9 +42,9 @@ The full list of options for the plugin generator may be seen by typing:
$ rails plugin --help
</shell>
The +--full+ option tells the plugin generator that you want to create an engine (which is a mountable plugin, hence the option name), creating the basic directory structure of an engine by providing things such as the foundations of an +app+ folder, as well a +config/routes.rb+ file. This generator also provides a file at +lib/blorgh/engine.rb+ which is identical in function to an application's +config/application.rb+ file.
The +--full+ option tells the plugin generator that you want to create an engine, creating the basic directory structure of an engine by providing things such as an +app+ directory and a +config/routes.rb+ file. This generator also provides a file at +lib/blorgh/engine.rb+ which is identical in function to a standard Rails application's +config/application.rb+ file.
The +--mountable+ option tells the generator to mount the engine inside the dummy testing application located at +test/dummy+ inside the engine. It does this by placing this line in to the dummy application's +config/routes.rb+ file, located at +test/dummy/config/routes.rb+ inside the engine:
The +--mountable+ option tells the generator to mount the engine inside the dummy testing application located at +test/dummy+. It does this by placing this line into the dummy application's routes file at +test/dummy/config/routes.rb+:
<ruby>
mount Blorgh::Engine, :at => "blorgh"
@ -54,7 +54,7 @@ h4. Inside an engine
h5. Critical files
At the root of this brand new engine's directory, lives a +blorgh.gemspec+ file. When you include the engine into the application later on, you will do so with this line in a Rails application's +Gemfile+:
At the root of this brand new engine's directory lives a +blorgh.gemspec+ file. When you include the engine into an application later on, you will do so with this line in the Rails application's +Gemfile+:
<ruby>
gem 'blorgh', :path => "vendor/engines/blorgh"
@ -69,7 +69,7 @@ module Blorgh
end
</ruby>
TIP: Some engines choose to use this file to put global configuration options for their engine. It's a relatively good idea, and so if you're wanting offer configuration options, the file where your engine's +module+ is defined is perfect for that. Place the methods inside the module and you'll be good to go.
TIP: Some engines choose to use this file to put global configuration options for their engine. It's a relatively good idea, and so if you want to offer configuration options, the file where your engine's +module+ is defined is perfect for that. Place the methods inside the module and you'll be good to go.
Within +lib/blorgh/engine.rb+ is the base class for the engine:
@ -83,25 +83,25 @@ end
By inheriting from the +Rails::Engine+ class, this gem notifies Rails that there's an engine at the specified path, and will correctly mount the engine inside the application, performing tasks such as adding the +app+ directory of the engine to the load path for models, mailers, controllers and views.
The +isolate_namespace+ method here deserves special notice. This call is responsible for isolating the controllers, models, routes and other things into their own namespace, away from similar components inside the application. Without this, there is a possibility that the engine's components could "leak" into the application, causing unwanted disruption, or that important engine components could be overridden by similarly named things within the application. One of the examples of such conflicts are helpers. Without calling +isolate_namespace+, engine's helpers would be included in application's controllers.
The +isolate_namespace+ method here deserves special notice. This call is responsible for isolating the controllers, models, routes and other things into their own namespace, away from similar components inside the application. Without this, there is a possibility that the engine's components could "leak" into the application, causing unwanted disruption, or that important engine components could be overridden by similarly named things within the application. One of the examples of such conflicts are helpers. Without calling +isolate_namespace+, engine's helpers would be included in an application's controllers.
NOTE: It is *highly* recommended that the +isolate_namespace+ line be left within the +Engine+ class definition. Without it, classes generated in an engine *may* conflict with an application.
What this isolation of the namespace means is that a model generated by a call to +rails g model+ such as +rails g model post+ wouldn't be called +Post+, but instead be namespaced and called +Blorgh::Post+. In addition to this, the table for the model is namespaced, becoming +blorgh_posts+, rather than simply +posts+. Similar to the model namespacing, a controller called +PostsController+ would be +Blorgh::Postscontroller+ and the views for that controller would not be at +app/views/posts+, but rather +app/views/blorgh/posts+. Mailers would be namespaced as well.
What this isolation of the namespace means is that a model generated by a call to +rails g model+ such as +rails g model post+ won't be called +Post+, but instead be namespaced and called +Blorgh::Post+. In addition, the table for the model is namespaced, becoming +blorgh_posts+, rather than simply +posts+. Similar to the model namespacing, a controller called +PostsController+ becomes +Blorgh::PostsController+ and the views for that controller will not be at +app/views/posts+, but +app/views/blorgh/posts+ instead. Mailers are namespaced as well.
Finally, routes will also be isolated within the engine. This is one of the most important parts about namespacing, and is discussed later in the "Routes":#routes section of this guide.
h5. +app+ directory
Inside the +app+ directory there is the standard +assets+, +controllers+, +helpers+, +mailers+, +models+ and +views+ directories that you should be familiar with from an application. The +helpers+, +mailers+ and +models+ directories are empty and so aren't described in this section. We'll look more into models in a future section, when we're writing the engine.
Inside the +app+ directory are the standard +assets+, +controllers+, +helpers+, +mailers+, +models+ and +views+ directories that you should be familiar with from an application. The +helpers+, +mailers+ and +models+ directories are empty and so aren't described in this section. We'll look more into models in a future section, when we're writing the engine.
Within the +app/assets+ directory, there is the +images+, +javascripts+ and +stylesheets+ directories which, again, you should be familiar with due to their similarities of an application. One difference here however is that each directory contains a sub-directory with the engine name. Because this engine is going to be namespaced, its assets should be too.
Within the +app/assets+ directory, there are the +images+, +javascripts+ and +stylesheets+ directories which, again, you should be familiar with due to their similarity to an application. One difference here however is that each directory contains a sub-directory with the engine name. Because this engine is going to be namespaced, its assets should be too.
Within the +app/controllers+ directory there is a +blorgh+ directory and inside that a file called +application_controller.rb+. This file will provide any common functionality for the controllers of the engine. The +blorgh+ directory is where the other controllers for the engine will go. By placing them within this namespaced directory, you prevent them from possibly clashing with identically-named controllers within other engines or even within the application.
NOTE: The +ApplicationController+ class is called as such inside an engine -- rather than +EngineController+ -- mainly due to that if you consider that an engine is really just a mini-application, it makes sense. You should also be able to convert an application to an engine with relatively little pain, and this is just one of the ways to make that process easier, albeit however so slightly.
NOTE: The +ApplicationController+ class inside an engine is named just like a Rails application in order to make it easier for you to convert your applications into engines.
Lastly, the +app/views+ directory contains a +layouts+ folder which contains file at +blorgh/application.html.erb+ which allows you to specify a layout for the engine. If this engine is to be used as a stand-alone engine, then you would add any customization to its layout in this file, rather than the applications +app/views/layouts/application.html.erb+ file.
Lastly, the +app/views+ directory contains a +layouts+ folder which contains a file at +blorgh/application.html.erb+ which allows you to specify a layout for the engine. If this engine is to be used as a stand-alone engine, then you would add any customization to its layout in this file, rather than the application's +app/views/layouts/application.html.erb+ file.
If you don't want to force a layout on to users of the engine, then you can delete this file and reference a different layout in the controllers of your engine.
@ -113,7 +113,7 @@ This directory contains one file, +script/rails+, which enables you to use the +
rails g model
</shell>
Keeping in mind, of course, that anything generated with these commands inside an engine that has +isolate_namespace+ inside the Engine class will be namespaced.
Keeping in mind, of course, that anything generated with these commands inside an engine that has +isolate_namespace+ inside the +Engine+ class will be namespaced.
h5. +test+ directory
@ -125,13 +125,13 @@ Rails.application.routes.draw do
end
</ruby>
This line mounts the engine at the path of +/blorgh+, which will make it accessible through the application only at that path.
This line mounts the engine at the path +/blorgh+, which will make it accessible through the application only at that path.
Also in the test directory is the +test/integration+ directory, where integration tests for the engine should be placed. Other directories can be created in the +test+ directory also. For example, you may wish to create a +test/unit+ directory for your unit tests.
h3. Providing engine functionality
The engine that this guide covers will provide posting and commenting functionality and follows a similar thread to the "Getting Started Guide":getting_started.html, with some new twists.
The engine that this guide covers provides posting and commenting functionality and follows a similar thread to the "Getting Started Guide":getting_started.html, with some new twists.
h4. Generating a post resource
@ -189,7 +189,7 @@ end
Note here that the routes are drawn upon the +Blorgh::Engine+ object rather than the +YourApp::Application+ class. This is so that the engine routes are confined to the engine itself and can be mounted at a specific point as shown in the "test directory":#test-directory section. This is also what causes the engine's routes to be isolated from those routes that are within the application. This is discussed further in the "Routes":#routes section of this guide.
Next, the +scaffold_controller+ generator is invoked, generating a controlled called +Blorgh::PostsController+ (at +app/controllers/blorgh/posts_controller.rb+) and its related views at +app/views/blorgh/posts+. This generator also generates a functional test for the controller (+test/functional/blorgh/posts_controller_test.rb+) and a helper (+app/helpers/blorgh/posts_controller.rb+).
Next, the +scaffold_controller+ generator is invoked, generating a controller called +Blorgh::PostsController+ (at +app/controllers/blorgh/posts_controller.rb+) and its related views at +app/views/blorgh/posts+. This generator also generates a functional test for the controller (+test/functional/blorgh/posts_controller_test.rb+) and a helper (+app/helpers/blorgh/posts_controller.rb+).
Everything this generator has created is neatly namespaced. The controller's class is defined within the +Blorgh+ module:
@ -361,7 +361,7 @@ Missing partial blorgh/comments/comment with {:handlers=>[:erb, :builder], :form
* "/Users/ryan/Sites/side_projects/blorgh/app/views"
</plain>
The engine is unable to find the partial required for rendering the comments. Rails has looked firstly in the application's (+test/dummy+) +app/views+ directory and then in the engine's +app/views+ directory. When it can't find it, it will throw this error. The engine knows to look for +blorgh/comments/comment+ because the model object it is receiving is from the +Blorgh::Comment+ class.
The engine is unable to find the partial required for rendering the comments. Rails looks first in the application's (+test/dummy+) +app/views+ directory and then in the engine's +app/views+ directory. When it can't find it, it will throw this error. The engine knows to look for +blorgh/comments/comment+ because the model object it is receiving is from the +Blorgh::Comment+ class.
This partial will be responsible for rendering just the comment text, for now. Create a new file at +app/views/blorgh/comments/_comment.html.erb+ and put this line inside it:
@ -375,7 +375,7 @@ That completes the comment function of the blogging engine. Now it's time to use
h3. Hooking into an application
Using an engine within an application is very easy. This section covers how to mount the engine into an application and the initial setup required for it, as well as linking the engine to a +User+ class provided by the application to provide ownership for posts and comments within the engine.
Using an engine within an application is very easy. This section covers how to mount the engine into an application and the initial setup required, as well as linking the engine to a +User+ class provided by the application to provide ownership for posts and comments within the engine.
h4. Mounting the engine
@ -391,18 +391,12 @@ Usually, specifying the engine inside the Gemfile would be done by specifying it
gem 'devise'
</ruby>
Because the +blorgh+ engine is still under development, it will need to have a +:path+ option for its +Gemfile+ specification:
However, because you are developing the +blorgh+ engine on your local machine, you will need to specify the +:path+ option in your +Gemfile+:
<ruby>
gem 'blorgh', :path => "/path/to/blorgh"
</ruby>
If the whole +blorgh+ engine directory is copied to +vendor/engines/blorgh+ then it could be specified in the +Gemfile+ like this:
<ruby>
gem 'blorgh', :path => "vendor/engines/blorgh"
</ruby>
As described earlier, by placing the gem in the +Gemfile+ it will be loaded when Rails is loaded, as it will first require +lib/blorgh.rb+ in the engine and then +lib/blorgh/engine.rb+, which is the file that defines the major pieces of functionality for the engine.
To make the engine's functionality accessible from within an application, it needs to be mounted in that application's +config/routes.rb+ file:
@ -458,7 +452,7 @@ h5. Using a model provided by the application
When an engine is created, it may want to use specific classes from an application to provide links between the pieces of the engine and the pieces of the application. In the case of the +blorgh+ engine, making posts and comments have authors would make a lot of sense.
Usually, an application would have a +User+ class that would provide the objects that would represent the posts' and comments' authors, but there could be a case where the application calls this class something different, such as +Person+. It's because of this reason that the engine should not hardcode the associations to be exactly for a +User+ class, but should allow for some flexibility around what the class is called.
A typical application might have a +User+ class that would be used to represent authors for a post or a comment. But there could be a case where the application calls this class something different, such as +Person+. For this reason, the engine should not hardcode associations specifically for a +User+ class.
To keep it simple in this case, the application will have a class called +User+ which will represent the users of the application. It can be generated using this command inside the application:
@ -536,7 +530,7 @@ Finally, the author's name should be displayed on the post's page. Add this code
</p>
</erb>
By outputting +@post.author+ using the +&lt;%=+ tag the +to_s+ method will be called on the object. By default, this will look quite ugly:
By outputting +@post.author+ using the +&lt;%=+ tag, the +to_s+ method will be called on the object. By default, this will look quite ugly:
<plain>
#<User:0x00000100ccb3b0>
@ -567,7 +561,7 @@ This change does require that the engine is run from a Rails application that ha
h4. Configuring an engine
This section covers firstly how you can make the +user_class+ setting of the Blorgh engine configurable, followed by general configuration tips for the engine.
This section covers how to make the +User+ class configurable, followed by general configuration tips for the engine.
h5. Setting configuration settings in the application
@ -601,7 +595,7 @@ def self.user_class
end
</ruby>
This would then turn the above code for +self.author=+ into this:
This would then turn the above code for +set_author+ into this:
<ruby>
self.author = Blorgh.user_class.find_or_create_by_name(author_name)
@ -621,7 +615,7 @@ WARNING: It's very important here to use the +String+ version of the class, rath
Go ahead and try to create a new post. You will see that it works exactly in the same way as before, except this time the engine is using the configuration setting in +config/initializers/blorgh.rb+ to learn what the class is.
There are now no strict dependencies on what the class is, only what the class's API must be. The engine simply requires this class to define a +find_or_create_by_name+ method which returns an object of that class to be associated with a post when it's created. This object, of course, should have some sort of identifier by which it can be referenced.
There are now no strict dependencies on what the class is, only what the API for the class must be. The engine simply requires this class to define a +find_or_create_by_name+ method which returns an object of that class to be associated with a post when it's created. This object, of course, should have some sort of identifier by which it can be referenced.
h5. General engine configuration
@ -661,11 +655,11 @@ h4. Overriding Models and Controllers
Engine model and controller classes can be extended by open classing them in the main Rails application (since model and controller classes are just Ruby classes that inherit Rails specific functionality). Open classing an Engine class redefines it for use in the main applicaiton. This is usually implemented by using the decorator pattern.
For simple class modifications use Class#class_eval, and for complex class modifications, consider using ActiveSupport::Concern.
For simple class modifications use +Class#class_eval+, and for complex class modifications, consider using +ActiveSupport::Concern+.
h5. Implementing Decorator Pattern Using Class#class_eval
**Adding** Post#time_since_created,
**Adding** +Post#time_since_created+,
<ruby>
# MyApp/app/decorators/models/blorgh/post_decorator.rb
@ -681,12 +675,12 @@ end
# Blorgh/app/models/post.rb
class Post < ActiveRecord::Base
:has_many :comments
has_many :comments
end
</ruby>
**Overriding** Post#summary
**Overriding** +Post#summary+
<ruby>
# MyApp/app/decorators/models/blorgh/post_decorator.rb
@ -702,7 +696,7 @@ end
# Blorgh/app/models/post.rb
class Post < ActiveRecord::Base
:has_many :comments
has_many :comments
def summary
"#{title}"
end
@ -712,10 +706,10 @@ end
h5. Implementing Decorator Pattern Using ActiveSupport::Concern
Using Class#class_eval is great for simple adjustments, but for more complex class modifications, you might want to consider using ActiveSupport::Concern. ["**ActiveSupport::Concern**":http://edgeapi.rubyonrails.org/classes/ActiveSupport/Concern.html] helps manage load order of interlinked dependencies at run time allowing you to significantly modularize your code.
Using +Class#class_eval+ is great for simple adjustments, but for more complex class modifications, you might want to consider using +ActiveSupport::Concern+. ["**ActiveSupport::Concern**":http://edgeapi.rubyonrails.org/classes/ActiveSupport/Concern.html] helps manage the load order of interlinked dependencies at run time allowing you to significantly modularize your code.
**Adding** Post#time_since_created<br/>
**Overriding** Post#summary
**Adding** +Post#time_since_created+<br/>
**Overriding** +Post#summary+
<ruby>
# MyApp/app/models/blorgh/post.rb
@ -781,7 +775,7 @@ When Rails looks for a view to render, it will first look in the +app/views+ dir
In the +blorgh+ engine, there is a currently a file at +app/views/blorgh/posts/index.html.erb+. When the engine is asked to render the view for +Blorgh::PostsController+'s +index+ action, it will first see if it can find it at +app/views/blorgh/posts/index.html.erb+ within the application and then if it cannot it will look inside the engine.
By overriding this view in the application, by simply creating a new file at +app/views/blorgh/posts/index.html.erb+, you can completely change what this view would normally output.
You can override this view in the application by simply creating a new file at +app/views/blorgh/posts/index.html.erb+. Then you can completely change what this view would normally output.
Try this now by creating a new file at +app/views/blorgh/posts/index.html.erb+ and put this content in it:
@ -856,10 +850,10 @@ INFO. Remember that in order to use languages like Sass or CoffeeScript, you sho
h4. Separate Assets & Precompiling
There are some situations where your engine's assets not required by the host application. For example, say that you've created
There are some situations where your engine's assets are not required by the host application. For example, say that you've created
an admin functionality that only exists for your engine. In this case, the host application doesn't need to require +admin.css+
or +admin.js+. Only the gem's admin layout needs these assets. It doesn't make sense for the host app to include +"blorg/admin.css"+ in it's stylesheets. In this situation, you should explicitly define these assets for precompilation.
This tells sprockets to add you engine assets when +rake assets:precompile+ is ran.
This tells sprockets to add your engine assets when +rake assets:precompile+ is ran.
You can define assets for precompilation in +engine.rb+
@ -873,8 +867,7 @@ For more information, read the "Asset Pipeline guide":http://guides.rubyonrails.
h4. Other gem dependencies
Gem dependencies inside an engine should be specified inside the +.gemspec+ file
that's at the root of the engine. The reason for this is because the engine may
Gem dependencies inside an engine should be specified inside the +.gemspec+ file at the root of the engine. The reason for this is because the engine may
be installed as a gem. If dependencies were to be specified inside the +Gemfile+,
these would not be recognised by a traditional gem install and so they would not
be installed, causing the engine to malfunction.
@ -899,7 +892,7 @@ the application. The development dependencies for the gem will only be used when
the tests for the engine are running.
Note that if you want to immediately require dependencies when the engine is
required, you should require them before engine's initialization. For example:
required, you should require them before the engine's initialization. For example:
<ruby>
require 'other_engine/engine'

View File

@ -82,7 +82,7 @@ h4. Multiple Hashes in Form Helper Calls
The +form_tag+ helper accepts 2 arguments: the path for the action and an options hash. This hash specifies the method of form submission and HTML options such as the form element's class.
As with the +link_to+ helper, the path argument doesn't have to be given a string; it can be a hash of URL parameters recognizable by Rails' routing mechanism, which will turn the hash into a valid URL. However, since both arguments to +form_tag+ are hashes, you can easily run into a problem if you would like to specify both. For instance, let's say you write this:
As with the +link_to+ helper, the path argument doesn't have to be a string; it can be a hash of URL parameters recognizable by Rails' routing mechanism, which will turn the hash into a valid URL. However, since both arguments to +form_tag+ are hashes, you can easily run into a problem if you would like to specify both. For instance, let's say you write this:
<ruby>
form_tag(:controller => "people", :action => "search", :method => "get", :class => "nifty_form")
@ -942,4 +942,4 @@ As a convenience you can instead pass the symbol +:all_blank+ which will create
h4. Adding Fields on the Fly
Rather than rendering multiple sets of fields ahead of time you may wish to add them only when a user clicks on an 'Add new child' button. Rails does not provide any builtin support for this. When generating new sets of fields you must ensure the the key of the associated array is unique - the current javascript date (milliseconds after the epoch) is a common choice.
Rather than rendering multiple sets of fields ahead of time you may wish to add them only when a user clicks on an 'Add new child' button. Rails does not provide any builtin support for this. When generating new sets of fields you must ensure the the key of the associated array is unique - the current javascript date (milliseconds after the epoch) is a common choice.

View File

@ -575,11 +575,14 @@ The +:count+ interpolation variable has a special role in that it both is interp
<ruby>
I18n.backend.store_translations :en, :inbox => {
:one => '1 message',
:one => 'one message',
:other => '%{count} messages'
}
I18n.translate :inbox, :count => 2
# => '2 messages'
I18n.translate :inbox, :count => 1
# => 'one message'
</ruby>
The algorithm for pluralizations in +:en+ is as simple as:

View File

@ -1185,7 +1185,7 @@ h5. Spacer Templates
Rails will render the +_product_ruler+ partial (with no data passed in to it) between each pair of +_product+ partials.
h5. Partial Layouts
h5(#collection-partial-layouts). Partial Layouts
When rendering collections it is also possible to use the +:layout+ option:

View File

@ -81,7 +81,7 @@ it to default to +false+ for new users, but existing users are considered to
have already opted in, so we use the User model to set the flag to +true+ for
existing users.
h4. Using the change method
h4. Using the +change+ Method
Rails 3.1 makes migrations smarter by providing a new <tt>change</tt> method.
This method is preferred for writing constructive migrations (adding columns or
@ -351,7 +351,7 @@ end
This migration will create a user_id column and appropriate index.
h4. Supported type modifiers
h4. Supported Type Modifiers
You can also specify some options just after the field type between curly braces. You can use the
following modifiers:
@ -550,7 +550,7 @@ and
"<tt>ActiveRecord::ConnectionAdapters::Table</tt>":http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html
(which provides the methods available on the object yielded by +change_table+).
h4. Using the +change+ Method
h4. When to Use the +change+ Method
The +change+ method removes the need to write both +up+ and +down+ methods in
those cases that Rails knows how to revert the changes automatically. Currently,
@ -672,7 +672,7 @@ Neither of these Rake tasks do anything you could not do with +db:migrate+. They
are simply more convenient, since you do not need to explicitly specify the
version to migrate to.
h4. Resetting the database
h4. Resetting the Database
The +rake db:reset+ task will drop the database, recreate it and load the
current schema into it.
@ -680,7 +680,7 @@ current schema into it.
NOTE: This is not the same as running all the migrations - see the section on
"schema.rb":#schema-dumping-and-you.
h4. Running specific migrations
h4. Running Specific Migrations
If you need to run a specific migration up or down, the +db:migrate:up+ and
+db:migrate:down+ tasks will do that. Just specify the appropriate version and
@ -695,7 +695,7 @@ will run the +up+ method from the 20080906120000 migration. This task will first
check whether the migration is already performed and will do nothing if Active Record believes
that it has already been run.
h4. Changing the output of running migrations
h4. Changing the Output of Running Migrations
By default migrations tell you exactly what they're doing and how long it took.
A migration creating a table and adding an index might produce output like this

View File

@ -644,10 +644,10 @@ You can also reuse dynamic segments from the match in the path to redirect to:
get "/stories/:name" => redirect("/posts/%{name}")
</ruby>
You can also provide a block to redirect, which receives the params and (optionally) the request object:
You can also provide a block to redirect, which receives the params and the request object:
<ruby>
get "/stories/:name" => redirect {|params| "/posts/#{params[:name].pluralize}" }
get "/stories/:name" => redirect {|params, req| "/posts/#{params[:name].pluralize}" }
get "/stories" => redirect {|p, req| "/posts/#{req.subdomain}" }
</ruby>

View File

@ -44,7 +44,7 @@ The <tt>delete</tt> method in collection associations can now receive <tt>Fixnum
Rails 4.0 has changed how orders get stacked in +ActiveRecord::Relation+. In previous versions of rails new order was applied after previous defined order. But this is no long true. Check "ActiveRecord Query guide":active_record_querying.html#ordering for more information.
Rails 4.0 has changed <tt>serialized_attributes</tt> and <tt>_attr_readonly</tt> to class methods only. Now you shouldn't use instance methods, it's deprecated. You must change them, e.g. <tt>self.serialized_attributes</tt> to <tt>self.class.serialized_attributes</tt>.
Rails 4.0 has changed <tt>serialized_attributes</tt> and <tt>&#95;attr_readonly</tt> to class methods only. Now you shouldn't use instance methods, it's deprecated. You must change them, e.g. <tt>self.serialized_attributes</tt> to <tt>self.class.serialized_attributes</tt>.
h4(#active_model4_0). Active Model