Created
February 1, 2016 19:24
-
-
Save RobinDaugherty/480d39f8e43561684054 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
module Concerns | |
module HasOneAutoCreated | |
extend ActiveSupport::Concern | |
module ClassMethods | |
def has_one_auto_created(association_name, options = {}) | |
has_one association_name, options | |
alias_method "existing_#{association_name}", association_name | |
# Returns the existing associated record, or a newly-created one. | |
define_method(association_name) do | |
transaction do | |
send("existing_#{association_name}") || send("create_#{association_name}") | |
end | |
end | |
# Yields with an existing or new association record, saving the record after the block completes. | |
# All of this happens inside of a single database transaction. | |
define_method("updating_#{association_name}") do |&block| | |
transaction do | |
record = send("existing_#{association_name}") || send("build_#{association_name}") | |
block.call(record) | |
record.save! | |
end | |
end | |
end | |
end | |
end | |
end |
This file contains hidden or 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
class Gadget < ActiveRecord::Base | |
include Concerns::HasOneAutoCreated | |
has_one_auto_created :gadget_status | |
end |
This file contains hidden or 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
require 'rails_helper' | |
describe Gadget, type: :model do | |
describe '#gadget_part' do | |
subject { FactoryGirl.create(:gadget) } | |
context 'with an existing record' do | |
let!(:gadget_part) { FactoryGirl.create(:gadget_part, gadget: subject) } | |
it 'returns the existing record' do | |
expect(subject.gadget_part).to eq(gadget_part) | |
end | |
end | |
context 'without existing record' do | |
it 'creates a new record' do | |
expect(subject.gadget_part).to be_kind_of(GadgetPart) | |
expect(subject.gadget_part).to be_persisted | |
expect(subject.gadget_part).to have_attributes(gadget_id: subject.id) | |
end | |
end | |
end | |
describe '#updating_gadget_part' do | |
subject { FactoryGirl.create(:gadget) } | |
context 'with an existing record' do | |
let!(:gadget_part) { FactoryGirl.create(:gadget_part, gadget: subject) } | |
it 'yields the existing record' do | |
expect { |b| subject.updating_gadget_part(&b) } | |
.to yield_with_args(gadget_part) | |
end | |
it 'saves the new record after yielding it' do | |
subject.updating_gadget_part do |gadget_part| | |
expect(gadget_part).to receive(:save!) | |
end | |
end | |
end | |
context 'without existing record' do | |
it 'yields a new record' do | |
fake_gadget_part = double('gadget_part', save!: true) | |
allow(subject).to receive(:build_gadget_part).and_return(fake_gadget_part) | |
expect { |b| subject.updating_gadget_part(&b) } | |
.to yield_with_args(fake_gadget_part) | |
end | |
it 'creates a correctly-formed GadgetPart' do | |
subject.updating_gadget_part do |gadget_part| | |
expect(gadget_part).to be_kind_of(GadgetPart) | |
expect(gadget_part).to_not be_persisted | |
expect(gadget_part).to have_attributes(gadget_id: subject.id) | |
end | |
end | |
it 'saves the new record after yielding it' do | |
subject.updating_gadget_part do |gadget_part| | |
expect(gadget_part).to receive(:save!) | |
end | |
end | |
end | |
end | |
end |
This file contains hidden or 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
class GadgetPart < ActiveRecord::Base | |
belongs_to :gadget | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment