The basic version of RedwoodRecord is really slick but I think until it can handle validations and life cycles it’s still a bit far from ready. I was reading and thinking about how you all were thinking about implementing these features but I think the current path may be lacking a key advantage of ActiveRecord. Looking at this example:
I think it’s missing the capability to skip or specify life cycle situations. From the AR docs:
class User < ApplicationRecord
before_validation :normalize_name, on: :create
# :on takes an array as well
after_validation :set_location, on: [ :create, :update ]
private
def normalize_name
self.name = name.downcase.titleize
end
def set_location
self.location = LocationService.query(self)
end
end
Attaching a validation hook to just create doesn’t seem like it would be possible unless there are going to be life cycle hooks for all the different situations that can occur. Another example is skipping a life cycle on a condition.
I’m sure some of the thinking is to put it into the function handler but what if instead, the definitions for life cycles leveraged HOCs. For example, using the example shared:
where config could hold options like: { if: conditionalFunc(), on: [CREATE] } as an example. Maybe this syntax isn’t as friendly but something where we could pass these options which would allow handler functions to remain small and testable but enable life cycle hooks to be rich and powerful.
Update: Ah! I just realized my syntax on my idea is off but the idea holds. The point being make life cycle functions composables where you can pass the config and handler separately.
Yeah I’d love it if RR had all of these features! I haven’t had a chance to extend it further, but duplicating the functionality of ActiveRecord in JS was always the ultimate goal.
But, I’ve had this worry in the back of my mind that RR can only get so far without Ruby’s metaprogramming abilities, and we’ll end up coding ourselves into a corner and then RR reaches some hard limit that we can’t get around. You end up having to write raw Prisma code again in your services, but now it’s mixed together with RR, and in the long run that might end up being worse from a maintainability standpoint than if you had just stuck with Prisma all along.
I don’t have any real evidence that this is what will happen, just a nebulous feeling in my gut. That, and the thought of trying to learn relational algebra so that all of SQL can be expressed in RR (to mimic the Arel syntax of ActiveRecord) is terrifying to me. Seeing this part of the wikipedia article made me feel like I was driving too fast over a hill in a car:
I think your gut is spot on. I can’t tell you exactly what’s going to go wrong, but I agree that without Ruby’s full metaprogramming, this may be a pipe dream to get the full AR capabilities. I think where the implementation is though is pretty close to opening the gateway to some of this functionality. I feel like most of the relational algebra is just to settle the some of the more complex queries to resolve such as N-to-N relations.
I think some of the other complications are the fact that operations like create v. save could be differently implemented as create is technically static while save is technically an instance method. Maybe conceptually something like this could work but then you have the problem that someone is overriding it.
but again - this leaves much to be desired and definitely highlights some of your key concerns around long term maintainability. I’ll keep pondering and see if I can come up with something better to recommend - just trying to help get this feature moving in that direction. Again - love the work - I’m just hungry for more and need to stop being so greedy