active record(1)
TRANSCRIPT
![Page 1: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/1.jpg)
Active records association
BYANANTA RAJ LAMICHHANE
![Page 2: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/2.jpg)
Active record?
facilitates the creation and use of business objects whose data requires persistent storage to a database.
is a description of an Object Relational Mapping system.ORM, is a technique that connects the rich objects of an application to tables
in a relational database management system.
![Page 3: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/3.jpg)
Convention over Configuration
Naming conventionDatabase Table - Plural with underscores separating words (e.g.,
book_clubs).Model Class - Singular with the first letter of each word capitalized (e.g.,
BookClub).Schema convention Foreign keys - These fields should be named following the pattern
singularized_table_name_id.Primary keys - By default, Active Record will use an integer column named
id as the table's primary keyoptional column names like created_at, updated_at, type etcs….
![Page 4: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/4.jpg)
AR associations. Why?
![Page 5: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/5.jpg)
make common operations simpler and easier
![Page 6: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/6.jpg)
Scenarioconsider a simple Rails application that
includes a model for customers and a model for orders.
Each customer can have many orders
![Page 7: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/7.jpg)
rails g model customer name:stringrails g model order customer_id:integer
description:stringrake db:migraterails c
![Page 8: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/8.jpg)
Without associationclass Customer < ActiveRecord::Baseendclass Order < ActiveRecord::Baseend
![Page 9: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/9.jpg)
2.1.1 :001 > c=Customer.create(name:'cust1') => #<Customer id: 1, name: "cust1", created_at: "2015-01-03 07:58:03", updated_at: "2015-01-03 07:58:03">To Add new Order2.1.1 :002 > o=Order.new2.1.1 :003 > o.customer_id=c.id2.1.1 :003 > o.description="this is a test description"2.1.1 :006 > o.save
To deleting a customer, and ensuring that all of its orders get deleted as well2.1.1 :009 > orders= Order.where(customer_id: c.id)2.1.1 :010 > orders.each do |order|2.1.1 :011 > order.destroy2.1.1 :012?> end2.1.1 :013 > c.destroy
![Page 10: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/10.jpg)
With Associationclass Customer < ActiveRecord::Base has_many :orders, dependent: :destroyend
class Order < ActiveRecord::Base belongs_to :customerend
2.1.1 :001 > c=Customer.create(name:'cust1') => #<Customer id: 1, name: "cust1", created_at: "2015-01-03 07:58:03", updated_at: "2015-01-03 07:58:03">To Add new Order2.1.1 :002 > o=c.orders.create(description:”this is first order”)To deleting a customer, and ensuring that all of its orders get deleted as well2.1.1 :003 > c.destroy
![Page 11: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/11.jpg)
Type of Association
![Page 12: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/12.jpg)
belongs_tohas_onehas_manyhas_many :throughhas_one :throughhas_and_belongs_to_many
![Page 13: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/13.jpg)
The belongs_to Association
a one-to-one connection, such that each instance of the declaring model "belongs to" one instance of the other model.
must use the singular term
![Page 14: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/14.jpg)
![Page 15: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/15.jpg)
The has_one Associationhas_one association also sets up a one-to-one connection with another
model
![Page 16: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/16.jpg)
![Page 17: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/17.jpg)
class Customer < ActiveRecord::Base has_one :order, dependent: :destroyend
class Order < ActiveRecord::Base belongs_to :customerend
c.create_order(description:"ccc")c.order
![Page 18: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/18.jpg)
The has_many Association
a one-to-many connection.the "other side" of a belongs_to association.The name of the other model is pluralized
when declaring a has_many association.
![Page 19: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/19.jpg)
![Page 20: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/20.jpg)
The has_many :through Association
a many-to-many connection
![Page 21: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/21.jpg)
![Page 22: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/22.jpg)
rails g model physician name:stringrails g model patient name:stringrails g model appointment physician_id:integer patient_id:integer
description:string
rake db:migraterails c
![Page 23: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/23.jpg)
class Physician < ActiveRecord::Base has_many :appointments has_many :patients, :through => :appointmentsend
class Patient < ActiveRecord::Base has_many :appointments has_many :physicians, :through => :appointmentsend
class Appointment < ActiveRecord::Base belongs_to :physician belongs_to :patientend
![Page 24: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/24.jpg)
2.1.1 :010 > p=Physician.find(1) => #<Physician id: 1, name: "physicain", created_at: "2015-01-04 12:19:37", updated_at: "2015-01-04 12:19:37">2.1.1 :012 > p.patients.create(name: "p2") => #<Patient id: 2, name: "p2", created_at: "2015-01-04 12:43:22", updated_at: "2015-01-04 12:43:22">2.1.1 :024 > p.appointments.where(patient_id: 2)[0].update_attributes(description:'test')
Alternatively,p.appointments.create(patient_id: 2, description: ‘this is a test description’)
2.1.1 :030 > ph=Physician.find(1) => #<Physician id: 1, name: "physicain", created_at: "2015-01-04 12:19:37", updated_at: "2015-01-04 12:19:37">2.1.1 :031 > ph.patients << Patient.all
![Page 25: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/25.jpg)
The has_one :through Association
a one-to-one connection with another model.declaring model can be matched with one instance of
another model by proceeding through a third model. if each supplier has one account, and each account is
associated with one account history, then the supplier model could look like this:
![Page 26: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/26.jpg)
![Page 27: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/27.jpg)
The has_and_belongs_to_many Association
creates a direct many-to-many connection with another model, with no intervening model.
![Page 28: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/28.jpg)
![Page 29: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/29.jpg)
Classwork 1: Create two tables husband and wife with one on one relationship and test things.
Create a rails app which should have a database named 'blog_db' in MySQL. Then do the following1. Create models Articles (title, content), Comments (comments, article_id), Tags (name)2. Article should have many comments and each comment should be associated to one article3. Each article can have many tags and each tag may be assigned to many articles.4. Create the relation such that if we delete an article then all the comments associated with that
article is also deleted5. Create a scope to query all the articles of yesterday sorted descending according to created
date
![Page 30: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/30.jpg)
Various options for relations
![Page 31: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/31.jpg)
class_namedependentpolymorphicvalidatewherethrough
![Page 32: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/32.jpg)
class_name: Controlling association scopeBy default, associations look for objects only within the current module's scope. For example:module MyApplication module Business class Supplier < ActiveRecord::Base has_one :account end class Account < ActiveRecord::Base belongs_to :supplier end endend
![Page 33: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/33.jpg)
Supplier and Account are defined in different scopes:module MyApplication module Business class Supplier < ActiveRecord::Base has_one :account end end module Billing class Account < ActiveRecord::Base belongs_to :supplier end endend
will not work!!
![Page 34: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/34.jpg)
module MyApplication module Business class Supplier < ActiveRecord::Base has_one :account, class_name: "MyApplication::Billing::Account" end end module Billing class Account < ActiveRecord::Base belongs_to :supplier, class_name: "MyApplication::Business::Supplier" end endend
![Page 35: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/35.jpg)
orif an order belongs to a customer, but the
actual name of the model containing customers is Patron, you'd set things up this way:
class Order < ActiveRecord::Base belongs_to :customer, class_name:
"Patron"end
![Page 36: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/36.jpg)
: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.
class User belongs_to :account validates :account, :presence => trueend.
![Page 37: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/37.jpg)
class Order < ActiveRecord::Base belongs_to :customer, -> { where active: true }, dependent: :destroyend
![Page 38: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/38.jpg)
Single table inheritance
![Page 39: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/39.jpg)
allows inheritance by storing the name of the class in a column that is named “type” by default.
a way to add inheritance to your models. STI lets you save different models inheriting from the
same model inside a single tableRef: http://samurails.com/tutorial/single-table-inheritance-
with-rails-4-part-1/
![Page 40: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/40.jpg)
rails new sti --no-test-frameworkrails g model animal name:string age:integer
race:stringrake db:migrate
# app/models/animal.rbclass Animal < ActiveRecord::Base belongs_to :tribe self.inheritance_column = :race
# We will need a way to know which animals # will subclass the Animal model def self.races %w(Lion WildBoar Meerkat) end
endNote that self.inheritance_column = :race is used to
specify the column for STI and is not necessary if you are using the default column type.
If you want to disable Single Table Inheritance or use the type column for something else, you can use self.inheritance_column = :fake_column.
![Page 41: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/41.jpg)
# app/models/wild_boar.rbclass WildBoar < Animalend# app/models/meerkat.rbclass Meerkat < Animalend# app/models/lion.rbclass Lion < Animalend
Lion.create(name:"himba", age:11)Meerkat.create(name:"meerkat")WildBoar.create(name:"wildboar")2.1.1 :016 > Animal.all=> # [#<Lion id: 1, name: "himba", age: "11",race:
"Lion", created_at: "2015-01-03 05:22:49", updated_at: "2015-01-03 05:22:49">,
#<Animal id: 2, name: "ananta", age: nil, race: nil, created_at: "2015-01-03 05:24:02", updated_at: "2015-01-03 05:24:02">,
#<Meerkat id: 3, name: "wildboar", age: nil, race: "Meerkat", created_at: "2015-01-03 05:25:03", updated_at: "2015-01-03 05:25:03">,
#<WildBoar id: 4, name: "wildboar", age: nil, race: "WildBoar", created_at: "2015-01-03 05:25:50", updated_at: "2015-01-03 05:25:50">]>
![Page 42: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/42.jpg)
Add scopes to the parent models for each child model
class Animal < ActiveRecord::Base scope :lions, -> { where(race: 'Lion') } scope :meerkats, -> { where(race: 'Meerkat') } scope :wild_boars, -> { where(race: 'WildBoar') }
---end
2.1.1 :001 > Animal.lions Animal Load (0.2ms) SELECT "animals".* FROM "animals" WHERE "animals"."race" = 'Lion' => #<ActiveRecord::Relation [#<Lion id: 1, name: "himba", age: "11", race: "Lion", created_at: "2015-01-03 05:22:49", updated_at: "2015-01-03 05:22:49">]>2.1.1 :002 > Animal.meerkats
![Page 43: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/43.jpg)
Polymorphic associationref: http://www.millwoodonline.co.uk/blog/polymorphic-associations-ruby-on-rails
![Page 44: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/44.jpg)
Scenario:Imagine a school or college system where both students
and teachers can add posts. The post has an author->author could be a student or
a teacher. The students and teachers can ->add many posts.
Therefore we need an association between the Student, Teacher and Post models.
![Page 45: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/45.jpg)
$ rails generate model student name:string email:string$ rails generate model teacher name:string email:string office:integer$ rails generate model post author:references{polymorphic}:index title:string
body:textNote: created the post model with the author reference set as polymorphic
and an index
![Page 46: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/46.jpg)
simplified by using the t.references formauthor:references{polymorphic}:index class CreatePosts < ActiveRecord::Migration def change
create_table :posts do |t| t.references :author, polymorphic: true,
index: true t.string :title t.text :body t.timestamps
end endend
class CreatePosts < ActiveRecord::Migration def change create_table :posts do |t| t.string :title t.text :body t.integer :author_id t.string :author_type t.timestamps end add_index :posts, :author_id endend
![Page 47: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/47.jpg)
The Post model will already be setup correctly# app/models/post.rbclass Post < ActiveRecord::Base belongs_to :author, polymorphic: trueend # app/models/student.rbclass Student < ActiveRecord::Base has_many :posts, as: :authorend
# app/models/teacher.rbclass Teacher < ActiveRecord::Base has_many :posts, as: :authorend
2.1.1 :019 > s=Student.create(name: ‘Ananta’)2.1.1 :019 > s=Student.find(1)2.1.1 :011 > p=Post.new => #<Post id: nil, author_id: nil, author_type: nil, title: nil, body: nil, created_at: nil, updated_at: nil>2.1.1 :012 > p.author= s => #<Student id: 1, name: "ananta", email: nil, created_at: "2015-01-03 07:06:51", updated_at: "2015-01-03 07:06:51">2.1.1 :013 > p.title="test title" => "test title"2.1.1 :014 > p.save2.1.1 :015 > Post.all [#<Post id: 1, author_id: 1, author_type: "Student", title: "test title", body: nil, created_at: "2015-01-03 07:08:02", updated_at: "2015-01-03 07:08:02">
![Page 48: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/48.jpg)
2.1.1 :019 > t=Teacher.create(name:"dddd") => #<Teacher id: 1, name: "dddd", email: nil, office: nil, created_at: "2015-01-03 07:15:02", updated_at: "2015-01-
03 07:15:02">2.1.1 :020 > p=Post.create(author:t, title: "this is title", body:"this is body") => #<Post id: 2, author_id: 1, author_type: "Teacher", title: "this is title", body: "this is body", created_at: "2015-01-
03 07:16:31", updated_at: "2015-01-03 07:16:31">2.1.1 :023 > Post.all => #<ActiveRecord::Relation [#<Post id: 1, author_id: 1, author_type: "Student", title: "test title", body: nil, created_at: "2015-01-03 07:08:02",
updated_at: "2015-01-03 07:08:02">, #<Post id: 2, author_id: 2, author_type: "Teacher", title: "this is title", body: "this is body", created_at: "2015-01-
03 07:16:31", updated_at: "2015-01-03 07:16:31">]>2.1.1 :024 > p= Post.find(1) => #<Post id: 1, author_id: 1, author_type: "Student", title: "test title", body: nil, created_at: "2015-01-03 07:08:02",
updated_at: "2015-01-03 07:08:02">2.1.1 :025 > p.author.name => "ananta"
![Page 49: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/49.jpg)
POlymorphic many to any association
![Page 50: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/50.jpg)
Scopes
![Page 51: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/51.jpg)
What is Scope?A scope is a subset of a collection.
![Page 52: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/52.jpg)
ScenarioYou have Users. Now, some of those Users are subscribed to your newsletter. You marked those who receive a newsletter by adding a field to the Users
Database (user.subscribed_to_newsletter = true). Naturally, you sometimes want to get those Users who are subscribed to
your newsletter.ref:
http://stackoverflow.com/questions/4869994/what-is-scope-named-scope-in-rails
![Page 53: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/53.jpg)
![Page 54: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/54.jpg)
of course, we always do this:User.where(subscribed_to_newsletter: true)
Instead of always writing this you could, however, do something like this.#File: users.rb
class User < ActiveRecord::Base scope :newsletter, where(subscribed_to_newsletter: true)end
This allows you to access your subscribers by simply doing this:User.newsletter
![Page 55: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/55.jpg)
Class methods on your model are automatically available on scopes. Assuming the following setup:class Article < ActiveRecord::Base scope :published, -> { where(published: true) } scope :featured, -> { where(featured: true) }
def self.latest_article order('published_at desc').first end
def self.titles pluck(:title) endend
We are able to call the methods like this:Article.published.featured.latest_articleArticle.featured.titles
![Page 56: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/56.jpg)
default_scopehttp://rails-bestpractices.com/posts/806-
default_scope-is-evil
![Page 57: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/57.jpg)
class Post default_scope where(published: true).order("created_at desc")end
> Post.limit(10) Post Load (3.3ms) SELECT `posts`.* FROM `posts` WHERE `posts`.`published` = 1 ORDER BY created_at desc LIMIT 10
> Post.unscoped.order("updated_at desc").limit(10) Post Load (1.9ms) SELECT `posts`.* FROM `posts` ORDER BY updated_at desc LIMIT 10
![Page 58: Active record(1)](https://reader034.vdocument.in/reader034/viewer/2022051520/58ee4eff1a28abb7698b4673/html5/thumbnails/58.jpg)
Thank you