Hinweis: Dies ist nur zu Erbauzwecken und kann unbeabsichtigte Folgen haben, die möglicherweise schwer zu debuggen sind.
Sie können die Virtus::InstanceMethods::Constructor
wie so überschreiben, wenn Sie wirklich wollen:
module VirtusOverride
def self.included(base)
raise "#{base.name} must include Virtus.model prior to including VirtusOverride" unless base.included_modules.include?(Virtus::InstanceMethods)
end
def initialize(*attributes)
super(construct(attributes))
end
private
def construct(attributes)
return attributes.first if valid_constructor?(attributes)
build_attributes_from_array(attributes)
end
def valid_constructor?(attributes)
return false unless attributes.count == 1
constructor = attributes.first
constructor.is_a?(Hash) &&
!(attribute_set.flat_map {|a| [a.name,a.name.to_s]} & constructor.keys).empty?
end
def build_attributes_from_array(attributes)
attribute_set.map(&:name).zip(attributes).to_h
end
end
Dann ist es enthalten, wie
benötigt
class Account
include Virtus.model
include VirtusOverride
attribute :id, String
attribute :contact, Hash
end
Jetzt können Sie entweder die Optionen Positions auf die Definition der Attribute übergeben (zB Account.new(id,contact)
) oder als Hash
.
Beispiel:
Account.new("1234",{name: 'mnky'})
#=> #<Account:0x2a071b8 @id="1234", @contact={:name=>"mnky"}>
Account.new(id: "1234", contact: {name: 'mnky'})
#=> #<Account:0x2b42b78 @id="1234", @contact={:name=>"mnky"}>
Sie könnten Virtus::InstanceMethods::Constructor
Affen Patch gleich auszuführen, aber ich bin kein großer Fan von dieser Philosophie, wie es Verwirrung zu anderen Entwicklern hinzufügen könnte, wo, wie das Modul Inklusion Granularität und Klarheit bietet.
aktualisieren
class Account
include Virtus.model
include VirtusOverride
attribute :id, String
attribute :contact, Contact
end
class Contact
include Virtus.model
include VirtusOverride
attribute :id, String
end
Account.new(id: '1234', contact: '123456', name: 'Bob Jones')
#=> #<Account:0x2bcb060 @id="1234", @contact=#<Contact:0x2bc9c50 @id="123456">, @name="Bob Jones">
Account.new('1234', '123456', 'Bob Jones')
#=> #<Account:0x2faea00 @id="1234", @contact=#<Contact:0x2fae880 @id="123456">, @name="Bob Jones">
Account.new('id' => '1234', 'contact' => '123456', 'name' => 'Bob Jones')
#=> #<Account:0x2faffc0 @id="1234", @contact=#<Contact:0x2fafb70 @id="123456">, @name="Bob Jones">
Das ist genial, und ist sooo nah an, was für im suchen. Ich habe meinen Beispielcode aktualisiert, mit dem die Daten konsistent aussehen werden. Ein letzter Blick? –
@JaisonBrooks haben Sie das tatsächlich versucht, weil es wie erwartet funktioniert. Ich habe mit einem Beispiel aktualisiert – engineersmnky
Ich habe es versucht, ich empfange den folgenden Fehler. '' 'undefinierte Methode' Schlüssel? ' für "1234": String'''. Ihre erste Beispielausgabe ist perfekt. Ich werde den Array-Typ-Eintrag nicht verwenden. da die Daten ein Hash sein werden, es sei denn, diese einzelne Zeichenfolge. Nochmals vielen Dank für diese Hilfe/rette mich. –