Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Renee, the friendly rack-based framework (reneerb.com)
80 points by joshbuddy on Oct 15, 2011 | hide | past | favorite | 37 comments


Its amazing how propaganda from one genocidal regime is accepted, even cool, but the other would get you banned anywhere.


I don't think it was the intent to make such propaganda cool, but rather more of the mistake of ignorance that it represented such things. It's been updated to something more kosher(hopefully) and fits nicer with the theme/name.


Che Communism is chez chic.


Who said it was a "genocidal regime"?

Americans who can't even point Russia on a map and know their history from the History channel and New York Times bestseller books (if that)?

For hundreds of millions of people all around the world it was an inspiration, even if faulty, and hardly comparable to nazism.

So, there.


The Stalinist Soviet Union that website evokes was in fact a genocidal regime. I don't know what specifically you're talking about; maybe it's some other government.

It would probably be better not to hash this out on HN, though, so I've downmodded the root comment on this thread.


Anyone got a 'why not Sinatra' for this?


Essentially, it let's you take something like

  before '/blog/:id' do
    @blog = Blog.get(params[:id])
  end
  
  get '/blog/:id' do
    @blog
  end
  
  put '/blog/:id' do
    @blog.update_attributes(params)
  end
and turn it into

  path 'blog' do
    var do |id|
      @blog = Blog.get(id)
      get { halt @blog }
      put { @blog.update(request.params); halt :ok}
    end
  end
I feel this is DRY'er than the Sinatra representation. It also has nice integration with Rack itself. The implementation is very simple, easy to get into.


Here's the same in Camping, using plain Ruby:

    class Blog < R '/blog/(\d+)'
      def service(id) @blog = Blog.get(id); super end
      def get(id)     render :blog end
      def put(id)     @blog.update_attributes(@input) end
    end


What I discovered recently when doing a new Rails 3 app was that the RESTful CRUD stuff is all boilerplate. This is true about Sinatra apps, too: Every GET, POST, PUT and DELETE are just wrappers around find, create update and destroy. I used Rabl for generating JSON, so it was possible to write a single serialization for all objects. So why not just boil everything down to the minimal code required?

Something like this:

    handle '/blog'
That's it. This makes some assumptions:

* That /blog maps to a class Blog which it can load and save. * That you either use "fat models" (with callbacks that munge data and perform actions when data changes) or external observers (like ActiveRecord's observers). * That the model supports all four CRUD actions.

When you want additional verbs:

    handle 'GET /blog/search' do
      MySearchEngine.search(params[:q])
    end
Or object-specific ones:

    handle 'GET /blog/:id/search' do |blog|
      MySearchEngine.search(params[:q], :blog_id => blog.id)
    end
In fact, aside from extra verbs, you could get away with no code at all, since you could introspect the database layer to discover which classes are mappable.

My app is a JavaScript-based single-page HTML5 web application using Backbone, so there is almost no server-side frontend code, meaning my app is basically a server-side database anyway.


I wrote something like this a while back: https://github.com/nakajima/sinatras-hat It's no longer maintained, but it was fun to see how many assumptions I could jam into one framework.


That's pretty cool!


The same in Cuba (http://cuba.is):

    Cuba.define do
      on "blog/:id" do |id|
        blog = Blog.get(id)

        on(get) { res.write blog }
        on(put) { blog.update(req.params); res.write :ok }
      end
    end


These all seem like good ideas in their own way. I say "it's great that we have all these useful ways of doing similar things!". Choose whatever best fits your application. I really like that this type of stuff is catching on over Rails.


Yes. But they say why: http://reneerb.com/concept


Right, I guess that sort of rewriting of CRUD situations would be nice in some cases.

Although in real applications, most of your methods are complex enough that you'd want them to be multiline blocks, at which point it would start to get really ugly IMO.

Anyway it sounds like I'm being more critical than I actually am I think.

But my un-DRY annoyance with Sinatra isn't writing multiple blocks with route declarations for CRUD methods, so much as not being able to refer to those routes in your views abstractly. ie., if you decide you want to change from /comments/:id to /awesome-comments/:id, it's a headache.

I assume there are plugins to fix that annoyance, but I'd have like Sinatra to generally have routing more abstracted from specific URL paths.


Yeah we agree regarding route generation being important. We came up with a decent solution to it for Renee, let us know what you think: http://reneerb.com/route-generation and time will tell but we think the combination of clearer routes, leaner code and url generation makes renee a fun alternative.


It's also easy to split a Renee application into multiple parts, but, I'd really like to address this more going forward, to make it easier.


Hmm, another Ruby web framework that goes the DSL route. Is there anything available that generally tries to be a bit more explicit? Strangely enough, camping seems to be the only somewhat well-known and maintained contender here, and that has those global object and twee details…


It's really easy to put together systems like this in Ruby now thanks to Rack. What sort of API would you be interested in seeing?


Honestly, that's mostly why I'm asking. You're right, getting something to work with Rack isn't hard. But getting a proper API in the first place, is.


I totally agree. That's why I was interested to see if you had any ideas. I find this sort of thing interesting and while I've played with ideas in the past, I always come back to the standard patterns :)


It's somewhat similar to this other microframework: https://github.com/soveran/cuba

Not because of the name ;)


