assert!developer.save,"allowed to save a developer with too low salary"
end
test"able to call methods defined with included module"do# https://rails.lighthouseapp.com/projects/8994/tickets/6065-activerecordobserver-is-not-aware-of-method-added-by-including-modules
During the normal operation of a Rails application, objects may be created, updated, and destroyed. Active Record provides hooks into this <em>object life cycle</em> so that you can control your application and its data.
Validations allow you to ensure that only valid data is stored in your database. Callbacks and observers allow you to trigger logic before or after an alteration of an object's state.
Validations allow you to ensure that only valid data is stored in your database. Callbacks allow you to trigger logic before or after an alteration of an object's state.
Validations Overview
--------------------
...
...
@@ -1272,70 +1271,6 @@ end
You can declare as many callbacks as you want inside your callback classes.
Observers
---------
Observers are similar to callbacks, but with important differences. Whereas callbacks can pollute a model with code that isn't directly related to its purpose, observers allow you to add the same functionality without changing the code of the model. For example, it could be argued that a `User` model should not include code to send registration confirmation emails. Whenever you use callbacks with code that isn't directly related to your model, you may want to consider creating an observer instead.
### Creating Observers
For example, imagine a `User` model where we want to send an email every time a new user is created. Because sending emails is not directly related to our model's purpose, we should create an observer to contain the code implementing this functionality.
```bash
$ rails generate observer User
```
generates `app/models/user_observer.rb` containing the observer class `UserObserver`:
```ruby
classUserObserver<ActiveRecord::Observer
end
```
You may now add methods to be called at the desired occasions:
```ruby
classUserObserver<ActiveRecord::Observer
defafter_create(model)
# code to send confirmation email...
end
end
```
As with callback classes, the observer's methods receive the observed model as a parameter.
### Registering Observers
Observers are conventionally placed inside of your `app/models` directory and registered in your application's `config/application.rb` file. For example, the `UserObserver` above would be saved as `app/models/user_observer.rb` and registered in `config/application.rb` this way:
```ruby
# Activate observers that should always be running.
config.active_record.observers=:user_observer
```
As usual, settings in `config/environments` take precedence over those in `config/application.rb`. So, if you prefer that an observer doesn't run in all environments, you can simply register it in a specific environment instead.
### Sharing Observers
By default, Rails will simply strip "Observer" from an observer's name to find the model it should observe. However, observers can also be used to add behavior to more than one model, and thus it is possible to explicitly specify the models that our observer should observe:
```ruby
classMailerObserver<ActiveRecord::Observer
observe:registration,:user
defafter_create(model)
# code to send confirmation email...
end
end
```
In this example, the `after_create` method will be called whenever a `Registration` or `User` is created. Note that this new `MailerObserver` would also need to be registered in `config/application.rb` in order to take effect:
```ruby
# Activate observers that should always be running.
@@ -67,8 +67,6 @@ class ProductsController < ActionController
end
```
If you want a more complicated expiration scheme, you can use cache sweepers to expire cached objects when things change. This is covered in the section on Sweepers.
By default, page caching automatically gzips files (for example, to `products.html.gz` if user requests `/products`) to reduce the size of data transmitted (web servers are typically configured to use a moderate compression ratio as a compromise, but since precompilation happens once, compression ratio is maximum).
Nginx is able to serve compressed content directly from disk by enabling `gzip_static`:
...
...
@@ -176,102 +174,6 @@ This fragment is then available to all actions in the `ProductsController` using
expire_fragment('all_available_products')
```
### 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 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:
You may notice that the actual product gets passed to the sweeper, so if we were caching the edit action for each product, we could add an expire method which specifies the page we want to expire:
Then we add it to our controller to tell it to call the sweeper when certain actions are called. So, if we wanted to expire the cached content for the list and edit actions when the create action was called, we could do the following:
```ruby
classProductsController<ActionController
before_filter:authenticate
caches_action:index
cache_sweeper:product_sweeper
defindex
@products=Product.all
end
end
```
Sometimes it is necessary to disambiguate the controller when you call `expire_action`, such as when there are two identically named controllers in separate namespaces:
Note the use of '/products' here rather than 'products'. If you wanted to expire an action cache for the `Admin::ProductsController`, you would use 'admin/products' instead.
### SQL Caching
Query caching is a Rails feature that caches the result set returned by each query so that if Rails encounters the same query again for that request, it will use the cached result set as opposed to running the query against the database again.
This is a setting for Rails itself. If you want to pass settings to individual Rails components, you can do so via the same `config` object in `config/application.rb`: