5 ms·
Renee, the friendly rack-based framework
- robomc 15y agoAnyone got a 'why not Sinatra' for this?
- deleted 15y ago[deleted]
- joshbuddy 15y agoEssentially, 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.
- judofyr 15y agoHere'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
- soveran 15y agoThe same in Cuba (http://cuba.is 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
- seanp2k2 15y agoThese 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.
- lobster_johnson 15y agoWhat 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.
- nakajima 15y agoI wrote something like this a while back: https://github.com/nakajima/sinatras-hat 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.
- lobster_johnson 15y agoThat's pretty cool!
- DanielRibeiro 15y agoYes. But they say why: http://reneerb.com/concept http://reneerb.com/concept
- robomc 15y agoRight, 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.
- nesquena 15y agoYeah 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 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.
- joshbuddy 15y agoIt'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.
- deleted 15y ago[deleted]
- keen 15y agoCool project. Anyone know what inspired the name, theme etc?
- joshbuddy 15y agoI 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.
- themgt 15y agoI'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!
- acangiano 15y agoJosh, 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.)
- joshbuddy 15y agoThis 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?
- swah 15y agoIts amazing how propaganda from one genocidal regime is accepted, even cool, but the other would get you banned anywhere.
- patio11 15y agoChe Communism is chez chic.
- achiu 15y agoI 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.
- dextorious 15y agoWho 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.
- tptacek 15y agoThe 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.
- pablodh 15y agoIt's somewhat similar to this other microframework: https://github.com/soveran/cuba https://github.com/soveran/cuba Not because of the name ;)
- carbon8 15y agoWhat's with the use of curly brackets for multi-line blocks?
- joshbuddy 15y agoUm, 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.)
- rue 15y agoMost “rules” about {…} vs. do…end are nonsense. I tend to use {…} unless I can't be bothered to put parens around the arguments.
- ryeguy 15y agoThey'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.
- seanp2k2 15y ago>"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.
- rue 15y ago…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.
- mhd 15y agoHmm, 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…
- petercooper 15y agoIt'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?
- mhd 15y agoHonestly, 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.
- petercooper 15y agoI 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 :)