5 ms·
Nostalgia warning: I also grew frustrated with Rails / ActiveRecord and jumped to Merb / DataMapper with excitement. Perhaps it will sound like a small thing, b
by Locke 10y ago
Nostalgia warning: I also grew frustrated with Rails / ActiveRecord and jumped to Merb / DataMapper with excitement. Perhaps it will sound like a small thing, but I remember feeling especially frustrated that every ActiveRecord model became such via inheritance. This drove me crazy:
class User < ActiveRecord::Base
Why should my `User` extend from `ActiveRecord::Base`? Is a User of my app also an ActiveRecord::Base? What is an ActiveRecord::Base anyway?
So, when DataMapper came along and favored composition over inheritance I was sold.
However, my experience with DataMapper was that it didn't have the stability of ActiveRecord, nor did it reach feature parity.
And, then Rails killed Merb. At the time I thought it was a tragedy. The competition Merb provided did improve Rails, it would have been nice if that competition had been longer term, though. On the flipside, I wonder if there would have been enough community to support two large Ruby web frameworks.
In the end I made peace with Rails and ActiveRecord (and, believe it or not, even ActiveSupport!). I don't have great love for Rails, but it is a powerful tool, so I accept it for what it is.
That said, I think the author's criticisms are well stated and hopefully there will be some influence on the future direction of Rails, etc, and the way devs approach Rails.
- jsnk 10y agoI don't get your complaint about "class User < ActiveRecord::Base". If you don't want to use ActiveRecord::Base methods, why don't you just declare a class without it? You can just do "class User" you know.
- Goopplesoft 10y agoI don't ruby but I'm guessing OP prefers the "include" that DataMapper uses since inheritance 'feels' weird ... a weak point nevertheless.
- solnic 10y ago`include` is also inheritance, multiple inheritance. I try to avoid inheritance and prefer composition. It is very simple in ruby and very powerful.
- deleted 10y ago[deleted]
- Locke 10y agoAs a thought exercise, suppose I have my User class and now I would like to write it as json. Do you think it would be strange if the established solution were this? class User < JSON::Base Where by extending JSON::Base, I now have access to helpful methods like to_json? Instead we have JSON.dump(user). And, if I need to customize the way the User json is written, I can opt in by defining a method. Thanks to Ruby's open classes, I can make the definition of such methods optional, suppose a separate file includes something like: class User def as_json end end Requiring this file will bring in the extra json behavior without littering my actual user.rb with the details of how a User is written to json. Whether this is worthwhile or a bad idea is debatable, but I like that it is possible. Now imagine if persisting a model to the database were similarly flexible? What if we could do this? ActiveRecord.save(user) Maybe it would be a good thing, maybe not. As it is, I've come to accept the ActiveRecord approach, but when I create a model that extends ActiveRecord::Base, I think of it, not as a User, but an ActiveRecordPersistedUser. Where it makes sense, I separate my BusinessModel's from my ActiveRecordPersistedBusinessModel's for clarity.
- bgentry 10y agoHave you tried Sequel? Sequel has, for me, filled the void left by DataMapper. Most folks I know that have used both ActiveRecord and Sequel vastly prefer Sequel. http://sequel.jeremyevans.net/ http://sequel.jeremyevans.net/
- Siyo 10y agoSomething to consider for people interested in Sequel. Sequel is great and all, but it still follows the Active Record pattern (Sequel::Model), not Data Mapper. Also expect to run into some problems with gems that interact with ActiveModel (Devise, CarrierWave, etc.). It's all solvable of course but it might require some hacking. Most popular gems have sequel versions or ship with sequel support, but it's not as well tested and maintained, we had to contribute several patches. Also, if you plan on using Sequel with Rails, don't use any of it's plugins that make it behave closer to ActiveRecord. Stuff like nested_attributes, delay_add_association, association_proxies, instance_hooks. They seem really nice at first, but I guarantee they will cause all sorts of unpredictable problems down the road. I would recommend looking into something like Reform which decouples form logic from your models because working with complex forms is going to be harder without all of the AR magic.
- andrei_says_ 10y agoIs there an authentication gem which works well with Sequel?
- Freaky 10y agohttp://rodauth.jeremyevans.net/ http://rodauth.jeremyevans.net/
- Freaky 10y agoSequel::Model's quite optional - it doesn't force you to use the AR pattern. It's built on top of Sequel::Dataset, which is entirely usable all on its own. ROM also uses it as its SQL backend: http://rom-rb.org/ http://rom-rb.org/
- erikpukinskis 10y agoIt's kind of amazing that an open source project was able to aqui-hire another open source project. I'm not sure I've seen that before. I guess if anything it speaks to the level of centralization in Merb development at that time?
- barrkel 10y agoHaving used many different ORMs that let you think that your business models could just gain persistence with a little sprinking of automagic, I far prefer the non-object-orientation of ActiveRecord. Databases aren't object-oriented. Thinking of them with an is-a, LSP etc. mindset is a recipe for pain down the road. Databases are containers for facts: a means of storing, finding, synthesizing and manipulating facts. Your User class isn't a user of your application; IMO it's wrong to think of it as an object, because it could just be a slice of the User's facts (e.g. a subset of the columns). I'm not a big fan of object orientation any more, and I like my databases to be stores of facts. The data in the database is primary; code in the application is secondary. Persistence isn't something I add to my benighted objects to let them be reanimated by query; persistence is what lets me briefly get a handy representation of a tuple locally. To my mind, ActiveRecord models are little more than hashes with a nicer syntax. I don't need them to be much more; I don't want them to be much more. You can try and add methods and make them smaller, but coordinating the manipulation of facts is problematic in a transactional world, and the responsibilities aren't clear either. Object orientation is predicated on the idea of message sends and hidden state; tables have explicit state and no behaviour. Not a good match.
- pm24601 10y agoEspecially true if there are more than 2 codebases interacting with the same database table.
- spacemanmatt 10y agoHonestly, I feel like OO has been a net harm to the practice. It is a useful code reuse pattern but I feel like it has gotten far too much play.
- sanderjd 10y agoThe inheritance approach, used in both ActiveRecord and ActionController is sort of like the original sin of Rails. It affects everything from semantics, to performance, to testability. It is often the reason things eventually seem hard, but also the reason many things initially seem easy.