Skip to content
Merged
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ The `Day` class will gain the following methods:
`nil` when a record does not exist.
- `.find_by`: finds the first record matching the specified conditions. If no
record is found, returns `nil`.
- `find_by!` behaves like `find_by` but raises a
`StaticAssociation::RecordNotFound` error if no record is found.
- `.where`: accepts an array of ids and returns all records with matching ids.

### Associations
Expand Down
7 changes: 7 additions & 0 deletions lib/static_association.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ def find_by(**args)
all.find { |record| matches_attributes?(record: record, attributes: args) }
end

def find_by!(**args)
find_by(**args) or raise RecordNotFound.new(
"Couldn't find #{name} with " +
args.map { |k, v| "#{k}=#{v}" }.join(", ")
)
end

def record(settings, &block)
settings.assert_valid_keys(:id)
id = settings.fetch(:id)
Expand Down
111 changes: 110 additions & 1 deletion spec/static_association_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,16 @@ class AssociationClass
)
end
end

context "when argument is numeric string" do
it "returns the record" do
record = DummyClass.record(id: 1)

found_record = DummyClass.find("1")

expect(found_record).to eq(record)
end
end
end

describe ".find_by_id" do
Expand Down Expand Up @@ -264,7 +274,7 @@ class AssociationClass
end

context "with undefined attributes" do
it "raises a StaticAssociation::UndefinedAttribute" do
it "raises an error" do
DummyClass.record(id: 1)

expect {
Expand All @@ -286,6 +296,105 @@ class AssociationClass
end
end

describe ".find_by!" do
context "when record exists with the specified attribute value" do
it "returns the record" do
record1 = DummyClass.record(id: 1) do |r|
r.name = "foo"
end
_record2 = DummyClass.record(id: 2) do |r|
r.name = "bar"
end

found_record = DummyClass.find_by!(name: "foo")

expect(found_record).to eq(record1)
end
end

context "when no record exists that matches the specified attribute value" do
it "raises an error" do
DummyClass.record(id: 1) do |r|
r.name = "foo"
end

expect {
DummyClass.find_by!(name: "bar")
}.to raise_error(
StaticAssociation::RecordNotFound,
"Couldn't find DummyClass with name=bar"
)
end
end

context "when multiple records match the specified attribute value" do
it "returns the first matching record" do
record1 = DummyClass.record(id: 1) do |r|
r.name = "foo"
end
_record2 = DummyClass.record(id: 2) do |r|
r.name = "foo"
end

found_record = DummyClass.find_by!(name: "foo")

expect(found_record).to eq(record1)
end
end

context "when specifying multiple attribute values" do
it "returns the record matching all attributes" do
_record1 = DummyClass.record(id: 1) do |r|
r.name = "foo"
end
record2 = DummyClass.record(id: 2) do |r|
r.name = "foo"
end

found_record = DummyClass.find_by!(id: 2, name: "foo")

expect(found_record).to eq(record2)
end
end

context "when specifying multiple attribute values but no record " \
"matches all attributes" do
it "raises an error" do
_record1 = DummyClass.record(id: 1) do |r|
r.name = "foo"
end

expect {
DummyClass.find_by!(id: 1, name: "bar")
}.to raise_error(
StaticAssociation::RecordNotFound,
"Couldn't find DummyClass with id=1, name=bar"
)
end
end

context "with undefined attributes" do
it "raises a StaticAssociation::UndefinedAttribute" do
DummyClass.record(id: 1)

expect {
DummyClass.find_by!(undefined_attribute: 1)
}.to raise_error(
StaticAssociation::UndefinedAttribute,
"Undefined attribute 'undefined_attribute'"
)
end
end

context "with no attributes" do
it "raises a StaticAssociation::ArgumentError" do
expect {
DummyClass.find_by!
}.to raise_error(StaticAssociation::ArgumentError)
end
end
end

describe ".belongs_to_static" do
it "defines a reader method for the association" do
associated_class = AssociationClass.new
Expand Down