Skip to content

Commit

Permalink
Merge pull request #6 from michael-hibbs/feature/has-one-default-support
Browse files Browse the repository at this point in the history
Allow has_one association to support default option
  • Loading branch information
Paul Ingham authored Feb 20, 2017
2 parents 4b90d95 + 4873b7f commit fc74bba
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 6 deletions.
1 change: 1 addition & 0 deletions lib/structural.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

require 'structural/version'
require 'structural/missing_attribute_error'
require 'structural/invalid_default_type_error'
require 'structural/hashifier'
require 'structural/model/definer'
require 'structural/model/descriptor'
Expand Down
4 changes: 4 additions & 0 deletions lib/structural/invalid_default_type_error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Structural
class InvalidDefaultTypeError < StandardError
end
end
15 changes: 14 additions & 1 deletion lib/structural/model/has_one.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,22 @@ module Structural
module Model
class HasOne < Association
def value_of(data)
child = data.fetch(key) { raise MissingAttributeError, key }
child = data.fetch(key, &default_value)
type.new(child) unless child.nil?
end

def default
valid_type_check(super)
end

private

def valid_type_check(v)
case v
when Hash then v
when Proc then valid_type_check(v.call)
else raise Structural::InvalidDefaultTypeError end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/structural/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Structural
VERSION = '0.1.0'
VERSION = '0.2.0'
end
56 changes: 52 additions & 4 deletions spec/lib/structural/model_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
class NestedModel
include Structural::Model
field :yak
field :name, :default => nil
field :surname, :default => nil
end

class SeparateClass
def self.as_hash
{ :name => 'Michael' }
end
end

class TestModel
Expand All @@ -20,6 +28,11 @@ class TestModel
has_one :aliased_model, :type => NestedModel
has_one :nested_model, :key => 'aliased_model'
has_one :extra_nested_model
has_one :nested_with_invalid_default, :default => nil
has_one :nested_with_hash_default, :default => { name: 'Michael' }, :type => NestedModel
has_one :nested_with_hash_proc_default, :default => Proc.new { SeparateClass.as_hash }, :type => NestedModel
has_one :nested_with_invalid_proc_default, :default => Proc.new { SeparateClass.new }, :type => NestedModel
has_one :missing_nested_without_default
has_one :test_model
has_many :nested_models

Expand Down Expand Up @@ -87,20 +100,55 @@ class ExtraNestedModel
end

describe ".has_one" do
it "allows nested models" do
it 'allows nested models' do
model.aliased_model.should be_a NestedModel
end
it "allows nested models" do

it 'allows nested models' do
model.nested_model.should be_a NestedModel
model.nested_model.yak.should eq 11
end
it "allows associations to be nested within the class" do

it 'allows associations to be nested within the class' do
model.extra_nested_model.should be_a TestModel::ExtraNestedModel
model.extra_nested_model.cats.should eq 'MIAOW'
end
it "allows recursively defined models" do

it 'allows recursively defined models' do
model.test_model.should be_a TestModel
end

it 'allows default values as a hash' do
model.nested_with_hash_default.name.should eq 'Michael'
model.nested_with_hash_default.surname.should be_nil
end

context 'when passing a Proc as a default' do
it 'allows the default' do
model.nested_with_hash_proc_default.name.should eq 'Michael'
model.nested_with_hash_default.surname.should be_nil
end

context 'when the Proc does not return a Hash' do
it 'raises an error' do
expect {
model.nested_with_invalid_proc_default
}.to raise_error(Structural::InvalidDefaultTypeError)
end
end
end

it 'fails if passed a non-hash as default' do
expect {
model.nested_with_invalid_default
}.to raise_error(Structural::InvalidDefaultTypeError)
end

it 'fails for missing associations without defaults' do
expect {
model.missing_nested_without_default
}.to raise_error(Structural::MissingAttributeError)
end
end

describe ".has_many" do
Expand Down

0 comments on commit fc74bba

Please sign in to comment.