-
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
further work on new presentation logic
- Loading branch information
1 parent
696560b
commit 762bdf9
Showing
7 changed files
with
178 additions
and
58 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,26 @@ | ||
module Presenters | ||
# This is work in progress we're releasing early so | ||
# that it can be used in forwarding to send the current | ||
# values as they're received. | ||
# TODO: add presenter tests, finish refactor following | ||
# spec in your spreadsheet, remove unneeded options, | ||
# use in appropriate views, add unauthorized_fields logic | ||
# delete unneeded code in models and views. | ||
PRESENTERS = { | ||
Device => Presenters::DevicePresenter | ||
Device => Presenters::DevicePresenter, | ||
User => Presenters::UserPresenter, | ||
Component => Presenters::ComponentPresenter, | ||
Sensor => Presenters::SensorPresenter, | ||
Measurement => Presenters::MeasurementPresenter, | ||
} | ||
|
||
def self.present(model, user, render_context, options={}) | ||
PRESENTERS[model.class]&.new(model, user, render_context, options).as_json | ||
def self.present(model_or_collection, user, render_context, options={}) | ||
if model_or_collection.is_a?(Enumerable) | ||
model_or_collection.map { |model| present(model, user, render_context, options) } | ||
else | ||
PRESENTERS[model_or_collection.class]&.new( | ||
model_or_collection, user, render_context, options | ||
).as_json | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,42 @@ | ||
module Presenters | ||
class BasePresenter | ||
|
||
def default_options | ||
{} | ||
end | ||
|
||
def exposed_fields | ||
[] | ||
end | ||
|
||
def initialize(model, current_user=nil, render_context=nil, options={}) | ||
@model = model | ||
@current_user = current_user | ||
@render_context = render_context | ||
@options = self.default_options.merge(options) | ||
end | ||
|
||
def as_json(_opts=nil) | ||
self.class.exposed_fields.inject({}) { |h, m| | ||
h.merge(m => self.send(m)) | ||
self.exposed_fields.inject({}) { |hash, field| | ||
value = self.send(field) | ||
value.nil? ? hash : hash.merge(field => value) | ||
} | ||
end | ||
|
||
def method_missing(method, *args, &block) | ||
if self.class.exposed_fields.include?(method) | ||
device.public_send(method, *args, &block) | ||
if self.exposed_fields.include?(method) | ||
model.public_send(method, *args, &block) | ||
else | ||
super | ||
end | ||
end | ||
|
||
|
||
def present(model, options={}) | ||
Presenters.present(model, current_user, render_context, options) | ||
def present(other_model, options={}) | ||
Presenters.present(other_model, current_user, render_context, options) | ||
end | ||
|
||
private | ||
|
||
attr_reader :current_user, :options, :render_context | ||
attr_reader :model, :current_user, :options, :render_context | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
module Presenters | ||
class ComponentPresenter < BasePresenter | ||
|
||
alias_method :component, :model | ||
|
||
def default_options | ||
{ readings: nil } | ||
end | ||
|
||
def exposed_fields | ||
%i{key sensor last_reading_at latest_value previous_value readings} | ||
end | ||
|
||
def sensor | ||
present(component.sensor) | ||
end | ||
|
||
def latest_value | ||
data = component.device.data | ||
data[component.sensor_id.to_s] if data | ||
end | ||
|
||
def previous_value | ||
old_data = component.device.old_data | ||
old_data[component.sensor_id.to_s] if old_data | ||
end | ||
|
||
def readings | ||
readings = options[:readings] | ||
if readings | ||
readings.flat_map { |reading| format_reading(reading) }.compact | ||
end | ||
end | ||
|
||
private | ||
|
||
def format_reading(reading) | ||
# TODO sort out the mess of multiple reading formats used ini | ||
# DataParser, RawStorer, etc, etc. | ||
reading.data.map { |entry| | ||
timestamp = entry.timestamp | ||
value = entry.sensors&.find { |sensor| | ||
sensor["id"] == component.sensor_id | ||
}.dig("value") | ||
{ timestamp: timestamp, value: value } if value | ||
}.compact | ||
|
||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module Presenters | ||
class MeasurementPresenter < BasePresenter | ||
|
||
alias_method :measurement, :model | ||
|
||
def exposed_fields | ||
%i{id name description unit uuid definition} | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
module Presenters | ||
class SensorPresenter < BasePresenter | ||
|
||
alias_method :sensor, :model | ||
|
||
def exposed_fields | ||
%i{id parent_id name description unit created_at updated_at uuid default_key datasheet unit_definition measurement tags} | ||
end | ||
|
||
def measurement | ||
present(sensor.measurement) | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
module Presenters | ||
class UserPresenter < BasePresenter | ||
|
||
alias_method :user, :model | ||
|
||
def default_options | ||
{ | ||
with_devices: true | ||
} | ||
end | ||
|
||
def exposed_fields | ||
%i{id uuid role username profile_picture url location email legacy_api_key devices created_at updated_at} | ||
end | ||
|
||
def profile_picture | ||
render_context&.profile_picture_url(user) | ||
end | ||
|
||
def email | ||
user.email if authorized? | ||
end | ||
|
||
def legacy_api_key | ||
user.legacy_api_key if authorized? | ||
end | ||
|
||
def devices | ||
present(user.devices) if options[:with_devices] | ||
end | ||
|
||
private | ||
|
||
def authorized? | ||
policy.show_private_info? | ||
end | ||
|
||
def policy | ||
@policy ||= UserPolicy.new(current_user, user) | ||
end | ||
end | ||
end |