Skip to content
This repository has been archived by the owner on Jun 2, 2021. It is now read-only.

New boolean attribute syntax #25

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions lib/tainbox/attribute_definer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@ def initialize(klass, attribute_name, requested_type, requested_args)
def define_getter
klass.tainbox_register_attribute(attribute_name)
attribute = attribute_name
type = requested_type

klass.tainbox_layer.instance_eval do
define_method(attribute) do
value = instance_variable_get(:"@tainbox_#{attribute}")
value.is_a?(Tainbox::DeferredValue) ? instance_exec(&value.proc) : value
end

alias_method("#{attribute}?", attribute) if type == :Boolean
end
end

Expand All @@ -40,6 +43,13 @@ def define_setter
instance_variable_set(:"@tainbox_#{attribute}", value)
end

if type == :Boolean
define_method("#{attribute}!") do
send("#{attribute}=", true)
self
end
end

define_method("tainbox_set_default_#{attribute}") do
if args.has_key?(:default)
tainbox_register_attribute_provided(attribute)
Expand Down
12 changes: 8 additions & 4 deletions lib/tainbox/class_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@ def tainbox_initializer_suppressed?
attr_reader :tainbox_initializer_suppressed

def attribute(name, type = nil, **args)
name = name.to_s
args = args.dup
define_reader = args.fetch(:reader, true)
define_writer = args.fetch(:writer, true)

if name.end_with?('?')
name.chop!
type = :Boolean
end

definer = Tainbox::AttributeDefiner.new(self, name, type, args)
definer.define_getter if define_reader
definer.define_setter if define_writer
definer.define_getter if args.fetch(:reader, true)
definer.define_setter if args.fetch(:writer, true)
end

def suppress_tainbox_initializer!
Expand Down
78 changes: 69 additions & 9 deletions spec/tainbox_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,95 @@

person = Class.new do
include Tainbox
attribute :name, default: 'Oliver'

attribute :name, default: 'Anonymous'
attribute :age, Integer
attribute :admin?, default: false

def name
super.strip
end
end

person = person.new(name: ' John ', 'age' => '24')
person = person.new(name: ' John ', 'age' => '24', 'admin' => '1')

expect(person.name).to eq('John')
expect(person.age).to eq(24)
expect(person.attribute_provided?(:name)).to be_truthy

expect(person.age).to eq(24)
expect(person.attribute_provided?(:age)).to be_truthy

expect(person.admin).to eq(true)
expect(person.admin?).to eq(true)
expect(person.attribute_provided?(:admin)).to be_truthy

expect(person.attributes).to eq(name: 'John', age: 24, admin: true)
expect(person.as_json).to eq('name' => 'John', 'age' => 24, 'admin' => true)

person.attributes = {}
expect(person.name).to eq('Oliver')
expect(person.age).to be_nil

expect(person.name).to eq('Anonymous')
expect(person.attribute_provided?(:name)).to be_truthy

expect(person.age).to be_nil
expect(person.attribute_provided?(:age)).to be_falsey

expect(person.attributes).to eq(name: 'Oliver', age: nil)
expect(person.admin).to eq(false)
expect(person.admin?).to eq(false)
expect(person.attribute_provided?(:admin)).to be_truthy

expect(person.attributes).to eq(name: 'Anonymous', age: nil, admin: false)
expect(person.as_json).to eq('name' => 'Anonymous', 'age' => nil, 'admin' => false)

person.age = 10

expect(person.age).to eq(10)
expect(person.attribute_provided?(:age)).to be_truthy

expect(person.as_json).to eq('name' => 'Oliver', 'age' => 10)
expect(person.as_json(only: :name)).to eq('name' => 'Oliver')
expect(person.as_json(except: :name)).to eq('age' => 10)
expect(person.admin!).to eq(person)

expect(person.admin).to eq(true)
expect(person.admin?).to eq(true)
expect(person.attribute_provided?(:admin)).to be_truthy

person.name = ' John '

expect(person.name).to eq('John')
expect(person.attribute_provided?(:name)).to be_truthy

expect(person.as_json).to eq('name' => 'John', 'age' => 10, 'admin' => true)
expect(person.as_json(only: :name)).to eq('name' => 'John')
expect(person.as_json(except: :name)).to eq('age' => 10, 'admin' => true)
end

it 'supports old syntax' do
person = Class.new do
include Tainbox

attribute :admin, :Boolean
end

person = person.new('admin' => '1')

expect(person.admin).to eq(true)
expect(person.attribute_provided?(:admin)).to be_truthy

expect(person.attributes).to eq(admin: true)
expect(person.as_json).to eq('admin' => true)

person.attributes = {}

expect(person.admin).to eq(nil)
expect(person.attribute_provided?(:admin)).to be_falsey

expect(person.attributes).to eq(admin: nil)
expect(person.as_json).to eq('admin' => nil)

person.admin = true

expect(person.admin).to eq(true)
expect(person.admin?).to eq(true)
expect(person.attribute_provided?(:admin)).to be_truthy
end

it 'accepts objects which respond to #to_h as attributes' do
Expand Down