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.
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.
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.
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.
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.
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.
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…
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 :)
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.)
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.
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.
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.