21 .where(first_name: 'Harvey')
33 .reorder(:title) # discards other .order's
34 .rewhere(...) # discards other .where's
43 See: [QueryMethods](http://devdocs.io/rails/activerecord/querymethods)
45 ### Advanced query methods
54 .group(:name) # GROUP BY name
55 .group('name AS grouped_name, age')
56 .having('SUM(price) > 30') # needs to be chained with .group
61 .includes(user: [:articles])
66 # aka: .where("posts.name = 'foo'").references(:posts)
73 item = Model.find_by_email(email)
74 item = Model.where(email: email).first
80 .exists?(name: "David")
86 .find_nth(4, [offset])
89 See: [FinderMethods](http://devdocs.io/rails/activerecord/findermethods)
103 item.save! # Same as above, but raises an Exception
107 item.update name: 'John' # Saves immediately
108 item.update! name: 'John'
112 item.update_column :name, 'John' # skips validations and callbacks
113 item.update_columns name: 'John'
114 item.update_columns! name: 'John'
118 item.touch # updates :updated_at
119 item.touch :published_at
124 item.delete # skips callbacks
128 Model.create # Same an #new then #save
129 Model.create! # Same as above, but raises an Exception
132 See: [Persistence](http://devdocs.io/rails/activerecord/persistence)
134 ### Attribute Assignment
137 item.attributes # #<Hash>
141 item.attributes = { name: 'John' } # Merges attributes in. Doesn't save.
142 item.assign_attributes name: 'John' # Same as above
145 See: [AttributeAssignment](http://devdocs.io/rails/activerecord/attributeassignment)
151 item.changed # ['name']
152 item.changed_attributes # { 'name' => 'Bob' } - original values
153 item.changes # { 'name' => ['Bob', 'Robert'] }
154 item.previous_changes # available after #save
155 item.restore_attributes
160 item.name_was # 'Bob'
161 item.name_change # [ 'Bob', 'Robert' ]
162 item.name_changed? # true
163 item.name_changed?(from: 'Bob', to: 'Robert')
166 See: [Dirty](http://devdocs.io/rails/activemodel/dirty)
175 See: [Validations](http://devdocs.io/rails/activerecord/validations)
181 Person.count(:age) # counts non-nil's
188 Person.sum('2 * age')
192 Person.calculate(:count, :all)
198 Person.distinct.count
199 Person.group(:city).count
202 See: [Calculations](http://devdocs.io/rails/activerecord/calculations)
204 ### Dynamic attribute-based finders
206 Given a field called `name`:
211 Person.find_by_name(name)
212 Person.find_last_by_name(name)
213 Person.find_or_create_by_name(name)
214 Person.find_or_initialize_by_name(name)
218 # Returns a list of records
219 Person.find_all_by_name(name)
223 # Add a bang to make it raise an exception
224 Person.find_by_name!(name)
228 # You may use `scoped` instead of `find`
229 Person.scoped_by_user_name
240 - `has_many :through`
242 - `has_and_belongs_to_many`
247 belongs_to :parent, :foreign_key => 'parent_id' class_name: 'Folder'
248 has_many :folders, :foreign_key => 'parent_id', class_name: 'Folder'
250 has_many :comments, -> { order('posted_on DESC') }
251 has_many :comments, :include => :author
252 has_many :people, :class_name => "Person"
253 has_many :people, :conditions => "deleted = 0"
254 has_many :tracks, -> { order(:position) }
255 has_many :comments, :dependent => :nullify
256 has_many :comments, :dependent => :destroy
257 has_many :tags, :as => :taggable
258 has_many :reports, :readonly => true
259 has_many :subscribers, :through => :subscriptions, class_name: "User", :source => :user
260 has_many :subscribers, :finder_sql =>
261 'SELECT DISTINCT people.* ' +
262 'FROM people p, post_subscriptions ps ' +
263 'WHERE ps.post_id = #{id} AND ps.person_id = p.id ' +
264 'ORDER BY p.first_name'
271 :dependent => :destroy # or :delete
273 :class_name => "Person"
275 :counter_cache => true
276 :counter_cache => :custom_counter
280 :conditions => 'published = true'
283 :touch => :authors_last_updated_at
285 :primary_key => "name"
286 :foreign_key => "author_name"
291 If you have a join model:
295 class Programmer < ActiveRecord::Base
296 has_many :assignments
297 has_many :projects, :through => :assignments
303 class Project < ActiveRecord::Base
304 has_many :assignments
305 has_many :programmers, :through => :assignments
313 belongs_to :programmer
318 ### Many-to-many (HABTM)
321 has_and_belongs_to_many :projects
322 has_and_belongs_to_many :projects, :include => [ :milestones, :manager ]
323 has_and_belongs_to_many :nations, :class_name => "Country"
324 has_and_belongs_to_many :categories, :join_table => "prods_cats"
325 has_and_belongs_to_many :categories, :readonly => true
326 has_and_belongs_to_many :active_projects, :join_table => 'developers_projects', :delete_sql =>
327 "DELETE FROM developers_projects WHERE active=1 AND developer_id = #{id} AND project_id = #{record.id}"
330 ### Polymorphic associations
334 has_many :attachments, as: :parent
341 belongs_to :parent, polymorphic: true
349 create_table :images do |t|
350 t.references :post, polymorphic: true
361 class Person < ActiveRecord::Base
367 validates :name, presence: true
373 validates :terms, acceptance: true
378 validates :email, confirmation: true
383 validates :slug, uniqueness: true
384 validates :slug, uniqueness: { case_sensitive: false }
385 validates :holiday, uniqueness: { scope: :year, message: 'yearly only' }
390 validates :code, format: /regex/
391 validates :code, format: { with: /regex/ }
396 validates :name, length: { minimum: 2 }
397 validates :bio, length: { maximum: 500 }
398 validates :password, length: { in: => 6..20 }
399 validates :number, length: { is: => 6 }
404 validates :gender, inclusion: %w(male female)
405 validates :gender, inclusion: { in: %w(male female) }
406 validates :lol, exclusion: %w(xyz)
411 validates :points, numericality: true
412 validates :played, numericality: { only_integer: true }
413 # ... greater_than, greater_than_or_equal_to,
414 # ... less_than, less_than_or_equal_to
415 # ... odd, even, equal_to
419 # Validate the associated records to ensure they're valid as well
421 validates_associated :books
425 # Length (full options)
426 validates :content, length: {
429 tokenizer: lambda { |str| str.scan(/\w+/) },
430 too_short: "must have at least %{count} words",
431 too_long: "must have at most %{count} words" }
436 validates :login, :email, presence: true
441 validates :description, presence: true, if: :published?
442 validates :description, presence: true, if: lambda { |obj| .. }
446 validates :title, presence: true, on: :save # :save | :create | :update
454 ### Custom validations
457 class Person < ActiveRecord::Base
458 validate :foo_cant_be_nil
461 errors.add(:foo, 'cant be nil') if foo.nil?
470 record.errors.valid? # → false
471 record.errors # → { :name => ["can't be blank"] }
472 record.errors.messages # → { :name => ["can't be blank"] }
476 record.errors[:name].any?
484 * [Guides: callbacks](http://guides.rubyonrails.org/active_record_validations_callbacks.html)
489 # Updates person id 15
490 Person.update 15, name: "John", age: 24
491 Person.update [1,2], [{name: "John"}, {name: "foo"}]
498 Student.joins(:schools).where(schools: { type: 'public' })
499 Student.joins(:schools).where('schools.type' => 'public' )
503 # Multiple associations
504 Article.joins(:category, :comments)
508 # Nested associations
509 Article.joins(comments: :guest)
515 'INNER JOIN posts ' +
516 'ON posts.author_id = authors.id ' +
517 'AND posts.published = "t"'
521 ### Where interpolation
524 where('name = ?', 'John')
525 where(['name = :name', { name: 'John' }])
531 class User < ActiveRecord::Base
532 serialize :preferences
540 'background' => 'black',
546 You can also specify a class option as the second parameter that’ll raise an
547 exception if a serialized object is retrieved as a descendant of a class not in
552 class User < ActiveRecord::Base
553 serialize :preferences, Hash
559 # Reading it raises SerializationTypeMismatch
560 user = User.create(preferences: %w(one two three))
561 User.find(user.id).preferences
567 ### Overriding accessors
570 class Song < ActiveRecord::Base
571 # Uses an integer of seconds to hold the length of the song
574 write_attribute(:length, minutes.to_i * 60)
578 read_attribute(:length) / 60
584 See: <http://api.rubyonrails.org/classes/ActiveRecord/Base.html>