Users controller and model - This is for the owner of the dashtag page to be able to edit and change the settings without making that available to the rest of the world. Currently the app restricts the User count to be one (in other words only one owner). The implementation is pretty standard.
Sessions controller - Also pretty standard. We are storing the user in a Session, which means login is not persisted when a browser is closed.
Settings
Settings page - the UI is pretty simple. Just a list of the settings plus descriptions and validations
Settings Models - There are two models that take care of settings: Settings & SettingStore.
Settings plays the role of sort of a view model. It extends and implements Active Model modules to keep the behavior of a model, but is not tied to the DB. The initial reasoning for the model was to take advantage of the view helpers Rails offers that bind well with model and in general provide an API to engage with Settings that would be kind of familiar to a Rails developer. Since the db stores settings as key-value pairs, but the view represents the data as a single record (with each setting as an attribute), I initially thought to split the model logic into two models, one for the view (Settings) and the other for the db (SettingStore).
SettingStore subclasses Active Record. It interacts with the DB and together with Settings translates the setting values input by the user into individual entries into the db.
Validations - Validations for settings are found in either SettingStore or Settings. SettingStore has independent setting validation like making sure a hashtag list is formatted correctly. This validation does not change depending on the status of other settings and makes sure properly formatted things get stored in the db. Settings has setting dependency validation like make sure twitter and/or instagram credentials are entered before storing hashtags (because we can't pull posts by hashtags with those credentials). This was put in Settings because the idea was that this dependency should only be enforced when a user changes settings all together. If in the future we allow users to change settings in independent ways we may not want to enforce this setting.
Individual Setting Models (Hashtags, TextSettings) - This was introduced to capture any logic of converting a setting from different types, like hashtags convert a list "#peace & #love, #war" into [["peace", "love"], ["war"]]
Final Thoughts: Looking back, I don't think it is necessary for this divide with Settings and SettingStore, and it is worth the time exploring and refactoring that logic into one model that has the right interface for the UI and the app, at large, and at the same time translate settings into the key value pair in the db. This will also bring the validations together in one model. Though I thought that initially field dependencies should be captured in a view model, I think the dependencies makes sense to be enforced in the system at large. In fact it will introduce some confusion if settings that are valid in one page, comes up as invalid for another. I highly recommend refactoring this! As far as the individual setting models, I think this was a bit of over engineering. We may not need setting models to wrap each setting (especially TextSetting), especially because one of the main consumer of this is the UI which would need to convert them to string and all objects have a to_s. So as we combine 'SettingsandSettingStore` we can eliminate non-essential models.
To do this, I introduced:
Dashtag Admin/Owner
Settings
Settings
&SettingStore
.Settings
plays the role of sort of a view model. It extends and implements Active Model modules to keep the behavior of a model, but is not tied to the DB. The initial reasoning for the model was to take advantage of the view helpers Rails offers that bind well with model and in general provide an API to engage with Settings that would be kind of familiar to a Rails developer. Since the db stores settings as key-value pairs, but the view represents the data as a single record (with each setting as an attribute), I initially thought to split the model logic into two models, one for the view (Settings
) and the other for the db (SettingStore
).SettingStore
subclasses Active Record. It interacts with the DB and together withSettings
translates the setting values input by the user into individual entries into the db.SettingStore
orSettings
.SettingStore
has independent setting validation like making sure a hashtag list is formatted correctly. This validation does not change depending on the status of other settings and makes sure properly formatted things get stored in the db.Settings
has setting dependency validation like make sure twitter and/or instagram credentials are entered before storing hashtags (because we can't pull posts by hashtags with those credentials). This was put inSettings
because the idea was that this dependency should only be enforced when a user changes settings all together. If in the future we allow users to change settings in independent ways we may not want to enforce this setting.Hashtags
,TextSettings
) - This was introduced to capture any logic of converting a setting from different types, like hashtags convert a list"#peace & #love, #war"
into[["peace", "love"], ["war"]]
Settings
andSettingStore
, and it is worth the time exploring and refactoring that logic into one model that has the right interface for the UI and the app, at large, and at the same time translate settings into the key value pair in the db. This will also bring the validations together in one model. Though I thought that initially field dependencies should be captured in a view model, I think the dependencies makes sense to be enforced in the system at large. In fact it will introduce some confusion if settings that are valid in one page, comes up as invalid for another. I highly recommend refactoring this! As far as the individual setting models, I think this was a bit of over engineering. We may not need setting models to wrap each setting (especiallyTextSetting
), especially because one of the main consumer of this is the UI which would need to convert them to string and all objects have ato_s
. So as we combine 'Settingsand
SettingStore` we can eliminate non-essential models.