Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save karmi/503660 to your computer and use it in GitHub Desktop.
Save karmi/503660 to your computer and use it in GitHub Desktop.
What's wrong with Ruby libraries for CouchDB?

What's wrong with Ruby libraries for CouchDB?

During the last year, I have worked on couple of Ruby/Rails based projects where the primary datastore was CouchDB. CouchDB, to me, is a dream database for web developer come true. The simplicity, the HTTP-based API, the abandonment of SQL semantics, the inspiring community, that all reminds me of when I came into Rails years ago.

However, working with Couch in Ruby and Rails is very, very painful, in my opinion. I'd like to briefly summarize some of my frustrations here. Maybe they are shared, maybe not -- if they are, I think we should launch some coordinate effort to make using Couch in Ruby a pleasure and intelectual satisfaction, not endless loops of research and hacks to „make it work“.

Please note, that my interest is solely to stir the debate. I may be severely mistaken in any point. But, I'd like using Couch in a Ruby application to be a joy, not a frustration, which is what I've met more times than I'd have liked.

Plethora of Gems

First and obvious problem is the plethora of gems you can choose from to interact with Couch. There's the granddaddy CouchRest, above which sits CouchPotato and above which sits SimplyStored. There's RelaxDB and Makura with different take on things. There's CouchFoo, aiming for drop-in ActiveRecord replacement. And possibly others -- due to the simple HTTP-based Couch's API, it's relatively simple to create some wrapper around it.

Why the choice is bad? First of all, you have to research your options. You have to read documentation for those gems, noticing that they are almost the same, that they offer almost the same features. So, which of those options are valuable for you? Which less so? Which of those gems seem to be more maintained or used?

The situation reminds me of the state of internationalization/localization in Ruby on Rails some two years ago. You could choose from Globalize, GlobaLITE, Gibberish and loads and loads of other plugins/gems, providing you with relatively simple, and similar funtionality: replacing identifiers in your code with locale-specific text. In the end, it became completely unberable to research and compare the options, and the plugin/gem authors decided to get together and try to nail the commonalities and differences in their approaches, and a generic, higly modular solution for Rails i18n was born: http://github.com/svenfuchs/i18n. In the video from Euruko 2010, Sven Fuchs gives a very good overview of the effort: http://vimeo.com/12665914.

Do you think this is something worthwile to do for Couch-related gems?

Layers of Abstraction

As briefly noted above, some of the solutions have grotesque numbers of layers. Consider using SimplyStored, a very advanced and Rails-compatible library, in your application. Apart from the CouchDB database itself, you deal with:

  1. RestClient -- Handling HTTP
  2. CouchRest -- Handling creating databases, saving documents, etc
  3. CouchPotato -- Handling saving documents, validations, declaring and querying views, etc
  4. SimplyStored -- Giving ActiveModel-like API, saving documents, validations, associations, etc

That's rather painful. Whenever you need to adapt, patch, or otherwise change something in your app, you have to constantly shift between these layers, their codebase, their test suites, documentation and quirks.

(Lack of) Modularization

I think current libraries do not do true justice to the flexibility of Couch.