What's with the use of curly brackets for multi-line blocks?


Um, where did you see those? I think I used curly braces for a lot of the Renee { .. } examples, and use the do..end once I'm inside there. That's just my style, but, you can use which ever one you prefer (and of course, if the precedence is correct.)


Most “rules” about {…} vs. do…end are nonsense. I tend to use {…} unless I can't be bothered to put parens around the arguments.


They're nonsense in that they are without ryhme or reason, but you should be following the community standard (curlies for one liners, do/end for everything else).

I'd honestly pass on an open source project not following the generally agreed upon ruby standard.


>"They're nonsense in that they are without ryhme or reason, but you should be following the community standard (curlies for one liners, do/end for everything else)."

That's my reasoning too. At first, I thought it was more readable (read: familiar) to use curly braces, but now I stick with do...end for blocks >1 line. Sometimes it's helpful for breaking up complex nested map() blocks as well.


…Except that that isn't “the community standard”. It's one of the more popular varieties, of about equal support with {…} for when you use the return value.


Cool project.

Anyone know what inspired the name, theme etc?


I have no idea how we got down the Russian path. Sort of started as a joke and somehow went from there.

Renee is my gf's name, and she's very patient with me when I wanna work on open source, so, it's a nod to her.

The inspiration for it came from Railsconf 2009 when one of the Sinatra guys said how get "/:id" do |id| was a smell because of the id repeat. I had been working on a new routing DSL for Goliath, when I got an itch to start making simple, useful rack apps.


Josh, I have not looked into the details of your framework, but why not simplify the DSL to:

    path 'blog' do |id|
      @blog = Blog.get(id)
      get { halt @blog }
      put { @blog.update(request.params); halt :ok}
    end
Why do you need the var call within the block? Also, you seem to break the ruby convention of using do end for blocks larger than one line, in many of your examples.

(Again, I spent three seconds on your site, so you may have a solid reason for this and have explained it already as well.)


This very well might be the next iteration in fact. There is no "good reason" aside from simplicity. One of the reasons against this is var can take validation. So, you can do the following.

  var Integer do |id|
this will only continue if it matches against an Integer (and it will also cast it for you). The argument list might get hella complicated if you allow munging like that.

I am considering allowing chaining though, so,

  path('blog').var do |id|
What would you think of that?


Yeah this is an early release. I can think of several ways to enhance the DSL even more with ideas similar to this to cleanup common cases.


Yeah, exactly. I wanna get a better handle on what these common cases are, so, comments like this are wonderful.


I'll definitely give this a try for my next would-be Sinatra/Padrino project. The code looks great and so does the site. Thanks for this!


Ah, cool.

I love Sinatra, and I'm big on DRY, so I'll definitely give Renee a shot.

BTW, noticed the 'GITHUB FORK YOU', nice haha.


Yeah, the "GITHUB FORK YOU" thing made me laugh too. Thanks for another viable option for a Ruby DSL! I might use it if I wanted to mess around with HTTP response headers -- looks like it'd be good for that.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: