I've never been happy with the way I've implemented certain kinds of features:
Then, I saw two things:
This is a really useful pattern that forms the basis of the way I'd like to build rails apps whose main functions are informatoin systems with hard needs for reporting, notifications, and auditing. (I'm also gonna use the definitions/words from above as my language for this thread). Now, I need to understand the particulars of how to do this. It seems like there are basically two approaches:
Of the two, I'm a lot more interested in the deeply embracing rails approach because I think that will stand the test of time. To do this, the goal is to build a simple little app: "Stuff Tracker." Basically, it's purpose is to store a list of items of things in my house I'd like to get rid of, store basic info (name, note, where stored), store images about them (to expose a list of things to sell), and move them through a simple state machine to ultimately sell/discard/store each thing. This way I can easily begin tracking all of the stuff in my house I need to get rid of, and easily expose lists of various types to other people (can I sell this thing? would you like to buy anything on this list of items that's "for sale?" etc.) to arrive at a decision on what to do with it.
I left the notebook I'd stored all my notes in about my thoughts here, and recently the number of computers and environments I code on exploded. To remedy this, and rebuild my notes, I'm gonna store the progression of thought on here. This would have an added benefit: perspective. So here's my ask: if you're reading through this and see a better way to do things, please either comment and/or pr! I'm not exactly sure what I'm doing, so different POV's would be really helpful.
I'm not interested in a 1:1 mapping of "the event sourcing pattern" into rails. I'm looking for an "event-sourcing-like" implementation usable across projects and that fits into the rails way. this means embracing:
When creating an event, a couple things jump to mind we'd need to handle:
I've got a little time remaining today. Immediate questions I want to get a basic implementation of:
I think I'm gonna blindly follow the idea of "bucket" and the idea that if a thing is "recordable" it can consist of a discrete set of events (meaning, if a thing is recordable then that means its an aggregate). "Bucketable" means it can behave as a bucket. Ultimately I think these should be real domain concepts (like tenant, or project), but I'm gonna go ahead and make a literal bucket and merge that into some other sort of differentiation later.
I haven't made enough progress to commit on, but it seems as though:
bucketis. So a Place model.
createaction via callbacks. I'm curious about using conventional
event typenames, and naming convention (is it
item_create? are there existing parts of rails I can leverage to sorta handle/automatically set these calculations for me?)
Seems like the
Event model will need to:
before_validation :set_aggregate # pull in validations from appropriate model after_validation :track_event # persist this event if validations pass after_create :apply_event # apply the contents of this event to the appropriate aggregate. in the case of creating an item, find_or_create
So the question becomes, where does the calculation logic for this event live. Kickstarter says, in the event definition. I think maybe I can just defer to
Item.create for right now, though
So it appears this is the big rub:
As long as validations fire off for things that aren't generated by the system/world, all should be fine... right?
I'd really like the best of both worlds. Don't wanna jump whole hog out of using typical rails methods. But I think there's value in the event being created first, then applied because that way things can be recalculated, retried, etc.
So I think what makes the most sense is layering in a new custom active record primitive into the system, much like "create" or "update" - "track."
Then as for where calculators for events live, they'll live on whatever model makes sense. The model itself for typical form interactions, activemodel-backed classes for form interactions that make sense, etc.
This slightly shifts create and update.
track becomes the method inside controllers,
update need to be slightly wrapped, and everything is still forced to be phrased through whatever it is.
This solves for
Doesn't solve for reactors yet, but once there are a variety of events happening, I think this will take the form of some centralized monitoring layer, maybe able to just get popped inside
Join 31,152+ developers who get early access to new screencasts, articles, guides, updates, and more.