One real world example. On my current contract, we need to save different models into different databases. (And we need to use and interact with the Couch authentication/authorization system, but that's another story.) That's impossible to do eg. in RelaxDB or CouchPotato/SimplyStored. In the end, we had to abandon attempts to hack that into SimplyStored and ended with replicating much of it's functionality in customized code.

But, hell, we need to use different databases for different model instances! (think user „inboxes“). Maybe that's kinda idiosyncratic, but consider that even the good old ActiveRecord has use_table.

And the list could continue. What if you, for example, want to use Typhoeus instead of RestClient? It should be trivial to do that.

Compatibility With The Rest of the World

Whatever our opinion is on Rails and "ActiveRecord", it's the dominant platform for Ruby web applications. CouchPotato has full ActiveModel compatibility -- but, as an example, it magically disappears in SimplyStored (http://github.com/karmi/simply_stored/commit/a168851). CouchPotato does not offer Model#save and such features by itself.

Compare this with the MongoID gem. That is just true drop-in solution. For simple cases, you swap MyModel < ActiveRecord::Base with some includes and you're done. I'd love Couch to be usable on exactly the same level.

I also hear endless talk about Couch „not being the same as relational databases“ and such, repeated over and over. This is truly painful because some of the people who repeat such things confuse „relational“ with has_many associations. Whatever the issue is, ActiveRecord semantics (Model#update_attributes, validations, etc) is (one) valid way for modelling in any data store. Even Ohm for Redis has similar semantics.

Another case in point is pagination. Some of the gems, like RelaxDB, implement pagination, some of them leave that as an exercise for the reader. RelaxDB implements pagination in it's own way, incompatible with the preferred way of pagination in a Rails app -- will_paginate. This way, we lose all the helpers, all the syntax sugar everybody is used to when working with Rails.

And of course, will_paginate's style of pagination is wrong in Couch. But, why should it not be one way of doing it? Why should you think about and implement pagination on your own?

It is my opinion, that anybody should be able to use Couch in Rails or Sinatra or plain Ruby application as easily as using ActiveRecord, or, maybe more importantly, the highly faved MongoDB. Please share your opinion in the comments.

@paulcarey
Copy link

First and obvious problem is the plethora of gems you can choose from to interact with Couch

I'll simply re-iterate what Mikeal said, it's in the nature of such projects that an explosion of similar-but-different libraries emerge. Despite the inevitable confusion caused, I think in general such efforts are to be lauded.

Quoting Mikeal

but if you want to really understand CouchDB and always be able to debug any higher level library you’re going to need to understand the REST interface as well as you understand the abstractions

I couldn't agree more.

And quoting langalex

imho there are just too many different ways to use couchdb, so there can't be one gem to rule them all

I'm inclined to agree with this too. Ultimately, I suspect the different libraries offer their own take simply because they provide specific solutions to their authors' specific pain points.

Researching and evaluating all the options is just hard, and I don't see any immediate benefit in that.

You're right in that there probably is no immediate benefit. But I guess the appropriate approach to research is the same, irrespective of the number of competing libraries. Work out what you need, then check the test suite of a lib. If it meets your needs, the code looks reasonable, and the lib is maintained, you're done. Else, move on.

Of course, popularity and suitability don't always intersect and so I'll finish by pointing you towards CouchTiny, which you didn't mention. Written by Brian Candler, it offers both database centric and document centric APIs. The code is consise and idiomatic. If you're serious about a desire to produce the de facto Ruby lib for CouchDB, perhaps it would be a good place to start. Or perhaps I've simply added to your pain :)


RelaxDB implements pagination in it's own way, incompatible with the preferred way of pagination in a Rails app -- will_paginate... And of course, will_paginate's style of pagination is wrong in Couch

I would have loved to implement pagination in RelaxDB in a manner consitent with will_paginate, but IIRC it wasn't possible, hence the balkanized approach. I don't know what the alternative might have been.

@karmi
Copy link
Author

karmi commented Aug 3, 2010

Just to clear some confusion, I agree 100% a) with Mikeal that you have to know the Couch's API to be able to use Couch features in any high-level library, and I even agree b) with Alex that there are many very different ways to use Couch.

As for a), every gem out there provides (sometimes very high-level) abstractions for that, eg. a DSL for view definitions. So while I understand the arguments about "abstractions", I think the argument is being stuck midway somewhere.

As for b), why almost every gem out there has more or less the same semantics, then? I just don't see the „diversity“ in their feture sets, nor in their code. Yes, definitely, different gems provide specific solutions to author's pains, as Paul writes. I myself had to monkeypatch and hack my way on every Couch project I've been working on. But is it really so, that everyone has their own pain, different from others? Wittgenstein would say so. I can't know if you're in pain and what sort of pain. But by observing you, I can think, „he's clearly in pain“. And by talking to you, I can say, „you seem to have some tooth pain, try this, it has helped me, maybe it'll help you as well“.

To re-iterate, this is not about "some lazy jerk's problems with couch gems" or "stopping people making gems". (I appreciate all the efforts, of course!, and may have not stressed that enough.)

This is about Couch being as simple, as elegant, as usable on the high-level, in Ruby, as when using curl, so to speak.

@langalex
Copy link

langalex commented Aug 3, 2010

so once again, since we can't and don't want to delete 90% of the gems out there, how about creating some central intro/guides website that helps less experienced people to evaluate their options? couchonrails.org?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment