Setup
Generate models.
rails g model author name:string
rails g model book title:string author:references
bundle exec rake db:migrate
Add associations:
in author.rb
has_many :books
in book.rb
belongs_to :author
in seeds.rb
author = Author.create(name: 'Some author')
author.books.create(title: 'Some book 1')
author.books.create(title: 'Another Book 1')
Seed database:
bundle exec rake db:seed
The Problem
Fire up console:
rails c
Get all books by first author:
first_author = Author.first
all_books = first_author.books
Add a new book to that author without saving it:
some_new_book = first_author.books.new(title: 'A test book')
Lets see books in all_books collection:
all_books.each do |book|
puts book.title
end
The unsaved book's title appears also which it shouldn't!
The Fix
add scope in book.rb
scope :persisted, -> { where "id IS NOT NULL" }
Now we can fetch only persisted books:
first_author = Author.first
all_books = first_author.books.persisted
Fix 2
Here we 'll use an active record associations extension to fetch only persisted data.
Create the file lib/extensions/active_record_extensions.rb
and add this:
module Extensions::ActiveRecordExtensions
def persisted
select(&:persisted?)
end
end
in author.rb
change the has_many :books
line to this:
has_many :books, extend: Extensions::ActiveRecordExtensions
Make sure the lib path is auto loaded by adding
config.autoload_paths << Rails.root.join('lib')
in application.rb
Finally we can fetch only persisted books with the same way:
first_author = Author.first
all_books = first_author.books.persisted