Skip to content

Instantly share code, notes, and snippets.

@marinados
Last active April 6, 2016 08:46
Show Gist options
  • Save marinados/33e3ed2bca7d627af4b62e40ecb20720 to your computer and use it in GitHub Desktop.
Save marinados/33e3ed2bca7d627af4b62e40ecb20720 to your computer and use it in GitHub Desktop.

Nested Queries

class Book < ActiveRecord::Base
  belongs_to :author
  has_many :reviews
end

class Author < ActiveRecord::Base
  has_many :books
end

class Review < ActiveRecord::Base
  belongs_to :book
end

book_ids = Book.where(publish_year: '2015').map(&:id)
# => SELECT "books".* FROM "books" WHERE (publish_year = '2015')

reviews = Review.where(publish_date: '2015-11-15',
                       book_ids: book_ids).to_a
# => SELECT "reviews".* FROM "reviews" WHERE "reviews"."publish_date" = '2015-11-15' AND "reviews"."book_ids" IN (1, 2, 3)

books = Book.where(publish_year: '2015')
# => ActiveRecord::Relation

# as a search parameter we could use an active record relation
reviews = Review.where(publish_date: '2015-11-15', book: books).to_a
# SELECT "reviews".* FROM "reviews" WHERE "reviews"."publish_date" = '2015-11-15' AND "reviews"."book_id" IN (SELECT "books"."id" FROM "books" WHERE "books"."publish_year" = '2015')

DRY scopes

class Review < ActiveRecord::Base
  belongs_to :book

  scope :approved, ->{ where(approved: true) }
end

# to get books with approved reviews
books = Book.where(publish_year: '2015')
            .includes(:reviews)
            .references(:reviews)
            .where('reviews.approved = ?', true )
            .to_a
            
books = Book.where(publish_year: '2015')
            .includes(:reviews)
            .references(:reviews)
            .merge(Review.approved) # => .merge scope feature!
            .to_a
# => SELECT #long books and reviews column select# FROM "books" LEFT OUTER JOIN "reviews" ON "reviews"."book_id" = "books"."id" WHERE "books"."publish_year" = '2015' AND (reviews.approved = 't')
```

# `.unscoped` method

`authors = Author.unscoped.where(last_name: 'Smith').take(5)`- removes all default scopes

# `.touch` method
To update a single timestamp column on an ActiveRecord object, `touch` is a great option. 
This method can accept the column name which should be updated in addition to an object’s `:updated_at` (if present).
```
class ReviewsController < ApplicationController
  def show
    @review = Review.find(params[:id])
    @review.touch(:last_viewed_at)
  end
end
```

# `.changes` method
```
review = Review.find(1)
review.book_id = 5
review.changes
# => {"book_id"=>[4, 5]}

Each key in the changes hash maps to a record’s attribute. The value of each key is an Array with two elements: what the attribute value used to be, and what it is now.

.changed?method

review = Review.find(1)
review.book_id = 5
review.changed?
# => true

<attribute>_was method

review = Review.find(1)
review.status = 'Approved'
review.status_was
# => 'Pending'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment