public
Last active

Rails Lightweight Stack. Most of this is detailed on Crafting Rails Applications - http://pragprog.com/book/jvrails/crafting-rails-applications

  • Download Gist
Gemfile
Ruby
1 2 3 4 5 6 7 8 9 10 11
source :rubygems
 
# We are not loading Active Record, nor Active Resources etc.
# We can do this in any app by simply replacing the rails gem
# by the parts we want to use.
gem "actionpack", "~> 3.2"
gem "railties", "~> 3.2"
gem "tzinfo"
 
# Let's use thin
gem "thin"
config.ru
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
# Run this file with:
#
# bundle exec RAILS_ENV=production rackup -p 3000 -s thin
#
# And access:
#
# http://localhost:3000/hello/world
#
# We are using Bundler in this example, but we could also
# have used rubygems:
#
# require "rubygems"
#
# gem "actionpack"
# gem "railties"
#
# require "rails"
# require "rails/all"
 
# The following lines should come as no surprise. Except by
# ActionController::Metal, it follows the same structure of
# config/application.rb, config/environment.rb and config.ru
# existing in any Rails 3 app. Here they are simply in one
# file and without the comments.
require "rails"
require "rails/all"
 
class MyApp < Rails::Application
routes.append do
match "/hello/world" => "hello#world"
end
 
# Enable cache classes. Production style.
config.cache_classes = true
 
# Here you could remove some middlewares, for example
# Rack::Lock, AD::Flash and AD::BestStandardsSupport below.
# The remaining stack is printed on rackup (for fun!).
# Rails 4 will have config.middleware.api_only! to get
# rid of browser related middleware.
config.middleware.delete "Rack::Lock"
config.middleware.delete "ActionDispatch::Flash"
config.middleware.delete "ActionDispatch::BestStandardsSupport"
 
# We need a secret token for session, cookies, etc.
config.secret_token = "49837489qkuweoiuoqwehisuakshdjksadhaisdy78o34y138974xyqp9rmye8yrpiokeuioqwzyoiuxftoyqiuxrhm3iou1hrzmjk"
end
 
# This is a barebone controller. One good reference can be found here:
# http://piotrsarnacki.com/2010/12/12/lightweight-controllers-with-rails3/
class HelloController < ActionController::Metal
include ActionController::Rendering
 
def world
render :text => "Hello world!"
end
end
 
# Initialize the app (originally in config/environment.rb)
MyApp.initialize!
 
# Print the stack for fun!
puts ">> Starting Rails lightweight stack"
Rails.configuration.middleware.each do |middleware|
puts "use #{middleware.inspect}"
end
puts "run #{Rails.application.class.name}.routes"
 
# Run it (originally in config.ru)
run MyApp

where's the +1 button on github?

The groundwork was laid in Rails 3 to have an "API app", but the work was never finished. If you (or anyone else) was serious about it, I'd be happy to walk you through what needs to be done and brainstorm the best ways to do it. I'll also happily review any pull requests toward this end.

It's actually the rest of Rails that I want; the stuff here I can do with Sinatra. :wink:

Still awesome that this is possible!

@iain Exactly. I haven't seen anyone doing single-file apps with Rails, simply because people don't need it. There are only two useful tips here:

1) Use ActionController::Metal in case you want to provide to speed up some specific endpoints

2) If you are building an API only endpoint, remove the middleware that are not API related (like Flash, BestStandardsSupport)

Again, this is mentioned in Crafting Rails Applications and in other blog posts. Funny that it still makes people surprised. :)

@josevalim

Funny that it still makes people surprised.

Because: ZOMG RAILS IS BLOATED! USE NODE NAO!

This would be an even cooler demo if there was a way to do it without lines 17-26, which are 10 out of the 25 actual lines of code, and also imply a great deal of knowledge to know to remove. Maybe something like a Rails::Application::Metal?

@jsanders those middlewares were removed at random. It happens a hello world app does not need any of them. :trollface:

The best way to remove middlewares in your app is to run rake middleware to get the full list and then take a look at the guides for more information about what they do.

@josevalim - Absolutely, but my point is that in terms of "here's a lightweight way to create a lightweight app", the only failure in your gist is the stuff about middleware deletion. It demonstrates the tension between the "lightweight code" idea and the "lightweight app" idea - with the middleware deletion code, the code is not as lightweight, but without it, the app is not as lightweight.

What we all REALLY want to know is - how did you get the troll-face appearing in your comment?

I think it was by accident. :trollface:

Kidding, here it goes: http://www.emoji-cheat-sheet.com/

Wow! such a nice response to all those "rails is bloated" posts.

Congrats!

@alextakitani The ability to use Rails to build a small, "one file" application, doesn't make the framework code less bloated. That's the point most of the guys pointing this as a solution miss.

@josevalim

Again, this is mentioned in Crafting Rails Applications and in other blog posts. Funny that it still makes people surprised.

So, if I need to buy a book or dig some number of blog posts to do such a "simple" thing, then it's the framework's documentation that's lacking, at minimum. Right?

way to go: complain about modular code that you can refrain from loading in your application, and call it bloat.

@lucashungaro framework documentation is mainly about APIs. Guides/recipes showing you how to achieve something specific for most frameworks out there is actually done with blog posts, books and tutorials (which are also part of the community content). Rails already took a step forward and provides a bunch of guides on the repo as well.

In other words: we already provide very solid documentation for what people are doing 99% of the cases. If you want to go out of the Rails way, do tailored stuff, you need to get your ass moving. Read blog posts, stay tuned, sometimes read a book.

@tomash Apparently the fact they know the code is there, bothers them somehow. All those 1MB in their filesystem being wasted!

@josevalim I agree with that and, yes, I can read books. I was just saying the if I need to read a book to do something that Rails uses as a flagship characteristic (modularity), then we're failing somewhere.

@tomash You clearly don't understand that modularity isn't configurability. But, since you're being so aggressive and ironic, I shouldn't bother trying to explain. But I will. :)

The code is stll there, unloaded, unused... still there. It may be 10kb of code, it still wastes my time when I try to read Rails' code to learn its core, not a bunch of unrelated features.

Also, I agree there should be another generators besides the default one. This "one file" app could be one. I also would like to see a "traditional" app with just ActionPack, ActionMailer and Railties. I forked Rails earlier today to see what I can do.

The term modularity is widely used in studies of technological and organizational systems. Product systems are deemed “modular”, for example, when they can be decomposed into a number of components that may be mixed and matched in a variety of configurations

--http://en.wikipedia.org/wiki/Modularity

The example above shows how to load a Rails application without many of its components (no ActiveRecord, no ActiveResource, etc) and ActionController::Metal is a perfect example of how you can have a bare bone structure and mix and match the behaviors you need, like layouts, callbacks, helpers, rendering, etc, composing a controller with only the features you need.

Of course you need to use language artifacts to achieve this modularity, in the example above, components/frameworks can be turned on via configuration options, requires or modules inclusion.

I knew someone would post Wikipedia's definition of modularity. I should've bet. :)

I elaborate on my opinion here: http://blog.lucashungaro.com/

Do you think something like that can be done?

Please tell me where in the Rails website we say that modularity is our flagship: http://rubyonrails.org/

Hint: it doesn't. Modularity was a goal in Rails 3 that will stick around, one of the goals me and other core members are happy to ensure. It isn't one of Rails flagships though, it isn't part of Rails Golden Path.

C'mon man, we don't need that. I'm trying to help, I'm not saying "This thing is all fucked up and I'm moving on to Node.js, fuck you all!".

To clarify, I'm talking about application level modularity. The internals are getting modular through Railties, which is a very good thing, but I think we're talking about different levels.

@lucashungaro Yes, it is possible and should be easy. What you want is to be able to opt-in to features/components/frameworks, instead of opting-out (the Rails way gives you all). You need to have modularity in order to either opt-in or opt-out.

In other words, you are saying that because Rails includes everything by default, it isn't modular. But this is wrong. What Rails lacks is simply a structured way to start with a clean slate and manually opt-in features.

Ok, so I'll adapt the vocabulary I'm using to improve our communication. I want Rails to be able to generate modular applications and support them (via documentation, easy upgrades, guides and so on). I think this sounds better.

Textual communication sucks to represent mood. I'm not attacking people or demeaning the work done. Yes, I said somethings are crap, and that's 'cause I think they're crap, but that doesn't mean I think the people doing it suck. Apple does awesome things and also does some crap. I learned some time ago to not judge an idea based on its origin (unless we're talking about Microsoft's ideas :P), only by its merits.

I understand you're upset given all the "complaints" been posted lately. Being a member of a public and very popular project for sure makes you a big target, but I think you guys receive a lot of well-deserved praise too, not to mention the visibility that leads to good career opportunities.

So I heard you may be stepping down from Rails and, if I can say something, I would say that "rage quitting" doesn't solve anything. Haters gonna hate, fanboys gonna irrationally love and that's the way things are. Steve Jobs had (and stil has!!) a legion of haters and people criticizing, but that couldn't stop him from doing what he believed. I apologize if I contributed to that decision and, while I don't take back anything I said on these posts, I'll also try to contribute somehow, even if I think that non-contributors can freely criticize and that should be used as a "termometer" of the work we're doing.

Sad to be late to the discussion, since it seems people already bashed enough to make @josevalim take a "sabbatical" off of rails, but I'd love to see him incarnate Linus Torvalds and just straight and boldly answer to all of this with "show me the patches". I don't think anyone would refuse that he hasn't the credit to do so and, as it would happen with many Linux, git, Gnome, etc stupid and pointless academic-blind "why don't you do this way" discussions, this one would probably end as fast as it started.

@13k

Yes, because that would be a very mature way to deal with the community. You need to be very "bold" to be an asshole, indeed.

That's something I always hated about some OSS leaders. You can't talk about anything that you don't directly contribute with or use somehow. It's like living in North Korea, I guess. ;)

Valim is doing way better than Linus and other jerks, trying to address the concerns. We just need to keep away from personal attacks and focus on the ideas (that can be good or bad, no matter the origin). It's hard when so many harsh words are thrown around, but give it some time to rest and things will be fine. I would get a bit upset too, but it's something you need to account for when being a prominent member of such a popular public project.

After all that, I can say my respect for him only grew.

lol, north korea comparison. as if you had any remains of credibility, you just lost it. show patches or gtfo.

Let me put a smiley there to avoid confusion. No hard feelings, man. I'm trying to help. (and, yes, I'm working on patches)

Before sending patches I needed to know if my ideas fits the way the Core Team wants the framework to shape up. I won't write code just to see it being rejected 'cause that's not the way the maintainers want the framework to work. I'll try my luck.

@lucashungaro

I'm glad you brought up the "OSS" word.

It would be silly of us to not understand it as being a meritocratic system and at the same time expect to have the so-called freedom of speech when you criticize something as big, and as subjective, as the project architecture without any practical argument (practical as in lines of code).

It would be even more silly to expect maturity of the "leaders" -- who reached the "leader" status working their ass off -- when people start a discussion that compromises the whole image of their work, which is a very fragile thing, when half their points would be answered if asked correctly.

The same criticism that is concerned about the entry level users, wouldn't take into account that maybe criticizing it publicly would take even more entry level users away, because it's much more easy to read a blog post and just stay away than reading the freaking code to actually prove it right. Ironically the other way around also is true: creating blog posts about how to overcome the lack of documentation or things like this very gist tries to do is much more helpful, has short/mid-term impact (while the supposed wrong things get fixed); is so much easier to implement by the non-core, eager-to-help contributors; and reaches much more easily the entry level users.

But none of what I described is new, right?

Now, sprinkle a little bit of frustration off-steam, a little bit jealously with the "I think the core is well rewarded"; on top of all that cluster fuck non-practical discussion, and you get core members leaving and the clever users playing the "oh, was it me?" bullshit. And I ask, who profits from that? What good it did?

@13k

I completely agree with you. Just want to state that I never attacked people, just code/ideas. If someone felt that way, I'm really sorry (and I'll make sure they hear that from me).

I don't think that non-code discussions should be dismissed. But I believe we'll just agree to disagree on that.

Anyway, I'm not jealous, if they're are rewarded they deserve it, of course. I also don't think he's leaving (if he's leaving) because of me (that's pretentious), just want to ensure people know I'm not criticizing them, especially when they do a lot of work and create way more good and useful things than the contrary. That doesn't mean bad things exist and we shouldn't talk about them before throwing code at the problem.

You see, since yesterday I've been derided and called liar, jealous, FUD spreading, implausible, stupid and many other things said by people who don't even know me or my work. You can read everything I wrote and see that I'm not calling anyone names. I'm criticizing some of their work, not themselves. I'm not writing rants saying "this sucks, I'm leaving, fuck you all", I'm saying "this sucks, here's a suggestion to improve".

That said, I'll take into account what you guys are saying and think about it, really. Despite good intentions, I probably took the wrong actions as seem by most of the community.

I really don't want to keep discussing about people or "what's right on OSS" and things like that. But I'm giving up in the application architecture discussion too, 'cause it's been really hard to keep it on topic. I'll just shut up and write code then.

Hey @josevalim, just came back to this discussion and noticed that you trimmed the middleware section and added the comment about config.middleware.clear in Rails 4 - I didn't know about that feature! :thumbsup:

I don't understand much about this gist, its details, its implications.

But I get the general idea that you're trying, pushing the limits and making awesome happen.
And I like that very much. You're doing the most difficult thing, being a fixer and a creator.

Now keep on keeping on and do your best to ignore all the people talking about bloat, limitations and bad design, they're doing the easiest thing in the world, criticizing and bashing.

You can't load all railties because activerecord inserts connection pool and query cache middleware which, without a database (specifically a config/database.yml), causes the app to throw exceptions on request.

Apart from this problem, loading the whole rails stack defeats the point of the gist and writing barebones rails app using only action controller metal.

Change:

require "rails/all"

to:

require "action_controller/railtie"

@sj26 Notice that we are not including the activerecord gem. Without requiring the activerecord gem, require "rails /all" will try to load active_record/railtie, fail because there is no gem and continue properly.

However, there is another issue here that can trigger error you were describing. Since rubygems loads a gem regardless if you have described it or not, if activerecord is in your system, it will be loaded regardless if you said gem "activerecord". That said, if you are using bundler, require "rails/all" is fine. If not, better to whitelist as you said. Thanks for the comment.

@sj26 fixed the gist by actually using bundler. I left a comment on how to use rubygems.

@josevalim yeah, that's what's happening. I wasn't using an isolated gemset or bundler so activerecord was still available, hence I used the same convention as for generated rails applications to load only part of the framework.

I was also going to suggest moving the require and gem loading into the shebang also (a la #!/usr/bin/env RAILS_ENV=production rackup -rubygems -r railties -r actionpack/railtie ...) but I generally prefer The Bundler Way:tm: too.

The gist is a nice demo of piecemeal rails, though!

@wycats For what it's worth, RocketPants uses a similar approach (inherit from ActionController::Metal, include only whats needed for API) and use that instead of ActionController::Base for API endpoints - see github.com/filtersquad/rocket_pants

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.