Red.git | docs/coverage/report-data/ | MetamodelX-Red-Dirtable.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>RaCoCo result: MetamodelX::Red::Dirtable</title>
<link rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
crossorigin="anonymous">
<style>
pre.code::before {
counter-reset: listing;
}
pre.code span {
counter-increment: listing;
}
pre.code span::before {
content: counter(listing) ". ";
}
.coverage-green {
background-color: #32CD32;
/*color-blind
background-color: #00CED1;
/**/
}
.coverage-red {
background-color: #fa8072;
}
.coverage-purple {
background-color: #9370DB;
}
</style>
</head>
<body>
<div class="container">
<div class="row mt-5 mb-3">
<div class="col-12">
<div class="page-header">
<h1>MetamodelX::Red::Dirtable 60.5%</h1>
</div>
</div>
</div>
<div class="row justify-content-md-center">
<div class="col-md-10">
<pre class="code">
<span class="coverage-green">use nqp;</span>
<span class="coverage-no">use Red::Attr::Column;</span>
<span class="coverage-no">use Red::Attr::Relationship;</span>
<span class="coverage-no"></span>
<span class="coverage-no">=head2 MetamodelX::Red::Dirtable</span>
<span class="coverage-no"></span>
<span class="coverage-green">unit role MetamodelX::Red::Dirtable;</span>
<span class="coverage-no"></span>
<span class="coverage-no">has %.dirty-cols{Mu} is rw;</span>
<span class="coverage-no">has $!col-data-attr;</span>
<span class="coverage-no"></span>
<span class="coverage-green">method col-data-attr(|) {</span>
<span class="coverage-green"> $!col-data-attr;</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
<span class="coverage-green">sub col-data-attr-build(|){</span>
<span class="coverage-green"> {}</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
<span class="coverage-no">has $!dirty-cols-attr;</span>
<span class="coverage-no"></span>
<span class="coverage-red">method dirty-cols-attr(|) {</span>
<span class="coverage-red"> $!dirty-cols-attr;</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
<span class="coverage-green">sub dirty-cols-attr-build(|) {</span>
<span class="coverage-green"> SetHash.new</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
<span class="coverage-red">has $!dirty-old-values-attr;</span>
<span class="coverage-no"></span>
<span class="coverage-green">method dirty-old-values-attr(|) {</span>
<span class="coverage-green"> $!dirty-old-values-attr;</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
<span class="coverage-green">sub dirty-old-values-attr-build(|) {</span>
<span class="coverage-green"> {}</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
<span class="coverage-green">method set-helper-attrs(Mu \type) {</span>
<span class="coverage-green"> my %attr = type.^attributes.map( -> $a { $a.name => $a }).Hash;</span>
<span class="coverage-green"> if %attr<%!___COLUMNS_DATA___> -> $a {</span>
<span class="coverage-green"> $!col-data-attr //= $a;</span>
<span class="coverage-no"> }</span>
<span class="coverage-red"> else {</span>
<span class="coverage-green"> $!col-data-attr = Attribute.new: :name<%!___COLUMNS_DATA___>, :package(type), :type(Any), :!has_accessor;</span>
<span class="coverage-green"> $!col-data-attr.set_build: &col-data-attr-build;</span>
<span class="coverage-green"> type.^add_attribute: $!col-data-attr;</span>
<span class="coverage-no"> }</span>
<span class="coverage-green"> if %attr<%!___DIRTY_COLS_DATA___> -> $a {</span>
<span class="coverage-green"> $!dirty-cols-attr //= $a;</span>
<span class="coverage-no"> }</span>
<span class="coverage-red"> else {</span>
<span class="coverage-green"> $!dirty-cols-attr = Attribute.new: :name<%!___DIRTY_COLS_DATA___>, :package(type), :type(Any), :!has_accessor;</span>
<span class="coverage-green"> $!dirty-cols-attr.set_build: &dirty-cols-attr-build;</span>
<span class="coverage-green"> type.^add_attribute: $!dirty-cols-attr;</span>
<span class="coverage-no"> }</span>
<span class="coverage-green"> if %attr<%!___DIRTY_OLD_DATA___> -> $a {</span>
<span class="coverage-green"> $!dirty-old-values-attr //= $a;</span>
<span class="coverage-no"> }</span>
<span class="coverage-red"> else {</span>
<span class="coverage-green"> $!dirty-old-values-attr = Attribute.new: :name<%!___DIRTY_OLD_DATA___>, :package(type), :type(Any), :!has_accessor;</span>
<span class="coverage-green"> $!dirty-old-values-attr.set_build: &dirty-old-values-attr-build;</span>
<span class="coverage-green"> type.^add_attribute: $!dirty-old-values-attr;</span>
<span class="coverage-no"> }</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
<span class="coverage-red">submethod !TWEAK_pr(\instance: *%data) is rw {</span>
<span class="coverage-red"> my @columns = instance.^columns;</span>
<span class="coverage-no"></span>
<span class="coverage-red"> my %new = |@columns.map: {</span>
<span class="coverage-red"> my Mu $built := .build;</span>
<span class="coverage-red"> $built := $built.(self.WHAT, Mu) if $built ~~ Method;</span>
<span class="coverage-red"> next if $built =:= Mu;</span>
<span class="coverage-red"> if instance.^is-id: $_ {</span>
<span class="coverage-red"> instance.^set-id: .name => $built</span>
<span class="coverage-no"> }</span>
<span class="coverage-red"> .column.attr-name => $built</span>
<span class="coverage-no"> };</span>
<span class="coverage-no"></span>
<span class="coverage-red"> for %data.kv -> $k, $v { %new{$k} = $v }</span>
<span class="coverage-no"></span>
<span class="coverage-red"> my $col-data-attr := self.^col-data-attr;</span>
<span class="coverage-red"> my $dirty-old-values-attr := self.^dirty-old-values-attr;</span>
<span class="coverage-red"> $col-data-attr.set_value: instance, %new;</span>
<span class="coverage-red"> for @columns -> \col {</span>
<span class="coverage-red"> my \proxy = Proxy.new:</span>
<span class="coverage-red"> FETCH => method {</span>
<span class="coverage-red"> $col-data-attr.get_value(instance).{ col.column.attr-name }</span>
<span class="coverage-no"> },</span>
<span class="coverage-red"> STORE => method (\value) is hidden-from-backtrace {</span>
<span class="coverage-red"> die X::Assignment::RO.new(value => $col-data-attr.get_value(instance).{ col.column.attr-name }) unless col.rw;</span>
<span class="coverage-red"> die X::TypeCheck::Assignment.new(symbol => col.name, got => value, expected => col.type) unless value ~~ col.type;</span>
<span class="coverage-red"> if instance.^is-id: col {</span>
<span class="coverage-red"> instance.^set-id: col.name => value</span>
<span class="coverage-no"> }</span>
<span class="coverage-red"> instance.^set-dirty: col;</span>
<span class="coverage-red"> $dirty-old-values-attr.get_value(instance).{ col.column.attr-name } =</span>
<span class="coverage-red"> $col-data-attr.get_value(instance).{ col.column.attr-name };</span>
<span class="coverage-red"> $col-data-attr.get_value(instance).{ col.column.attr-name } = value</span>
<span class="coverage-no"> }</span>
<span class="coverage-no"> #use nqp;</span>
<span class="coverage-no"> #nqp::bindattr(nqp::decont(instance), self.WHAT, col.name, proxy);</span>
<span class="coverage-red"> col.set_value: instance<>, proxy</span>
<span class="coverage-no"> }</span>
<span class="coverage-red"> for self.^attributes -> $attr {</span>
<span class="coverage-red"> with %data{ $attr.name.substr: 2 } {</span>
<span class="coverage-red"> unless $attr ~~ Red::Attr::Column {</span>
<span class="coverage-red"> if self.^is-id: $attr {</span>
<span class="coverage-red"> self.^set-id: $attr.name => $_</span>
<span class="coverage-no"> }</span>
<span class="coverage-red"> $attr.set_value: self, $_</span>
<span class="coverage-no"> }</span>
<span class="coverage-no"> }</span>
<span class="coverage-no"> # TODO: this should be on M::R::Relationship</span>
<span class="coverage-red"> if $attr ~~ Red::Attr::Relationship {</span>
<span class="coverage-red"> with %data{ $attr.name.substr: 2 } {</span>
<span class="coverage-red"> $attr.set-data: instance, $_</span>
<span class="coverage-no"> } else {</span>
<span class="coverage-red"> my Mu $built := $attr.build;</span>
<span class="coverage-red"> $built := $built.(self.WHAT, Mu) if $built ~~ Method;</span>
<span class="coverage-red"> $attr.set-data: instance, $_ with $built</span>
<span class="coverage-no"> }</span>
<span class="coverage-no"> }</span>
<span class="coverage-no"> }</span>
<span class="coverage-no"></span>
<span class="coverage-red"> nextsame</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
<span class="coverage-green">method compose-dirtable(Mu \type) {</span>
<span class="coverage-red"> my \meta = self;</span>
<span class="coverage-no"> #state &build //= self.^find_private_method("TWEAK_pr");</span>
<span class="coverage-green"> my &build = method (\instance: *%data) is rw {</span>
<span class="coverage-green"> my $*RED-INTERNAL = True;</span>
<span class="coverage-green"> my @columns = instance.^columns;</span>
<span class="coverage-no"></span>
<span class="coverage-green"> my %new = |@columns.map: {</span>
<span class="coverage-green"> my Mu $built := .build;</span>
<span class="coverage-green"> $built := $built.(self.WHAT, Mu) if $built ~~ Method;</span>
<span class="coverage-green"> next if $built =:= Mu;</span>
<span class="coverage-green"> if instance.^is-id: $_ {</span>
<span class="coverage-green"> instance.^set-id: .name => $built</span>
<span class="coverage-no"> }</span>
<span class="coverage-green"> .column.attr-name => $built</span>
<span class="coverage-no"> };</span>
<span class="coverage-no"></span>
<span class="coverage-green"> for %data.kv -> $k, $v { %new{$k} = $v }</span>
<span class="coverage-no"></span>
<span class="coverage-no"></span>
<span class="coverage-green"> my $col-data-attr := self.^col-data-attr;</span>
<span class="coverage-green"> for $col-data-attr.get_value(instance).kv -> $k, $v { %new{$k} = $v }</span>
<span class="coverage-no"></span>
<span class="coverage-green"> my $dirty-old-values-attr := self.^dirty-old-values-attr;</span>
<span class="coverage-green"> $col-data-attr.set_value: instance, %new;</span>
<span class="coverage-green"> for @columns -> \col {</span>
<span class="coverage-green"> my \proxy = Proxy.new:</span>
<span class="coverage-green"> FETCH => method {</span>
<span class="coverage-green"> $col-data-attr.get_value(instance).{ col.column.attr-name }</span>
<span class="coverage-no"> },</span>
<span class="coverage-green"> STORE => method (\value) is hidden-from-backtrace {</span>
<span class="coverage-green"> die X::Assignment::RO.new(value => $col-data-attr.get_value(instance).{ col.column.attr-name }) unless col.rw;</span>
<span class="coverage-green"> die X::TypeCheck::Assignment.new(symbol => col.name, got => value, expected => col.type) unless value ~~ col.type;</span>
<span class="coverage-green"> if instance.^is-id: col {</span>
<span class="coverage-green"> instance.^set-id: col.name => value</span>
<span class="coverage-no"> }</span>
<span class="coverage-green"> instance.^set-dirty: col;</span>
<span class="coverage-green"> $dirty-old-values-attr.get_value(instance).{ col.column.attr-name } =</span>
<span class="coverage-red"> $col-data-attr.get_value(instance).{ col.column.attr-name };</span>
<span class="coverage-green"> $col-data-attr.get_value(instance).{ col.column.attr-name } = value</span>
<span class="coverage-no"> }</span>
<span class="coverage-no"> #use nqp;</span>
<span class="coverage-no"> #nqp::bindattr(nqp::decont(instance), self.WHAT, col.name, proxy);</span>
<span class="coverage-green"> col.set_value: instance<>, proxy</span>
<span class="coverage-no"> }</span>
<span class="coverage-green"> for self.^attributes -> $attr {</span>
<span class="coverage-green"> with %data{ $attr.name.substr: 2 } {</span>
<span class="coverage-green"> unless $attr ~~ Red::Attr::Column {</span>
<span class="coverage-green"> if self.^is-id: $attr {</span>
<span class="coverage-green"> self.^set-id: $attr.name => $_</span>
<span class="coverage-no"> }</span>
<span class="coverage-green"> $attr.set_value: self, $_</span>
<span class="coverage-no"> }</span>
<span class="coverage-no"> }</span>
<span class="coverage-no"> # TODO: this should be on M::R::Relationship</span>
<span class="coverage-green"> if $attr ~~ Red::Attr::Relationship {</span>
<span class="coverage-green"> with %data{ $attr.name.substr: 2 } {</span>
<span class="coverage-green"> $attr.set-data: instance, $_</span>
<span class="coverage-purple"> } else {</span>
<span class="coverage-green"> my Mu $built := $attr.build;</span>
<span class="coverage-green"> $built := $built.(self.WHAT, Mu) if $built ~~ Method;</span>
<span class="coverage-green"> $attr.set-data: instance, $_ with $built</span>
<span class="coverage-no"> }</span>
<span class="coverage-no"> }</span>
<span class="coverage-no"> }</span>
<span class="coverage-no"></span>
<span class="coverage-green"> nextsame</span>
<span class="coverage-no"> }</span>
<span class="coverage-no"></span>
<span class="coverage-green"> my role DirtableWrapped { };</span>
<span class="coverage-no"></span>
<span class="coverage-green"> if self.declares_method(type, "TWEAK") {</span>
<span class="coverage-green"> my &tweak = self.find_method(type, "TWEAK", :no_fallback(1));</span>
<span class="coverage-green"> if &tweak !~~ DirtableWrapped {</span>
<span class="coverage-green"> &tweak.wrap: &build;</span>
<span class="coverage-green"> &tweak does DirtableWrapped;</span>
<span class="coverage-no"> }</span>
<span class="coverage-red"> } else {</span>
<span class="coverage-green"> self.add_method: type, "TWEAK", &build;</span>
<span class="coverage-no"> }</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
<span class="coverage-no">#| Accepts a Set of attributes of model and enables dirtiness flag for them,</span>
<span class="coverage-no">#| which means that the values were changed and need a database sync.</span>
<span class="coverage-green">multi method set-dirty(\obj, Set() $attr) {</span>
<span class="coverage-green"> $!dirty-cols-attr.get_value(obj).{$_}++ for $attr.keys</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
<span class="coverage-green">multi method clean-up-columns(\obj, Set() $attr) {</span>
<span class="coverage-green"> $!dirty-cols-attr.get_value(obj).{$_}-- for $attr.keys</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
<span class="coverage-no">#| Returns `True` if any of the object attributes were changed</span>
<span class="coverage-no">#| from original database record values.</span>
<span class="coverage-green">method is-dirty(Any:D \obj --> Bool) { so $!dirty-cols-attr.get_value(obj) }</span>
<span class="coverage-no">#| Returns dirty columns of the object.</span>
<span class="coverage-green">method dirty-columns(Any:D \obj) { $!dirty-cols-attr.get_value(obj) }</span>
<span class="coverage-no">#| Erases dirty status from all model's attributes, but does not (!)</span>
<span class="coverage-no">#| revert their values to original ones.</span>
<span class="coverage-green">method clean-up(Any:D \obj) {</span>
<span class="coverage-green"> $!dirty-cols-attr.set_value: obj, SetHash.new;</span>
<span class="coverage-green"> $!dirty-old-values-attr.set_value: obj, {}</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
<span class="coverage-red">multi method get-attr(\instance, Str $name) {</span>
<span class="coverage-red"> $!col-data-attr.get_value(instance).{ $name }</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
<span class="coverage-red">multi method set-attr(\instance, Str $name, \value) {</span>
<span class="coverage-red"> $!col-data-attr.get_value(instance).{ $name } = value</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
<span class="coverage-red">multi method get-attr(\instance, Red::Attr::Column $attr) {</span>
<span class="coverage-red"> samewith instance, $attr.column.attr-name</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
<span class="coverage-red">multi method set-attr(\instance, Red::Attr::Column $attr, \value) {</span>
<span class="coverage-red"> samewith instance, $attr.column.attr-name, value</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
<span class="coverage-green">multi method get-old-attr(\instance, Str $name) {</span>
<span class="coverage-green"> $!dirty-old-values-attr.get_value(instance).{ $name }</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
<span class="coverage-red">multi method set-old-attr(\instance, Str $name, \value) {</span>
<span class="coverage-red"> $!dirty-old-values-attr.get_value(instance).{ $name } = value</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
<span class="coverage-green">multi method get-old-attr(\instance, Red::Attr::Column $attr) {</span>
<span class="coverage-green"> samewith instance, $attr.column.attr-name</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
<span class="coverage-red">multi method set-old-attr(\instance, Red::Attr::Column $attr, \value) {</span>
<span class="coverage-red"> samewith instance, $attr.column.attr-name, value</span>
<span class="coverage-no">}</span>
<span class="coverage-no"></span>
</pre>
</div>
</div>
</div>
</body>
</html>