diff options
| author | Marius Peter <dev@marius-peter.com> | 2025-11-23 17:54:45 +0100 |
|---|---|---|
| committer | Marius Peter <dev@marius-peter.com> | 2025-11-23 17:54:45 +0100 |
| commit | fa77a691ce0cc8941fe470a762f352b27f4f0563 (patch) | |
| tree | 08916174840a7896fc59633cc59fab931e7012c2 /app/models/concerns/nutrient_vector.rb | |
| parent | 73283f2f5153c77f72b6a29e98f173628f5e1057 (diff) | |
Diffstat (limited to 'app/models/concerns/nutrient_vector.rb')
| -rw-r--r-- | app/models/concerns/nutrient_vector.rb | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/app/models/concerns/nutrient_vector.rb b/app/models/concerns/nutrient_vector.rb new file mode 100644 index 0000000..ba4f28a --- /dev/null +++ b/app/models/concerns/nutrient_vector.rb @@ -0,0 +1,55 @@ +module NutrientVector + extend ActiveSupport::Concern + + NUTRIENT_KEYS = %i[ + nno3 p k ca mg s na cl si fe zn b mn cu mo nnh4 + ].freeze + + included do + # Define simple readers (nno3, p, k, ...) that read from #nutrient_values + NUTRIENT_KEYS.each do |k| + define_method(k) { nutrient_values[k] } + end + end + + # Hash-like access + def [](key) + key = key.to_sym + return nil unless NUTRIENT_KEYS.include?(key) + public_send(key) + end + + def keys = NUTRIENT_KEYS + + # Returns a copy to avoid accidental mutation + def to_h + NUTRIENT_KEYS.index_with { |k| public_send(k) } + end + + # Iterate over pairs + def each_pair + return enum_for(:each_pair) unless block_given? + NUTRIENT_KEYS.each { |k| yield k, public_send(k) } + end + + # Simple difference (self - other), useful for “how far from target?” + def delta_against(other) + NUTRIENT_KEYS.index_with { |k| (public_send(k).to_f) - (other.public_send(k).to_f) } + end + + # Percent difference relative to other (e.g., measurement vs target) + # Returns 0 when both are 0, and nil when target is 0 but measurement isn’t. + def percent_diff_against(other) + NUTRIENT_KEYS.index_with do |k| + a = public_send(k).to_f + b = other.public_send(k).to_f + if b.zero? && a.zero? + 0.0 + elsif b.zero? + nil + else + ((a - b) / b) * 100.0 + end + end + end +end |