-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Forms Refactoring -Add ability to reference single document in collec…
…tion (#512) * Forms Refactoring - Add ability to reference single document in collection From: https://eaflood.atlassian.net/browse/RUBY-693 In Wex, using Active Record, we were able to simplify a lot our logic around addresses forms by redefining the association to the address as `has_one` associations. Currently, there is no way to do the same with MongId 5.2, hence this adds some metaprogramming code that will allow a mode l to define a single object that is persisted inside a location and to override it.
- Loading branch information
Showing
6 changed files
with
124 additions
and
19 deletions.
There are no files selected for viewing
This file contains 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
48 changes: 48 additions & 0 deletions
48
app/models/concerns/waste_carriers_engine/can_reference_single_document_in_collection.rb
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# frozen_string_literal: true | ||
|
||
# This module's aim is to implement a way to reference a single document in a | ||
# collection so that they can then be treated as `has_one` associations. | ||
# In projects using ActiveRecord like WEX we achieve the same functionality | ||
# thanks to ActiveRecord's Relation ability to specify custom associations using | ||
# default scopes. But because here we are using an old version of MongoDB, we | ||
# are also stuck with a version of Mongoid which does not have this ability. | ||
module WasteCarriersEngine | ||
module CanReferenceSingleDocumentInCollection | ||
extend ActiveSupport::Concern | ||
|
||
class_methods do | ||
def reference_one(attribute_name, collection:, find_by:) | ||
define_method(attribute_name) do | ||
retrieve_attribute(attribute_name, collection, find_by) | ||
end | ||
|
||
define_method("#{attribute_name}=") do |new_object| | ||
assign_attribute(attribute_name, collection, new_object) | ||
end | ||
end | ||
end | ||
|
||
included do | ||
def retrieve_attribute(attribute_name, collection, find_by) | ||
instance_variable_get("@#{attribute_name}") || | ||
fetch_attribute(collection, find_by) | ||
end | ||
|
||
# rubocop:disable Lint/UnusedMethodArgument | ||
def assign_attribute(attribute_name, collection, new_object) | ||
send(attribute_name)&.delete | ||
|
||
instance_eval("#{collection} << new_object", __FILE__, __LINE__) | ||
|
||
instance_variable_set("@#{attribute_name}", nil) | ||
end | ||
# rubocop:enable Lint/UnusedMethodArgument | ||
|
||
def fetch_attribute(collection, find_by) | ||
criteria = instance_eval("#{collection}.criteria", __FILE__, __LINE__) | ||
|
||
criteria.where(find_by).first | ||
end | ||
end | ||
end | ||
end |
This file contains 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
This file contains 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
This file contains 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
34 changes: 34 additions & 0 deletions
34
spec/support/shared_examples/can_reference_single_document_in_collection.rb
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.shared_examples "Can reference single document in collection" do |subject_lambda, attribute, object_from_collection, new_object_for_collection, collection| | ||
subject { instance_eval(&subject_lambda) } | ||
|
||
describe ".reference_one" do | ||
it "defines an attr getter for the given attribute" do | ||
expect(subject).to respond_to(attribute.to_s) | ||
end | ||
|
||
it "defines an attr setter for the given attribute" do | ||
expect(subject).to respond_to("#{attribute}=") | ||
end | ||
end | ||
|
||
describe "##{attribute}" do | ||
it "returns the correct object from the collection" do | ||
expect(subject.send(attribute)).to eq(instance_eval(&object_from_collection)) | ||
end | ||
end | ||
|
||
describe "##{attribute}=" do | ||
it "updates the object's collection with the new object" do | ||
size = subject.send(collection).size | ||
|
||
expect(subject.send(collection)).to_not include(new_object_for_collection) | ||
|
||
subject.send("#{attribute}=", new_object_for_collection) | ||
|
||
expect(subject.send(collection)).to include(new_object_for_collection) | ||
expect(subject.send(collection).size).to eq(size) | ||
end | ||
end | ||
end |