Created
April 15, 2015 16:48
-
-
Save oojikoo-gist/85df888d26d9b1018c69 to your computer and use it in GitHub Desktop.
rails: association
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# With this declaration, Rails will keep the cache value up to date, and then return that value in response to the size method. | |
# without contuer_cache option | |
# asking for the value of @customer.orders.size requires making a call to the database to perform a COUNT(*) query | |
# To avoid this call, you can add a counter cache to the belonging model: | |
belongs_to :customer, counter_cache: true | |
# throught association | |
class Physician < ActiveRecord::Base | |
has_many :appointments | |
has_many :patients, through: :appointments | |
end | |
class Appointment < ActiveRecord::Base | |
belongs_to :physician | |
belongs_to :patient | |
end | |
class Patient < ActiveRecord::Base | |
has_many :appointments | |
has_many :physicians, through: :appointments | |
end | |
# nested association | |
class Document < ActiveRecord::Base | |
has_many :sections | |
has_many :paragraphs, through: :sections | |
end | |
class Section < ActiveRecord::Base | |
belongs_to :document | |
has_many :paragraphs | |
end | |
class Paragraph < ActiveRecord::Base | |
belongs_to :section | |
end | |
# many to many | |
# | |
class Assembly < ActiveRecord::Base | |
has_and_belongs_to_many :parts | |
end | |
class Part < ActiveRecord::Base | |
has_and_belongs_to_many :assemblies | |
end | |
# has_one | |
class Supplier < ActiveRecord::Base | |
has_one :account | |
end | |
class Account < ActiveRecord::Base | |
belongs_to :supplier | |
end | |
# polyymorphic | |
class Picture < ActiveRecord::Base | |
belongs_to :imageable, polymorphic: true | |
end | |
class Employee < ActiveRecord::Base | |
has_many :pictures, as: :imageable | |
end | |
class Product < ActiveRecord::Base | |
has_many :pictures, as: :imageable | |
end | |
# self join | |
class Employee < ActiveRecord::Base | |
has_many :subordinates, class_name: "Employee", | |
foreign_key: "manager_id" | |
belongs_to :manager, class_name: "Employee" | |
end | |
# inverse_of | |
class Customer < ActiveRecord::Base | |
has_many :orders, inverse_of: :customer | |
end | |
class Order < ActiveRecord::Base | |
belongs_to :customer, inverse_of: :orders | |
end | |
c = Customer.first | |
o = c.orders.first | |
c.first_name == o.customer.first_name # => true | |
c.first_name = 'Manny' | |
c.first_name == o.customer.first_name # => true | |
class Order < ActiveRecord::Base | |
belongs_to :customer | |
end | |
# > methods | |
# customer | |
# customer= | |
# build_customer | |
# create_customer | |
# create_customer! | |
@customer = @order.build_customer(customer_number: 123, | |
customer_name: "John Doe") | |
@order.customer = @customer | |
# :dependent | |
# :destroy, when the object is destroyed, destroy will be called on its associated objects. | |
# :delete, when the object is destroyed, all its associated objects will be deleted directly from the database without calling their destroy method | |
# :foreign_key | |
# By convention, Rails assumes that the column used to hold the foreign key on this model is the name of the association with the suffix _id added. The :foreign_key option lets you set the name of the foreign key directly: | |
class Order < ActiveRecord::Base | |
belongs_to :customer, class_name: "Patron", | |
foreign_key: "patron_id" | |
end | |
# :touch | |
# | |
class Order < ActiveRecord::Base | |
belongs_to :customer, touch: true | |
end | |
class Customer < ActiveRecord::Base | |
has_many :orders | |
end | |
# In this case, saving or destroying an order will update the timestamp on the associated customer. You can also specify a particular timestamp attribute to update: | |
class Order < ActiveRecord::Base | |
belongs_to :customer, touch: :orders_updated_at | |
end | |
# :validate | |
# If you set the :validate option to true, then associated objects will be validated whenever you save this object. By default, this is false: associated objects will not be validated when this object is saved. | |
# Scopes for belongs_to | |
# There may be times when you wish to customize the query used by belongs_to. Such customizations can be achieved via a scope block. For example: | |
class Order < ActiveRecord::Base | |
belongs_to :customer, -> { where active: true }, | |
dependent: :destroy | |
end | |
# You can use any of the standard querying methods inside the scope block. The following ones are discussed below: | |
# where | |
# includes | |
# readonly | |
# select | |
# includes | |
# If you frequently retrieve representatives directly from suppliers (@supplier.account.representative), then you can make your code somewhat more efficient by including representatives in the association from suppliers to accounts: | |
class Supplier < ActiveRecord::Base | |
has_one :account, -> { includes :representative } | |
end | |
class Account < ActiveRecord::Base | |
belongs_to :supplier | |
belongs_to :representative | |
end | |
class Representative < ActiveRecord::Base | |
has_many :accounts | |
end | |
# ==================================== | |
# has_many Association Reference | |
# ==================================== | |
# | |
# collection(force_reload = false) | |
# collection<<(object, ...) | |
# collection.delete(object, ...) | |
# collection.destroy(object, ...) | |
# collection=(objects) | |
# collection_singular_ids | |
# collection_singular_ids=(ids) | |
# collection.clear | |
# collection.empty? | |
# collection.size | |
# collection.find(...) | |
# collection.where(...) | |
# collection.exists?(...) | |
# collection.build(attributes = {}, ...) | |
# collection.create(attributes = {}) | |
# collection.create!(attributes = {}) | |
# The collection<< method adds one or more objects to the collection by setting their foreign keys to the primary key of the calling model. | |
@customer.orders << @order1 | |
# The collection.delete method removes one or more objects from the collection by setting their foreign keys to NULL. | |
@customer.orders.delete(@order1) | |
# The collection.destroy method removes one or more objects from the collection by running destroy on each object. | |
@customer.orders.destroy(@order1) | |
# The collection_singular_ids method returns an array of the ids of the objects in the collection. | |
@order_ids = @customer.order_ids | |
# The collection.clear method removes every object from the collection. This destroys the associated objects if they are associated with dependent: :destroy, deletes them directly from the database if dependent: :delete_all, and otherwise sets their foreign keys to NULL. | |
######################## | |
# Options for has_many | |
######################## | |
# >> methods | |
# :as | |
# :autosave | |
# :class_name | |
# :dependent | |
# :foreign_key | |
# :inverse_of | |
# :primary_key | |
# :source | |
# :source_type | |
# :through | |
# :validate | |
# The group method supplies an attribute name to group the result set by, using a GROUP BY clause in the finder SQL. | |
class Customer < ActiveRecord::Base | |
has_many :line_items, -> { group 'orders.id' }, | |
through: :orders | |
end | |
# The limit method lets you restrict the total number of objects that will be fetched through an association. | |
# | |
class Customer < ActiveRecord::Base | |
has_many :recent_orders, | |
-> { order('order_date desc').limit(100) }, | |
class_name: "Order" | |
end | |
# The offset method lets you specify the starting offset for fetching objects via an association. For example, -> { offset(11) } will skip the first 11 records. | |
# | |
# The order method dictates the order in which associated objects will be received (in the syntax used by an SQL ORDER BY clause). | |
class Customer < ActiveRecord::Base | |
has_many :orders, -> { order "date_confirmed DESC" } | |
end | |
# If you use the readonly method, then the associated objects will be read-only when retrieved via the association. | |
# The select method lets you override the SQL SELECT clause that is used to retrieve data about the associated objects. By default, Rails retrieves all columns. | |
# ***** If you specify your own select, be sure to include the primary key and foreign key columns of the associated model. If you do not, Rails will throw an error. | |
# Use the distinct method to keep the collection free of duplicates. This is mostly useful together with the :through option. | |
class Person < ActiveRecord::Base | |
has_many :readings | |
has_many :articles, through: :readings | |
end | |
person = Person.create(name: 'John') | |
article = Article.create(name: 'a1') | |
person.articles << article | |
person.articles << article | |
person.articles.inspect # => [#<Article id: 5, name: "a1">, #<Article id: 5, name: "a1">] | |
Reading.all.inspect # => [#<Reading id: 12, person_id: 5, article_id: 5>, #<Reading id: 13, person_id: 5, article_id: 5>] | |
class Person | |
has_many :readings | |
has_many :articles, -> { distinct }, through: :readings | |
end | |
person = Person.create(name: 'Honda') | |
article = Article.create(name: 'a1') | |
person.articles << article | |
person.articles << article | |
person.articles.inspect # => [#<Article id: 7, name: "a1">] | |
Reading.all.inspect # => [#<Reading id: 16, person_id: 7, article_id: 7>, #<Reading id: 17, person_id: 7, article_id: 7>] | |
# If you want to make sure that, upon insertion, all of the records in the persisted association are distinct (so that you can be sure that when you inspect the association that you will never find duplicate records), you should add a unique index on the table itself. For example, if you have a table named person_articles and you want to make sure all the articles are unique, you could add the following in a migration: | |
add_index :person_articles, :article, unique: true | |
# Options for has_and_belongs_to_many | |
# :association_foreign_key | |
# :autosave | |
# :class_name | |
# :foreign_key | |
# :join_table | |
# :validate | |
# :association_foreign_key | |
# By convention, Rails assumes that the column in the join table used to hold the foreign key pointing to the other model is the name of that model with the suffix _id added. The :association_foreign_key option lets you set the name of the foreign key directly: | |
# | |
class User < ActiveRecord::Base | |
has_and_belongs_to_many :friends, | |
class_name: "User", | |
foreign_key: "this_user_id", | |
association_foreign_key: "other_user_id" | |
end | |
# If the default name of the join table, based on lexical ordering, is not what you want, you can use the :join_table option to override the default. | |
# If you set the :validate option to false, then associated objects will not be validated whenever you save this object. By default, this is true: associated objects will be validated when this object is saved. | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment