Skip to content

Commit 68c59d7

Browse files
committed
use the module by including it instead of extending it
1 parent 6eab554 commit 68c59d7

3 files changed

Lines changed: 78 additions & 71 deletions

File tree

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ A simple module to provide value objects semantics to a class.
1616
require 'value_object'
1717

1818
class Point
19-
extend ValueObject
19+
include ValueObject
2020
fields :x, :y
2121
end
2222

@@ -39,7 +39,7 @@ point.x = 3
3939
require 'value_object'
4040

4141
class Point
42-
extend ValueObject
42+
include ValueObject
4343
fields :x, :y
4444
end
4545

@@ -71,7 +71,7 @@ a_point.eql?(a_different_point)
7171
require 'value_object'
7272

7373
class Point
74-
extend ValueObject
74+
include ValueObject
7575
fields :x, :y
7676
end
7777

@@ -99,7 +99,7 @@ You can declare invariants to restrict field values on initialization
9999
require 'value_object'
100100

101101
class Point
102-
extend ValueObject
102+
include ValueObject
103103
fields :x, :y
104104
invariants :x_less_than_y, :inside_first_quadrant
105105

lib/value_object.rb

Lines changed: 71 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,96 @@
11
require 'exceptions'
22

33
module ValueObject
4-
def fields(*names)
5-
raise NotDeclaredFields.new() if names.empty?()
64

7-
attr_reader(*names)
5+
def self.included(base)
6+
base.extend(ClassMethods)
7+
end
88

9-
define_method(:initialize) do |*values|
10-
check_fields_are_initialized(values)
11-
set_instance_variables(values)
12-
check_invariants()
13-
end
9+
module ClassMethods
10+
def fields(*names)
11+
raise NotDeclaredFields.new() if names.empty?()
1412

15-
define_method(:eql?) do |other|
16-
self.class == other.class && values == other.values
17-
end
13+
attr_reader(*names)
1814

19-
define_method(:==) do |other|
20-
eql?(other)
21-
end
15+
define_method(:initialize) do |*values|
16+
check_fields_are_initialized(values)
17+
set_instance_variables(values)
18+
check_invariants()
19+
end
2220

23-
define_method(:hash) do
24-
self.class.hash ^ values.hash
25-
end
21+
define_method(:eql?) do |other|
22+
self.class == other.class && values == other.values
23+
end
2624

27-
define_method(:values) do
28-
names.map { |field| send(field) }
29-
end
30-
protected(:values)
25+
define_method(:==) do |other|
26+
eql?(other)
27+
end
3128

32-
define_method(:check_invariants) do
33-
end
34-
private(:check_invariants)
29+
define_method(:hash) do
30+
self.class.hash ^ values.hash
31+
end
3532

36-
define_method(:check_fields_are_initialized) do |values|
37-
raise WrongNumberOfArguments.new(names.length, values.length) unless arguments_number_is_right?(values)
38-
raise FieldWithoutValue.new(uninitialized_fields_names(values)) unless all_fields_initialized?(values)
39-
end
40-
private(:check_fields_are_initialized)
33+
define_method(:values) do
34+
names.map { |field| send(field) }
35+
end
36+
protected(:values)
4137

42-
define_method(:arguments_number_is_right?) do |values|
43-
fields_number = names.length
44-
arguments_number = values.length
45-
values.length == names.length
46-
end
47-
private(:arguments_number_is_right?)
38+
define_method(:check_invariants) do
39+
end
40+
private(:check_invariants)
4841

49-
define_method(:uninitialized_fields) do |values|
50-
names.zip(values).select { |name, value| value.nil? }
51-
end
52-
private(:uninitialized_fields)
42+
define_method(:check_fields_are_initialized) do |values|
43+
raise WrongNumberOfArguments.new(names.length, values.length) unless arguments_number_is_right?(values)
44+
raise FieldWithoutValue.new(uninitialized_fields_names(values)) unless all_fields_initialized?(values)
45+
end
46+
private(:check_fields_are_initialized)
5347

54-
define_method(:all_fields_initialized?) do |values|
55-
uninitialized_fields(values).empty?
56-
end
57-
private(:all_fields_initialized?)
48+
define_method(:arguments_number_is_right?) do |values|
49+
fields_number = names.length
50+
arguments_number = values.length
51+
values.length == names.length
52+
end
53+
private(:arguments_number_is_right?)
5854

59-
define_method(:uninitialized_fields_names) do |values|
60-
uninitialized_fields(values).map { |field| field.first }
61-
end
62-
private(:uninitialized_fields_names)
55+
define_method(:uninitialized_fields) do |values|
56+
names.zip(values).select { |name, value| value.nil? }
57+
end
58+
private(:uninitialized_fields)
6359

64-
define_method(:set_instance_variables) do |values|
65-
names.zip(values) do |name, value|
66-
instance_variable_set(:"@#{name}", value)
60+
define_method(:all_fields_initialized?) do |values|
61+
uninitialized_fields(values).empty?
6762
end
68-
end
69-
private(:set_instance_variables)
70-
end
63+
private(:all_fields_initialized?)
64+
65+
define_method(:uninitialized_fields_names) do |values|
66+
uninitialized_fields(values).map { |field| field.first }
67+
end
68+
private(:uninitialized_fields_names)
7169

72-
def invariants(*predicate_symbols)
73-
define_method(:check_invariants) do
74-
predicate_symbols.each do |predicate_symbol|
75-
valid = invariant_holds?(predicate_symbol)
76-
raise ViolatedInvariant.new(predicate_symbol, self.values) unless valid
70+
define_method(:set_instance_variables) do |values|
71+
names.zip(values) do |name, value|
72+
instance_variable_set(:"@#{name}", value)
73+
end
7774
end
75+
private(:set_instance_variables)
7876
end
7977

80-
define_method(:invariant_holds?) do |predicate_symbol|
81-
begin
82-
valid = send(predicate_symbol)
83-
rescue
84-
raise NotImplementedInvariant.new(predicate_symbol)
78+
def invariants(*predicate_symbols)
79+
define_method(:check_invariants) do
80+
predicate_symbols.each do |predicate_symbol|
81+
valid = invariant_holds?(predicate_symbol)
82+
raise ViolatedInvariant.new(predicate_symbol, self.values) unless valid
83+
end
84+
end
85+
86+
define_method(:invariant_holds?) do |predicate_symbol|
87+
begin
88+
valid = send(predicate_symbol)
89+
rescue
90+
raise NotImplementedInvariant.new(predicate_symbol)
91+
end
8592
end
93+
private(:invariant_holds?)
8694
end
87-
private(:invariant_holds?)
8895
end
8996
end

spec/value_object_spec.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
describe "standard behavior" do
77
class Point
8-
extend ValueObject
8+
include ValueObject
99
fields :x, :y
1010
end
1111

@@ -62,7 +62,7 @@ class Point
6262

6363
it "must have number of values equal to number of fields" do
6464
class Point
65-
extend ValueObject
65+
include ValueObject
6666
fields :x, :y
6767
end
6868

@@ -80,7 +80,7 @@ class Point
8080
describe "forcing invariants" do
8181
it "forces declared invariants" do
8282
class Point
83-
extend ValueObject
83+
include ValueObject
8484
fields :x, :y
8585
invariants :x_less_than_y, :inside_first_quadrant
8686

0 commit comments

Comments
 (0)