mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #22567 from gsamokovarov/introduce-application-record
Introduce ApplicationRecord, an Active Record layer supertype
This commit is contained in:
commit
1d7d8062b2
16 changed files with 200 additions and 134 deletions
|
@ -1,3 +1,18 @@
|
|||
* Introduce ApplicationRecord, an Active Record layer super type.
|
||||
|
||||
An `ApplicationRecord` let's engines have models, isolated from the main
|
||||
application. Plugin authors can use it to distribute extensions as modules
|
||||
to be included into `ApplicationRecord`, instead of monkey patches. It can
|
||||
also serve as a place for applications to customize the default
|
||||
`ActiveRecord::Base` model behaviour.
|
||||
|
||||
Newly generated applications have `app/models/application_record.rb`
|
||||
present by default. Generators are smart enough to recognize that
|
||||
newly generated models have to inherit from `ApplicationRecord` only if
|
||||
it's present.
|
||||
|
||||
*Genadi Samokovarov*
|
||||
|
||||
* Version the API presented to migration classes, so we can change parameter
|
||||
defaults without breaking existing migrations, or forcing them to be
|
||||
rewritten through a deprecation cycle.
|
||||
|
|
|
@ -43,9 +43,16 @@ module ActiveRecord
|
|||
|
||||
# Used by the migration template to determine the parent name of the model
|
||||
def parent_class_name
|
||||
options[:parent] || "ActiveRecord::Base"
|
||||
options[:parent] || determine_default_parent_class
|
||||
end
|
||||
|
||||
def determine_default_parent_class
|
||||
if File.exist?('app/models/application_record.rb')
|
||||
"ApplicationRecord"
|
||||
else
|
||||
"ActiveRecord::Base"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -132,10 +132,10 @@ Creating Active Record Models
|
|||
-----------------------------
|
||||
|
||||
It is very easy to create Active Record models. All you have to do is to
|
||||
subclass the `ActiveRecord::Base` class and you're good to go:
|
||||
subclass the `ApplicationRecord` class and you're good to go:
|
||||
|
||||
```ruby
|
||||
class Product < ActiveRecord::Base
|
||||
class Product < ApplicationRecord
|
||||
end
|
||||
```
|
||||
|
||||
|
@ -168,11 +168,12 @@ What if you need to follow a different naming convention or need to use your
|
|||
Rails application with a legacy database? No problem, you can easily override
|
||||
the default conventions.
|
||||
|
||||
You can use the `ActiveRecord::Base.table_name=` method to specify the table
|
||||
name that should be used:
|
||||
`ApplicationRecord` inherits from `ActionController::Base`, which defines a
|
||||
number of helpful methods. You can use the `ActiveRecord::Base.table_name=`
|
||||
method to specify the table name that should be used:
|
||||
|
||||
```ruby
|
||||
class Product < ActiveRecord::Base
|
||||
class Product < ApplicationRecord
|
||||
self.table_name = "my_products"
|
||||
end
|
||||
```
|
||||
|
@ -193,7 +194,7 @@ It's also possible to override the column that should be used as the table's
|
|||
primary key using the `ActiveRecord::Base.primary_key=` method:
|
||||
|
||||
```ruby
|
||||
class Product < ActiveRecord::Base
|
||||
class Product < ApplicationRecord
|
||||
self.primary_key = "product_id"
|
||||
end
|
||||
```
|
||||
|
@ -320,7 +321,7 @@ they raise the exception `ActiveRecord::RecordInvalid` if validation fails.
|
|||
A quick example to illustrate:
|
||||
|
||||
```ruby
|
||||
class User < ActiveRecord::Base
|
||||
class User < ApplicationRecord
|
||||
validates :name, presence: true
|
||||
end
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ Callbacks are methods that get called at certain moments of an object's life cyc
|
|||
In order to use the available callbacks, you need to register them. You can implement the callbacks as ordinary methods and use a macro-style class method to register them as callbacks:
|
||||
|
||||
```ruby
|
||||
class User < ActiveRecord::Base
|
||||
class User < ApplicationRecord
|
||||
validates :login, :email, presence: true
|
||||
|
||||
before_validation :ensure_login_has_a_value
|
||||
|
@ -48,7 +48,7 @@ end
|
|||
The macro-style class methods can also receive a block. Consider using this style if the code inside your block is so short that it fits in a single line:
|
||||
|
||||
```ruby
|
||||
class User < ActiveRecord::Base
|
||||
class User < ApplicationRecord
|
||||
validates :login, :email, presence: true
|
||||
|
||||
before_create do
|
||||
|
@ -60,7 +60,7 @@ end
|
|||
Callbacks can also be registered to only fire on certain life cycle events:
|
||||
|
||||
```ruby
|
||||
class User < ActiveRecord::Base
|
||||
class User < ApplicationRecord
|
||||
before_validation :normalize_name, on: :create
|
||||
|
||||
# :on takes an array as well
|
||||
|
@ -126,7 +126,7 @@ The `after_find` callback will be called whenever Active Record loads a record f
|
|||
The `after_initialize` and `after_find` callbacks have no `before_*` counterparts, but they can be registered just like the other Active Record callbacks.
|
||||
|
||||
```ruby
|
||||
class User < ActiveRecord::Base
|
||||
class User < ApplicationRecord
|
||||
after_initialize do |user|
|
||||
puts "You have initialized an object!"
|
||||
end
|
||||
|
@ -151,7 +151,7 @@ You have initialized an object!
|
|||
The `after_touch` callback will be called whenever an Active Record object is touched.
|
||||
|
||||
```ruby
|
||||
class User < ActiveRecord::Base
|
||||
class User < ApplicationRecord
|
||||
after_touch do |user|
|
||||
puts "You have touched an object"
|
||||
end
|
||||
|
@ -168,14 +168,14 @@ You have touched an object
|
|||
It can be used along with `belongs_to`:
|
||||
|
||||
```ruby
|
||||
class Employee < ActiveRecord::Base
|
||||
class Employee < ApplicationRecord
|
||||
belongs_to :company, touch: true
|
||||
after_touch do
|
||||
puts 'An Employee was touched'
|
||||
end
|
||||
end
|
||||
|
||||
class Company < ActiveRecord::Base
|
||||
class Company < ApplicationRecord
|
||||
has_many :employees
|
||||
after_touch :log_when_employees_or_company_touched
|
||||
|
||||
|
@ -266,11 +266,11 @@ Relational Callbacks
|
|||
Callbacks work through model relationships, and can even be defined by them. Suppose an example where a user has many articles. A user's articles should be destroyed if the user is destroyed. Let's add an `after_destroy` callback to the `User` model by way of its relationship to the `Article` model:
|
||||
|
||||
```ruby
|
||||
class User < ActiveRecord::Base
|
||||
class User < ApplicationRecord
|
||||
has_many :articles, dependent: :destroy
|
||||
end
|
||||
|
||||
class Article < ActiveRecord::Base
|
||||
class Article < ApplicationRecord
|
||||
after_destroy :log_destroy_action
|
||||
|
||||
def log_destroy_action
|
||||
|
@ -297,7 +297,7 @@ As with validations, we can also make the calling of a callback method condition
|
|||
You can associate the `:if` and `:unless` options with a symbol corresponding to the name of a predicate method that will get called right before the callback. When using the `:if` option, the callback won't be executed if the predicate method returns false; when using the `:unless` option, the callback won't be executed if the predicate method returns true. This is the most common option. Using this form of registration it is also possible to register several different predicates that should be called to check if the callback should be executed.
|
||||
|
||||
```ruby
|
||||
class Order < ActiveRecord::Base
|
||||
class Order < ApplicationRecord
|
||||
before_save :normalize_card_number, if: :paid_with_card?
|
||||
end
|
||||
```
|
||||
|
@ -307,7 +307,7 @@ end
|
|||
You can also use a string that will be evaluated using `eval` and hence needs to contain valid Ruby code. You should use this option only when the string represents a really short condition:
|
||||
|
||||
```ruby
|
||||
class Order < ActiveRecord::Base
|
||||
class Order < ApplicationRecord
|
||||
before_save :normalize_card_number, if: "paid_with_card?"
|
||||
end
|
||||
```
|
||||
|
@ -317,7 +317,7 @@ end
|
|||
Finally, it is possible to associate `:if` and `:unless` with a `Proc` object. This option is best suited when writing short validation methods, usually one-liners:
|
||||
|
||||
```ruby
|
||||
class Order < ActiveRecord::Base
|
||||
class Order < ApplicationRecord
|
||||
before_save :normalize_card_number,
|
||||
if: Proc.new { |order| order.paid_with_card? }
|
||||
end
|
||||
|
@ -328,7 +328,7 @@ end
|
|||
When writing conditional callbacks, it is possible to mix both `:if` and `:unless` in the same callback declaration:
|
||||
|
||||
```ruby
|
||||
class Comment < ActiveRecord::Base
|
||||
class Comment < ApplicationRecord
|
||||
after_create :send_email_to_author, if: :author_wants_emails?,
|
||||
unless: Proc.new { |comment| comment.article.ignore_comments? }
|
||||
end
|
||||
|
@ -354,7 +354,7 @@ end
|
|||
When declared inside a class, as above, the callback methods will receive the model object as a parameter. We can now use the callback class in the model:
|
||||
|
||||
```ruby
|
||||
class PictureFile < ActiveRecord::Base
|
||||
class PictureFile < ApplicationRecord
|
||||
after_destroy PictureFileCallbacks.new
|
||||
end
|
||||
```
|
||||
|
@ -374,7 +374,7 @@ end
|
|||
If the callback method is declared this way, it won't be necessary to instantiate a `PictureFileCallbacks` object.
|
||||
|
||||
```ruby
|
||||
class PictureFile < ActiveRecord::Base
|
||||
class PictureFile < ApplicationRecord
|
||||
after_destroy PictureFileCallbacks
|
||||
end
|
||||
```
|
||||
|
@ -398,7 +398,7 @@ end
|
|||
By using the `after_commit` callback we can account for this case.
|
||||
|
||||
```ruby
|
||||
class PictureFile < ActiveRecord::Base
|
||||
class PictureFile < ApplicationRecord
|
||||
after_commit :delete_picture_file_from_disk, on: [:destroy]
|
||||
|
||||
def delete_picture_file_from_disk
|
||||
|
@ -420,7 +420,7 @@ common, there are aliases for those operations:
|
|||
* `after_destroy_commit`
|
||||
|
||||
```ruby
|
||||
class PictureFile < ActiveRecord::Base
|
||||
class PictureFile < ApplicationRecord
|
||||
after_destroy_commit :delete_picture_file_from_disk
|
||||
|
||||
def delete_picture_file_from_disk
|
||||
|
|
|
@ -39,7 +39,7 @@ create_table :documents do |t|
|
|||
end
|
||||
|
||||
# app/models/document.rb
|
||||
class Document < ActiveRecord::Base
|
||||
class Document < ApplicationRecord
|
||||
end
|
||||
|
||||
# Usage
|
||||
|
@ -63,7 +63,7 @@ add_index :books, :tags, using: 'gin'
|
|||
add_index :books, :ratings, using: 'gin'
|
||||
|
||||
# app/models/book.rb
|
||||
class Book < ActiveRecord::Base
|
||||
class Book < ApplicationRecord
|
||||
end
|
||||
|
||||
# Usage
|
||||
|
@ -97,7 +97,7 @@ ActiveRecord::Schema.define do
|
|||
end
|
||||
|
||||
# app/models/profile.rb
|
||||
class Profile < ActiveRecord::Base
|
||||
class Profile < ApplicationRecord
|
||||
end
|
||||
|
||||
# Usage
|
||||
|
@ -122,7 +122,7 @@ create_table :events do |t|
|
|||
end
|
||||
|
||||
# app/models/event.rb
|
||||
class Event < ActiveRecord::Base
|
||||
class Event < ApplicationRecord
|
||||
end
|
||||
|
||||
# Usage
|
||||
|
@ -150,7 +150,7 @@ create_table :events do |t|
|
|||
end
|
||||
|
||||
# app/models/event.rb
|
||||
class Event < ActiveRecord::Base
|
||||
class Event < ApplicationRecord
|
||||
end
|
||||
|
||||
# Usage
|
||||
|
@ -200,7 +200,7 @@ create_table :contacts do |t|
|
|||
end
|
||||
|
||||
# app/models/contact.rb
|
||||
class Contact < ActiveRecord::Base
|
||||
class Contact < ApplicationRecord
|
||||
end
|
||||
|
||||
# Usage
|
||||
|
@ -239,7 +239,7 @@ def down
|
|||
end
|
||||
|
||||
# app/models/article.rb
|
||||
class Article < ActiveRecord::Base
|
||||
class Article < ApplicationRecord
|
||||
end
|
||||
|
||||
# Usage
|
||||
|
@ -294,7 +294,7 @@ create_table :revisions do |t|
|
|||
end
|
||||
|
||||
# app/models/revision.rb
|
||||
class Revision < ActiveRecord::Base
|
||||
class Revision < ApplicationRecord
|
||||
end
|
||||
|
||||
# Usage
|
||||
|
@ -317,12 +317,12 @@ create_table :comments, id: :uuid, default: 'gen_random_uuid()' do |t|
|
|||
end
|
||||
|
||||
# app/models/post.rb
|
||||
class Post < ActiveRecord::Base
|
||||
class Post < ApplicationRecord
|
||||
has_many :comments
|
||||
end
|
||||
|
||||
# app/models/comment.rb
|
||||
class Comment < ActiveRecord::Base
|
||||
class Comment < ApplicationRecord
|
||||
belongs_to :post
|
||||
end
|
||||
```
|
||||
|
@ -341,7 +341,7 @@ create_table :users, force: true do |t|
|
|||
end
|
||||
|
||||
# app/models/device.rb
|
||||
class User < ActiveRecord::Base
|
||||
class User < ApplicationRecord
|
||||
end
|
||||
|
||||
# Usage
|
||||
|
@ -370,7 +370,7 @@ create_table(:devices, force: true) do |t|
|
|||
end
|
||||
|
||||
# app/models/device.rb
|
||||
class Device < ActiveRecord::Base
|
||||
class Device < ApplicationRecord
|
||||
end
|
||||
|
||||
# Usage
|
||||
|
@ -410,7 +410,7 @@ create_table :devices, id: :uuid, default: 'gen_random_uuid()' do |t|
|
|||
end
|
||||
|
||||
# app/models/device.rb
|
||||
class Device < ActiveRecord::Base
|
||||
class Device < ApplicationRecord
|
||||
end
|
||||
|
||||
# Usage
|
||||
|
@ -434,7 +434,7 @@ end
|
|||
execute "CREATE INDEX documents_idx ON documents USING gin(to_tsvector('english', title || ' ' || body));"
|
||||
|
||||
# app/models/document.rb
|
||||
class Document < ActiveRecord::Base
|
||||
class Document < ApplicationRecord
|
||||
end
|
||||
|
||||
# Usage
|
||||
|
@ -484,7 +484,7 @@ CREATE VIEW articles AS
|
|||
SQL
|
||||
|
||||
# app/models/article.rb
|
||||
class Article < ActiveRecord::Base
|
||||
class Article < ApplicationRecord
|
||||
self.primary_key = "id"
|
||||
def archive!
|
||||
update_attribute :archived, true
|
||||
|
|
|
@ -25,7 +25,7 @@ Code examples throughout this guide will refer to one or more of the following m
|
|||
TIP: All of the following models use `id` as the primary key, unless specified otherwise.
|
||||
|
||||
```ruby
|
||||
class Client < ActiveRecord::Base
|
||||
class Client < ApplicationRecord
|
||||
has_one :address
|
||||
has_many :orders
|
||||
has_and_belongs_to_many :roles
|
||||
|
@ -33,19 +33,19 @@ end
|
|||
```
|
||||
|
||||
```ruby
|
||||
class Address < ActiveRecord::Base
|
||||
class Address < ApplicationRecord
|
||||
belongs_to :client
|
||||
end
|
||||
```
|
||||
|
||||
```ruby
|
||||
class Order < ActiveRecord::Base
|
||||
class Order < ApplicationRecord
|
||||
belongs_to :client, counter_cache: true
|
||||
end
|
||||
```
|
||||
|
||||
```ruby
|
||||
class Role < ActiveRecord::Base
|
||||
class Role < ApplicationRecord
|
||||
has_and_belongs_to_many :clients
|
||||
end
|
||||
```
|
||||
|
@ -740,7 +740,7 @@ SELECT "articles".* FROM "articles" WHERE (id > 10) ORDER BY id desc LIMIT 20
|
|||
The `reorder` method overrides the default scope order. For example:
|
||||
|
||||
```ruby
|
||||
class Article < ActiveRecord::Base
|
||||
class Article < ApplicationRecord
|
||||
has_many :comments, -> { order('posted_at DESC') }
|
||||
end
|
||||
|
||||
|
@ -889,7 +889,7 @@ This behavior can be turned off by setting `ActiveRecord::Base.lock_optimistical
|
|||
To override the name of the `lock_version` column, `ActiveRecord::Base` provides a class attribute called `locking_column`:
|
||||
|
||||
```ruby
|
||||
class Client < ActiveRecord::Base
|
||||
class Client < ApplicationRecord
|
||||
self.locking_column = :lock_client_column
|
||||
end
|
||||
```
|
||||
|
@ -970,26 +970,26 @@ Active Record lets you use the names of the [associations](association_basics.ht
|
|||
For example, consider the following `Category`, `Article`, `Comment`, `Guest` and `Tag` models:
|
||||
|
||||
```ruby
|
||||
class Category < ActiveRecord::Base
|
||||
class Category < ApplicationRecord
|
||||
has_many :articles
|
||||
end
|
||||
|
||||
class Article < ActiveRecord::Base
|
||||
class Article < ApplicationRecord
|
||||
belongs_to :category
|
||||
has_many :comments
|
||||
has_many :tags
|
||||
end
|
||||
|
||||
class Comment < ActiveRecord::Base
|
||||
class Comment < ApplicationRecord
|
||||
belongs_to :article
|
||||
has_one :guest
|
||||
end
|
||||
|
||||
class Guest < ActiveRecord::Base
|
||||
class Guest < ApplicationRecord
|
||||
belongs_to :comment
|
||||
end
|
||||
|
||||
class Tag < ActiveRecord::Base
|
||||
class Tag < ApplicationRecord
|
||||
belongs_to :article
|
||||
end
|
||||
```
|
||||
|
@ -1199,7 +1199,7 @@ Scoping allows you to specify commonly-used queries which can be referenced as m
|
|||
To define a simple scope, we use the `scope` method inside the class, passing the query that we'd like to run when this scope is called:
|
||||
|
||||
```ruby
|
||||
class Article < ActiveRecord::Base
|
||||
class Article < ApplicationRecord
|
||||
scope :published, -> { where(published: true) }
|
||||
end
|
||||
```
|
||||
|
@ -1207,7 +1207,7 @@ end
|
|||
This is exactly the same as defining a class method, and which you use is a matter of personal preference:
|
||||
|
||||
```ruby
|
||||
class Article < ActiveRecord::Base
|
||||
class Article < ApplicationRecord
|
||||
def self.published
|
||||
where(published: true)
|
||||
end
|
||||
|
@ -1217,7 +1217,7 @@ end
|
|||
Scopes are also chainable within scopes:
|
||||
|
||||
```ruby
|
||||
class Article < ActiveRecord::Base
|
||||
class Article < ApplicationRecord
|
||||
scope :published, -> { where(published: true) }
|
||||
scope :published_and_commented, -> { published.where("comments_count > 0") }
|
||||
end
|
||||
|
@ -1241,7 +1241,7 @@ category.articles.published # => [published articles belonging to this category]
|
|||
Your scope can take arguments:
|
||||
|
||||
```ruby
|
||||
class Article < ActiveRecord::Base
|
||||
class Article < ApplicationRecord
|
||||
scope :created_before, ->(time) { where("created_at < ?", time) }
|
||||
end
|
||||
```
|
||||
|
@ -1255,7 +1255,7 @@ Article.created_before(Time.zone.now)
|
|||
However, this is just duplicating the functionality that would be provided to you by a class method.
|
||||
|
||||
```ruby
|
||||
class Article < ActiveRecord::Base
|
||||
class Article < ApplicationRecord
|
||||
def self.created_before(time)
|
||||
where("created_at < ?", time)
|
||||
end
|
||||
|
@ -1274,7 +1274,7 @@ If we wish for a scope to be applied across all queries to the model we can use
|
|||
`default_scope` method within the model itself.
|
||||
|
||||
```ruby
|
||||
class Client < ActiveRecord::Base
|
||||
class Client < ApplicationRecord
|
||||
default_scope { where("removed_at IS NULL") }
|
||||
end
|
||||
```
|
||||
|
@ -1290,7 +1290,7 @@ If you need to do more complex things with a default scope, you can alternativel
|
|||
define it as a class method:
|
||||
|
||||
```ruby
|
||||
class Client < ActiveRecord::Base
|
||||
class Client < ApplicationRecord
|
||||
def self.default_scope
|
||||
# Should return an ActiveRecord::Relation.
|
||||
end
|
||||
|
@ -1301,7 +1301,7 @@ NOTE: The `default_scope` is also applied while creating/building a record.
|
|||
It is not applied while updating a record. E.g.:
|
||||
|
||||
```ruby
|
||||
class Client < ActiveRecord::Base
|
||||
class Client < ApplicationRecord
|
||||
default_scope { where(active: true) }
|
||||
end
|
||||
|
||||
|
@ -1314,7 +1314,7 @@ Client.unscoped.new # => #<Client id: nil, active: nil>
|
|||
Just like `where` clauses scopes are merged using `AND` conditions.
|
||||
|
||||
```ruby
|
||||
class User < ActiveRecord::Base
|
||||
class User < ApplicationRecord
|
||||
scope :active, -> { where state: 'active' }
|
||||
scope :inactive, -> { where state: 'inactive' }
|
||||
end
|
||||
|
@ -1343,7 +1343,7 @@ One important caveat is that `default_scope` will be prepended in
|
|||
`scope` and `where` conditions.
|
||||
|
||||
```ruby
|
||||
class User < ActiveRecord::Base
|
||||
class User < ApplicationRecord
|
||||
default_scope { where state: 'pending' }
|
||||
scope :active, -> { where state: 'active' }
|
||||
scope :inactive, -> { where state: 'inactive' }
|
||||
|
@ -1405,7 +1405,7 @@ Enums
|
|||
The `enum` macro maps an integer column to a set of possible values.
|
||||
|
||||
```ruby
|
||||
class Book < ActiveRecord::Base
|
||||
class Book < ApplicationRecord
|
||||
enum availability: [:available, :unavailable]
|
||||
end
|
||||
```
|
||||
|
@ -1657,7 +1657,7 @@ a large or often-running query. However, any model method overrides will
|
|||
not be available. For example:
|
||||
|
||||
```ruby
|
||||
class Client < ActiveRecord::Base
|
||||
class Client < ApplicationRecord
|
||||
def name
|
||||
"I am #{super}"
|
||||
end
|
||||
|
@ -1692,7 +1692,7 @@ Person.ids
|
|||
```
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
self.primary_key = "person_id"
|
||||
end
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ Validations Overview
|
|||
Here's an example of a very simple validation:
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :name, presence: true
|
||||
end
|
||||
|
||||
|
@ -80,7 +80,7 @@ method to determine whether an object is already in the database or not.
|
|||
Consider the following simple Active Record class:
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
end
|
||||
```
|
||||
|
||||
|
@ -157,7 +157,7 @@ and returns true if no errors were found in the object, and false otherwise.
|
|||
As you saw above:
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :name, presence: true
|
||||
end
|
||||
|
||||
|
@ -175,7 +175,7 @@ even if it's technically invalid, because validations are automatically run
|
|||
only when the object is saved, such as with the `create` or `save` methods.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :name, presence: true
|
||||
end
|
||||
|
||||
|
@ -221,7 +221,7 @@ it doesn't verify the validity of the object as a whole. It only checks to see
|
|||
whether there are errors found on an individual attribute of the object.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :name, presence: true
|
||||
end
|
||||
|
||||
|
@ -239,7 +239,7 @@ To check which validations failed on an invalid attribute, you can use
|
|||
key to get the symbol of the validator:
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :name, presence: true
|
||||
end
|
||||
|
||||
|
@ -285,7 +285,7 @@ the field does exist in your database, the `accept` option must be set to
|
|||
`true` or else the validation will not run.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :terms_of_service, acceptance: true
|
||||
end
|
||||
```
|
||||
|
@ -297,7 +297,7 @@ It can receive an `:accept` option, which determines the value that will be
|
|||
considered acceptance. It defaults to "1" and can be easily changed.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :terms_of_service, acceptance: { accept: 'yes' }
|
||||
end
|
||||
```
|
||||
|
@ -309,7 +309,7 @@ and they also need to be validated. When you try to save your object, `valid?`
|
|||
will be called upon each one of the associated objects.
|
||||
|
||||
```ruby
|
||||
class Library < ActiveRecord::Base
|
||||
class Library < ApplicationRecord
|
||||
has_many :books
|
||||
validates_associated :books
|
||||
end
|
||||
|
@ -332,7 +332,7 @@ or a password. This validation creates a virtual attribute whose name is the
|
|||
name of the field that has to be confirmed with "_confirmation" appended.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :email, confirmation: true
|
||||
end
|
||||
```
|
||||
|
@ -349,7 +349,7 @@ confirmation, make sure to add a presence check for the confirmation attribute
|
|||
(we'll take a look at `presence` later on in this guide):
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :email, confirmation: true
|
||||
validates :email_confirmation, presence: true
|
||||
end
|
||||
|
@ -360,7 +360,7 @@ confirmation constraint will be case sensitive or not. This option defaults to
|
|||
true.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :email, confirmation: { case_sensitive: false }
|
||||
end
|
||||
```
|
||||
|
@ -373,7 +373,7 @@ This helper validates that the attributes' values are not included in a given
|
|||
set. In fact, this set can be any enumerable object.
|
||||
|
||||
```ruby
|
||||
class Account < ActiveRecord::Base
|
||||
class Account < ApplicationRecord
|
||||
validates :subdomain, exclusion: { in: %w(www us ca jp),
|
||||
message: "%{value} is reserved." }
|
||||
end
|
||||
|
@ -393,7 +393,7 @@ This helper validates the attributes' values by testing whether they match a
|
|||
given regular expression, which is specified using the `:with` option.
|
||||
|
||||
```ruby
|
||||
class Product < ActiveRecord::Base
|
||||
class Product < ApplicationRecord
|
||||
validates :legacy_code, format: { with: /\A[a-zA-Z]+\z/,
|
||||
message: "only allows letters" }
|
||||
end
|
||||
|
@ -409,7 +409,7 @@ This helper validates that the attributes' values are included in a given set.
|
|||
In fact, this set can be any enumerable object.
|
||||
|
||||
```ruby
|
||||
class Coffee < ActiveRecord::Base
|
||||
class Coffee < ApplicationRecord
|
||||
validates :size, inclusion: { in: %w(small medium large),
|
||||
message: "%{value} is not a valid size" }
|
||||
end
|
||||
|
@ -428,7 +428,7 @@ This helper validates the length of the attributes' values. It provides a
|
|||
variety of options, so you can specify length constraints in different ways:
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :name, length: { minimum: 2 }
|
||||
validates :bio, length: { maximum: 500 }
|
||||
validates :password, length: { in: 6..20 }
|
||||
|
@ -451,7 +451,7 @@ number corresponding to the length constraint being used. You can still use the
|
|||
`:message` option to specify an error message.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :bio, length: { maximum: 1000,
|
||||
too_long: "%{count} characters is the maximum allowed" }
|
||||
end
|
||||
|
@ -483,7 +483,7 @@ WARNING. Note that the regular expression above allows a trailing newline
|
|||
character.
|
||||
|
||||
```ruby
|
||||
class Player < ActiveRecord::Base
|
||||
class Player < ApplicationRecord
|
||||
validates :points, numericality: true
|
||||
validates :games_played, numericality: { only_integer: true }
|
||||
end
|
||||
|
@ -521,7 +521,7 @@ This helper validates that the specified attributes are not empty. It uses the
|
|||
is, a string that is either empty or consists of whitespace.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :name, :login, :email, presence: true
|
||||
end
|
||||
```
|
||||
|
@ -531,7 +531,7 @@ whether the associated object itself is present, and not the foreign key used
|
|||
to map the association.
|
||||
|
||||
```ruby
|
||||
class LineItem < ActiveRecord::Base
|
||||
class LineItem < ApplicationRecord
|
||||
belongs_to :order
|
||||
validates :order, presence: true
|
||||
end
|
||||
|
@ -541,7 +541,7 @@ In order to validate associated records whose presence is required, you must
|
|||
specify the `:inverse_of` option for the association:
|
||||
|
||||
```ruby
|
||||
class Order < ActiveRecord::Base
|
||||
class Order < ApplicationRecord
|
||||
has_many :line_items, inverse_of: :order
|
||||
end
|
||||
```
|
||||
|
@ -568,7 +568,7 @@ This helper validates that the specified attributes are absent. It uses the
|
|||
is, a string that is either empty or consists of whitespace.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :name, :login, :email, absence: true
|
||||
end
|
||||
```
|
||||
|
@ -578,7 +578,7 @@ whether the associated object itself is absent, and not the foreign key used
|
|||
to map the association.
|
||||
|
||||
```ruby
|
||||
class LineItem < ActiveRecord::Base
|
||||
class LineItem < ApplicationRecord
|
||||
belongs_to :order
|
||||
validates :order, absence: true
|
||||
end
|
||||
|
@ -588,7 +588,7 @@ In order to validate associated records whose absence is required, you must
|
|||
specify the `:inverse_of` option for the association:
|
||||
|
||||
```ruby
|
||||
class Order < ActiveRecord::Base
|
||||
class Order < ApplicationRecord
|
||||
has_many :line_items, inverse_of: :order
|
||||
end
|
||||
```
|
||||
|
@ -611,7 +611,7 @@ with the same value for a column that you intend to be unique. To avoid that,
|
|||
you must create a unique index on that column in your database.
|
||||
|
||||
```ruby
|
||||
class Account < ActiveRecord::Base
|
||||
class Account < ApplicationRecord
|
||||
validates :email, uniqueness: true
|
||||
end
|
||||
```
|
||||
|
@ -623,7 +623,7 @@ There is a `:scope` option that you can use to specify one or more attributes th
|
|||
are used to limit the uniqueness check:
|
||||
|
||||
```ruby
|
||||
class Holiday < ActiveRecord::Base
|
||||
class Holiday < ApplicationRecord
|
||||
validates :name, uniqueness: { scope: :year,
|
||||
message: "should happen once per year" }
|
||||
end
|
||||
|
@ -635,7 +635,7 @@ uniqueness constraint will be case sensitive or not. This option defaults to
|
|||
true.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :name, uniqueness: { case_sensitive: false }
|
||||
end
|
||||
```
|
||||
|
@ -658,7 +658,7 @@ class GoodnessValidator < ActiveModel::Validator
|
|||
end
|
||||
end
|
||||
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates_with GoodnessValidator
|
||||
end
|
||||
```
|
||||
|
@ -686,7 +686,7 @@ class GoodnessValidator < ActiveModel::Validator
|
|||
end
|
||||
end
|
||||
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates_with GoodnessValidator, fields: [:first_name, :last_name]
|
||||
end
|
||||
```
|
||||
|
@ -699,7 +699,7 @@ If your validator is complex enough that you want instance variables, you can
|
|||
easily use a plain old Ruby object instead:
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validate do |person|
|
||||
GoodnessValidator.new(person).validate
|
||||
end
|
||||
|
@ -728,7 +728,7 @@ passed to `validates_each` will be tested against it. In the following example,
|
|||
we don't want names and surnames to begin with lower case.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates_each :name, :surname do |record, attr, value|
|
||||
record.errors.add(attr, 'must start with upper case') if value =~ /\A[[:lower:]]/
|
||||
end
|
||||
|
@ -751,7 +751,7 @@ The `:allow_nil` option skips the validation when the value being validated is
|
|||
`nil`.
|
||||
|
||||
```ruby
|
||||
class Coffee < ActiveRecord::Base
|
||||
class Coffee < ApplicationRecord
|
||||
validates :size, inclusion: { in: %w(small medium large),
|
||||
message: "%{value} is not a valid size" }, allow_nil: true
|
||||
end
|
||||
|
@ -764,7 +764,7 @@ will let validation pass if the attribute's value is `blank?`, like `nil` or an
|
|||
empty string for example.
|
||||
|
||||
```ruby
|
||||
class Topic < ActiveRecord::Base
|
||||
class Topic < ApplicationRecord
|
||||
validates :title, length: { is: 5 }, allow_blank: true
|
||||
end
|
||||
|
||||
|
@ -787,7 +787,7 @@ A `Proc` `:message` value is given two arguments: a message key for i18n, and
|
|||
a hash with `:model`, `:attribute`, and `:value` key-value pairs.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
# Hard-coded message
|
||||
validates :name, presence: { message: "must be given please" }
|
||||
|
||||
|
@ -818,7 +818,7 @@ new record is created or `on: :update` to run the validation only when a record
|
|||
is updated.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
# it will be possible to update email with a duplicated value
|
||||
validates :email, uniqueness: true, on: :create
|
||||
|
||||
|
@ -837,7 +837,7 @@ You can also specify validations to be strict and raise
|
|||
`ActiveModel::StrictValidationFailed` when the object is invalid.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :name, presence: { strict: true }
|
||||
end
|
||||
|
||||
|
@ -847,7 +847,7 @@ Person.new.valid? # => ActiveModel::StrictValidationFailed: Name can't be blank
|
|||
There is also the ability to pass a custom exception to the `:strict` option.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :token, presence: true, uniqueness: true, strict: TokenGenerationException
|
||||
end
|
||||
|
||||
|
@ -871,7 +871,7 @@ to the name of a method that will get called right before validation happens.
|
|||
This is the most commonly used option.
|
||||
|
||||
```ruby
|
||||
class Order < ActiveRecord::Base
|
||||
class Order < ApplicationRecord
|
||||
validates :card_number, presence: true, if: :paid_with_card?
|
||||
|
||||
def paid_with_card?
|
||||
|
@ -887,7 +887,7 @@ contain valid Ruby code. You should use this option only when the string
|
|||
represents a really short condition.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :surname, presence: true, if: "name.nil?"
|
||||
end
|
||||
```
|
||||
|
@ -900,7 +900,7 @@ inline condition instead of a separate method. This option is best suited for
|
|||
one-liners.
|
||||
|
||||
```ruby
|
||||
class Account < ActiveRecord::Base
|
||||
class Account < ApplicationRecord
|
||||
validates :password, confirmation: true,
|
||||
unless: Proc.new { |a| a.password.blank? }
|
||||
end
|
||||
|
@ -912,7 +912,7 @@ Sometimes it is useful to have multiple validations use one condition. It can
|
|||
be easily achieved using `with_options`.
|
||||
|
||||
```ruby
|
||||
class User < ActiveRecord::Base
|
||||
class User < ApplicationRecord
|
||||
with_options if: :is_admin? do |admin|
|
||||
admin.validates :password, length: { minimum: 10 }
|
||||
admin.validates :email, presence: true
|
||||
|
@ -930,7 +930,7 @@ should happen, an `Array` can be used. Moreover, you can apply both `:if` and
|
|||
`:unless` to the same validation.
|
||||
|
||||
```ruby
|
||||
class Computer < ActiveRecord::Base
|
||||
class Computer < ApplicationRecord
|
||||
validates :mouse, presence: true,
|
||||
if: ["market.retail?", :desktop?],
|
||||
unless: Proc.new { |c| c.trackpad.present? }
|
||||
|
@ -984,7 +984,7 @@ class EmailValidator < ActiveModel::EachValidator
|
|||
end
|
||||
end
|
||||
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :email, presence: true, email: true
|
||||
end
|
||||
```
|
||||
|
@ -1008,7 +1008,7 @@ so your custom validation methods should add errors to it when you
|
|||
wish validation to fail:
|
||||
|
||||
```ruby
|
||||
class Invoice < ActiveRecord::Base
|
||||
class Invoice < ApplicationRecord
|
||||
validate :expiration_date_cannot_be_in_the_past,
|
||||
:discount_cannot_be_greater_than_total_value
|
||||
|
||||
|
@ -1032,7 +1032,7 @@ custom validations by giving an `:on` option to the `validate` method,
|
|||
with either: `:create` or `:update`.
|
||||
|
||||
```ruby
|
||||
class Invoice < ActiveRecord::Base
|
||||
class Invoice < ApplicationRecord
|
||||
validate :active_customer, on: :create
|
||||
|
||||
def active_customer
|
||||
|
@ -1053,7 +1053,7 @@ The following is a list of the most commonly used methods. Please refer to the `
|
|||
Returns an instance of the class `ActiveModel::Errors` containing all errors. Each key is the attribute name and the value is an array of strings with all errors.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :name, presence: true, length: { minimum: 3 }
|
||||
end
|
||||
|
||||
|
@ -1072,7 +1072,7 @@ person.errors.messages # => {}
|
|||
`errors[]` is used when you want to check the error messages for a specific attribute. It returns an array of strings with all error messages for the given attribute, each string with one error message. If there are no errors related to the attribute, it returns an empty array.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :name, presence: true, length: { minimum: 3 }
|
||||
end
|
||||
|
||||
|
@ -1097,7 +1097,7 @@ The `add` method lets you add an error message related to a particular attribute
|
|||
The `errors.full_messages` method (or its equivalent, `errors.to_a`) returns the error messages in a user-friendly format, with the capitalized attribute name prepended to each message, as shown in the examples below.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
def a_method_used_for_validation_purposes
|
||||
errors.add(:name, "cannot contain the characters !@#%*()_-+=")
|
||||
end
|
||||
|
@ -1115,7 +1115,7 @@ person.errors.full_messages
|
|||
An equivalent to `errors#add` is to use `<<` to append a message to the `errors.messages` array for an attribute:
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
def a_method_used_for_validation_purposes
|
||||
errors.messages[:name] << "cannot contain the characters !@#%*()_-+="
|
||||
end
|
||||
|
@ -1136,7 +1136,7 @@ You can specify a validator type to the returned error details hash using the
|
|||
`errors.add` method.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
def a_method_used_for_validation_purposes
|
||||
errors.add(:name, :invalid_characters)
|
||||
end
|
||||
|
@ -1152,7 +1152,7 @@ To improve the error details to contain the unallowed characters set for instanc
|
|||
you can pass additional keys to `errors.add`.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
def a_method_used_for_validation_purposes
|
||||
errors.add(:name, :invalid_characters, not_allowed: "!@#%*()_-+=")
|
||||
end
|
||||
|
@ -1172,7 +1172,7 @@ validator type.
|
|||
You can add error messages that are related to the object's state as a whole, instead of being related to a specific attribute. You can use this method when you want to say that the object is invalid, no matter the values of its attributes. Since `errors[:base]` is an array, you can simply add a string to it and it will be used as an error message.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
def a_method_used_for_validation_purposes
|
||||
errors[:base] << "This person is invalid because ..."
|
||||
end
|
||||
|
@ -1184,7 +1184,7 @@ end
|
|||
The `clear` method is used when you intentionally want to clear all the messages in the `errors` collection. Of course, calling `errors.clear` upon an invalid object won't actually make it valid: the `errors` collection will now be empty, but the next time you call `valid?` or any method that tries to save this object to the database, the validations will run again. If any of the validations fail, the `errors` collection will be filled again.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :name, presence: true, length: { minimum: 3 }
|
||||
end
|
||||
|
||||
|
@ -1207,7 +1207,7 @@ p.errors[:name]
|
|||
The `size` method returns the total number of error messages for the object.
|
||||
|
||||
```ruby
|
||||
class Person < ActiveRecord::Base
|
||||
class Person < ApplicationRecord
|
||||
validates :name, presence: true, length: { minimum: 3 }
|
||||
end
|
||||
|
||||
|
|
|
@ -508,7 +508,7 @@ Turning the model into this:
|
|||
|
||||
```ruby
|
||||
module Blorgh
|
||||
class Article < ActiveRecord::Base
|
||||
class Article < ApplicationRecord
|
||||
has_many :comments
|
||||
end
|
||||
end
|
||||
|
@ -1129,7 +1129,7 @@ end
|
|||
```ruby
|
||||
# Blorgh/app/models/article.rb
|
||||
|
||||
class Article < ActiveRecord::Base
|
||||
class Article < ApplicationRecord
|
||||
has_many :comments
|
||||
end
|
||||
```
|
||||
|
@ -1150,7 +1150,7 @@ end
|
|||
```ruby
|
||||
# Blorgh/app/models/article.rb
|
||||
|
||||
class Article < ActiveRecord::Base
|
||||
class Article < ApplicationRecord
|
||||
has_many :comments
|
||||
def summary
|
||||
"#{title}"
|
||||
|
@ -1171,7 +1171,7 @@ classes at run time allowing you to significantly modularize your code.
|
|||
```ruby
|
||||
# MyApp/app/models/blorgh/article.rb
|
||||
|
||||
class Blorgh::Article < ActiveRecord::Base
|
||||
class Blorgh::Article < ApplicationRecord
|
||||
include Blorgh::Concerns::Models::Article
|
||||
|
||||
def time_since_created
|
||||
|
@ -1187,7 +1187,7 @@ end
|
|||
```ruby
|
||||
# Blorgh/app/models/article.rb
|
||||
|
||||
class Article < ActiveRecord::Base
|
||||
class Article < ApplicationRecord
|
||||
include Blorgh::Concerns::Models::Article
|
||||
end
|
||||
```
|
||||
|
|
|
@ -17,7 +17,7 @@ After reading this guide, you will know:
|
|||
This guide describes how to build a test-driven plugin that will:
|
||||
|
||||
* Extend core Ruby classes like Hash and String.
|
||||
* Add methods to `ActiveRecord::Base` in the tradition of the `acts_as` plugins.
|
||||
* Add methods to `ApplicationRecord` in the tradition of the `acts_as` plugins.
|
||||
* Give you information about where to put generators in your plugin.
|
||||
|
||||
For the purpose of this guide pretend for a moment that you are an avid bird watcher.
|
||||
|
@ -182,7 +182,6 @@ To start out, write a failing test that shows the behavior you'd like:
|
|||
require 'test_helper'
|
||||
|
||||
class ActsAsYaffleTest < ActiveSupport::TestCase
|
||||
|
||||
def test_a_hickwalls_yaffle_text_field_should_be_last_squawk
|
||||
assert_equal "last_squawk", Hickwall.yaffle_text_field
|
||||
end
|
||||
|
@ -190,7 +189,6 @@ class ActsAsYaffleTest < ActiveSupport::TestCase
|
|||
def test_a_wickwalls_yaffle_text_field_should_be_last_tweet
|
||||
assert_equal "last_tweet", Wickwall.yaffle_text_field
|
||||
end
|
||||
|
||||
end
|
||||
```
|
||||
|
||||
|
@ -234,22 +232,22 @@ like yaffles.
|
|||
```ruby
|
||||
# test/dummy/app/models/hickwall.rb
|
||||
|
||||
class Hickwall < ActiveRecord::Base
|
||||
class Hickwall < ApplicationRecord
|
||||
acts_as_yaffle
|
||||
end
|
||||
|
||||
# test/dummy/app/models/wickwall.rb
|
||||
|
||||
class Wickwall < ActiveRecord::Base
|
||||
class Wickwall < ApplicationRecord
|
||||
acts_as_yaffle yaffle_text_field: :last_tweet
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
We will also add code to define the `acts_as_yaffle` method.
|
||||
|
||||
```ruby
|
||||
# yaffle/lib/yaffle/acts_as_yaffle.rb
|
||||
|
||||
module Yaffle
|
||||
module ActsAsYaffle
|
||||
extend ActiveSupport::Concern
|
||||
|
@ -265,7 +263,13 @@ module Yaffle
|
|||
end
|
||||
end
|
||||
|
||||
ActiveRecord::Base.include(Yaffle::ActsAsYaffle)
|
||||
# test/dummy/app/models/application_record.rb
|
||||
|
||||
class ApplicationRecord < ActiveRecord::Base
|
||||
include Yaffle::ActsAsYaffle
|
||||
|
||||
self.abstract_class = true
|
||||
end
|
||||
```
|
||||
|
||||
You can then return to the root directory (`cd ../..`) of your plugin and rerun the tests using `rake`.
|
||||
|
@ -308,7 +312,13 @@ module Yaffle
|
|||
end
|
||||
end
|
||||
|
||||
ActiveRecord::Base.include(Yaffle::ActsAsYaffle)
|
||||
# test/dummy/app/models/application_record.rb
|
||||
|
||||
class ApplicationRecord < ActiveRecord::Base
|
||||
include Yaffle::ActsAsYaffle
|
||||
|
||||
self.abstract_class = true
|
||||
end
|
||||
```
|
||||
|
||||
When you run `rake`, you should see the tests all pass:
|
||||
|
@ -329,7 +339,6 @@ To start out, write a failing test that shows the behavior you'd like:
|
|||
require 'test_helper'
|
||||
|
||||
class ActsAsYaffleTest < ActiveSupport::TestCase
|
||||
|
||||
def test_a_hickwalls_yaffle_text_field_should_be_last_squawk
|
||||
assert_equal "last_squawk", Hickwall.yaffle_text_field
|
||||
end
|
||||
|
@ -382,7 +391,13 @@ module Yaffle
|
|||
end
|
||||
end
|
||||
|
||||
ActiveRecord::Base.include(Yaffle::ActsAsYaffle)
|
||||
# test/dummy/app/models/application_record.rb
|
||||
|
||||
class ApplicationRecord < ActiveRecord::Base
|
||||
include Yaffle::ActsAsYaffle
|
||||
|
||||
self.abstract_class = true
|
||||
end
|
||||
```
|
||||
|
||||
Run `rake` one final time and you should see:
|
||||
|
|
|
@ -293,6 +293,12 @@ module Rails
|
|||
end
|
||||
end
|
||||
|
||||
def delete_application_record_skipping_active_record
|
||||
if options[:skip_active_record]
|
||||
remove_file 'app/models/application_record.rb'
|
||||
end
|
||||
end
|
||||
|
||||
def delete_active_record_initializers_skipping_active_record
|
||||
if options[:skip_active_record]
|
||||
remove_file 'config/initializers/active_record_belongs_to_required_by_default.rb'
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
class ApplicationRecord < ActiveRecord::Base
|
||||
self.abstract_class = true
|
||||
end
|
|
@ -0,0 +1,6 @@
|
|||
<%= wrap_in_modules <<-rb.strip_heredoc
|
||||
class ApplicationRecord < ActiveRecord::Base
|
||||
self.abstract_class = true
|
||||
end
|
||||
rb
|
||||
%>
|
|
@ -228,6 +228,7 @@ module ApplicationTests
|
|||
end
|
||||
|
||||
test "the application can be eager loaded even when there are no frameworks" do
|
||||
FileUtils.rm_rf("#{app_path}/app/models/application_record.rb")
|
||||
FileUtils.rm_rf("#{app_path}/config/environments")
|
||||
add_to_config <<-RUBY
|
||||
config.eager_load = true
|
||||
|
|
|
@ -98,7 +98,7 @@ module ApplicationTests
|
|||
end
|
||||
|
||||
def test_code_statistics_sanity
|
||||
assert_match "Code LOC: 7 Test LOC: 0 Code to Test Ratio: 1:0.0",
|
||||
assert_match "Code LOC: 10 Test LOC: 0 Code to Test Ratio: 1:0.0",
|
||||
Dir.chdir(app_path){ `bin/rake stats` }
|
||||
end
|
||||
|
||||
|
|
|
@ -334,6 +334,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
|
|||
run_generator [destination_root, "--skip-active-record"]
|
||||
assert_no_file "config/database.yml"
|
||||
assert_no_file "config/initializers/active_record_belongs_to_required_by_default.rb"
|
||||
assert_no_file "app/models/application_record.rb"
|
||||
assert_file "config/application.rb", /#\s+require\s+["']active_record\/railtie["']/
|
||||
assert_file "test/test_helper.rb" do |helper_content|
|
||||
assert_no_match(/fixtures :all/, helper_content)
|
||||
|
|
|
@ -35,6 +35,17 @@ class ModelGeneratorTest < Rails::Generators::TestCase
|
|||
assert_no_migration "db/migrate/create_accounts.rb"
|
||||
end
|
||||
|
||||
def test_model_with_existent_application_record
|
||||
mkdir_p "#{destination_root}/app/models"
|
||||
touch "#{destination_root}/app/models/application_record.rb"
|
||||
|
||||
Dir.chdir(destination_root) do
|
||||
run_generator ["account"]
|
||||
end
|
||||
|
||||
assert_file "app/models/account.rb", /class Account < ApplicationRecord/
|
||||
end
|
||||
|
||||
def test_plural_names_are_singularized
|
||||
content = run_generator ["accounts".freeze]
|
||||
assert_file "app/models/account.rb", /class Account < ActiveRecord::Base/
|
||||
|
|
Loading…
Reference in a new issue