國外 Planet
: penetralia: 1. The innermos...
2. The most private or secret parts; recesses: the penetralia of the soul.
Ryan Davis: vlad version 1.1.0 has been released!
Vlad the Deployer is pragmatic application deployment automation, without mercy. Much like Capistrano, but with 1/10th the complexity. Vlad integrates seamlessly with Rake, and uses familiar and standard tools like ssh and rsync.
Impale your application on the heartless spike of the Deployer.
FEATURES/PROBLEMS:- Full deployment automation stack.
- Turnkey deployment for mongrel+apache+svn.
- Supports single server deployment with just 3 variables defined.
- Built on rake. Easy. Engine is small.
- Very few dependencies. All simple.
- Uses ssh with your ssh settings already in place.
- Uses rsync for efficient transfers.
- Run remote commands on one or more servers.
- Mix and match local and remote tasks.
- Compatible with all of your tab completion shell script rake-tastic goodness.
- Ships with tests that actually pass in 0.028 seconds!
- Does NOT support Windows right now (we think). Coming soon in 1.2.
- 3 major enhancements:
- Vlad.load now takes a hash of recipe overrides, eg: Vlad.load :web => :nginx. See rdoc for defaults.
- Removed vlad_tasks.rb and split into vlad/apache.rb, vlad/mongrel.rb, and vlad/core.rb.
- The flog ratio between capistrano+deps / vlad+deps is pi (or, damn close)!
- 12 minor enhancements:
- Added $TRACE to make it more available and cleaner to read.
- Added :svn_cmd variable.
- Added Rake.clear_tasks *str_or_regexp
- Added debug and mana_from_heaven tasks to Rakefile.
- Added more documentation.
- Added :rsync_cmd and :rsync_flags.
- Added :ssh_cmd and :ssh_flags.
- Added variable expansion to vlad:debug task.
- Removed :scm variable. Now a Vlad.load component/flavor/need-a-word-here.
- Removed :application var. Use it if you want it. We don't require it.
- Renamed :p4cmd to :p4_cmd.
- Renamed :rake var to :rake_cmd.
2 (important) bug fixes:
- HUGE: Fixed sudo hang bug #13072. Fix suggested by Chris Van Pelt.
- HUGE: Vlad.load calls user config last, allowing variable overrides. ACK! Sorry!
- http://rubyforge.org/projects/hitsquad/
err.the_blog: Even More Ambitious
Things are really looking up for Ambition. It’s been almost two weeks since the initial release and I thought I would catch y’all up on the progress we’ve made.
The current version is 0.2.2, so grab that while you can and follow along. Supplies are limited.
$ sudo gem install ambition -y
Databasein’Ambition has gone from generating generic SQL to respecting your database of choice (as long as it’s MySQL or PostgreSQL).
Check it:
# Postgres User.select { |m| m.name =~ /chris/ } SELECT * FROM users WHERE users."name" ~ 'chris' # MySQL User.select { |m| m.name =~ /chris/ } SELECT * FROM users WHERE users.`name` REGEXP 'chris'How cool is that? And because Postgres supports case insensitive regular expressions, so do we:
User.select { |m| m.name =~ /chris/i } SELECT * FROM users WHERE users."name" ~* 'chris'Escaping is also DB-specific, whether you like it or not. Oh, and OFFSET works with Postgres now.
Don’t see your database of choice on our (short) list? Feel free to send patches—we happily accept them.
Toyin’If you just want to dip your toe in, we’ve added a test/console inspired by will_paginate’s.
You have to create the database yourself, but once that’s setup this irbish script will create a schema and load it with fixtures for you to play with and enjoy.
$ mysqladmin create ambition_development $ cd GEMS/ambition-0.2.2 $ ruby test/console >> Developer.select { |u| u.salary > 80_000 }.size => 9 >> Developer.select { |u| u.salary > 80_000 }.entries => [#<Developer:0x271f370 ...> ...]There might be some rough spots as far as the associations go, but overall it should work pretty nicely.
To use a different database, set an ADAPTER environment variable, e.g.
$ ADAPTER=sqlite3 ruby test/console
Speedin’Some people have been asking about performance. You know how it goes. “Oh, that’s cool, but it’s slow.” “It doesn’t scale.” “Who owns the trademark?”
In the interest of appeasing the unappeasable, I spent some time with ruby-prof. Below are the fruits of my labor, comparing the first and latest versions of Ambition.
Each case runs 10,000 times. The benchmark I used is here. I had to fix some bugs in 0.1.0 to get it to work, but that shouldn’t affect anything.
# Ambition 0.1.0 user system total real simple select 7.030000 0.020000 7.050000 ( 7.052899) dual select 8.050000 0.010000 8.060000 ( 8.094917) join select 7.890000 0.030000 7.920000 ( 8.003906) dual select w/ sort 13.390000 0.040000 13.430000 ( 13.529581) dual select w/ stuff 13.600000 0.050000 13.650000 ( 14.107565) it's complicated 16.030000 0.070000 16.100000 ( 16.213238) # Ambition 0.2.2 user system total real simple select 0.910000 0.010000 0.920000 ( 0.921048) dual select 1.380000 0.010000 1.390000 ( 1.398235) join select 1.950000 0.020000 1.970000 ( 1.981603) dual select w/ sort 1.960000 0.000000 1.960000 ( 1.964018) dual select w/ stuff 2.080000 0.010000 2.090000 ( 2.111435) it's complicated 2.820000 0.000000 2.820000 ( 2.831330)So, that’s pretty cool. We’re definitely not slowing anything down—Ambition happily leaves that task up to your app. Zing!
Stubbin’This is an experimental feature, but that’s what we’re all about. Observe:
User.ambition_source = fixtures(:chris, :pj, :_why) User.detect { |u| u.name == 'Chris' }If an ambition_source is set, Ambition will run all it instead of the database. The above example runs select on the fixtures array rather than building and executing SQL. Could be cool for functional / unit tests.
Gitin’Development is now riding Git rather than Subversion. Follow along:
$ git clone git://errtheblog.com/git/ambition
If you haven’t already tried Git, this could be a golden opportunity for us both. Other projects like Rubinius, god, and CouchObject are already using this up and coming tool for development, so give it a shot.
Us using Git or Subversion should not affect your ability to use Ambition in a Rails app. You can either require the gem or run gem unpack ambition in your vendor/plugins directory to get it working.
Contributin’Thanks to Matthew King, David Chelimsky, Pratik Naik, Loïc, Louis Rose, John Topley, and François Beausoleil for bug reports, feature requests, and their contributions.
If you didn’t catch the updates on the last post, we added empty?, downcase, upcase, any?, all?, and slice thanks to their hard work.
As always, you can add bugs, make requests, and participate in general over at the Lighthouse bug tracker.
We now have a mailing list, too: http://groups.google.com/group/ambition-rb
Prospectin’We’ve moved our sights from Rack to LINQ. That is, we don’t want to only support other ORMs—we want Ambition to be a query language for SQL, LDAP, XPath, the works. The 1.0 release will be backend-agnostic. Maybe then we’ll change the name to Hubris? Time will tell.
Charles Oliver Nutter: InfoWorld Bossies Close to my Heart
- Best Open Source Programming Language - Summary: Ruby gets mad props for a vibrant community and a diverse range of implementations (e.g. JRuby), and then they go squishy and say "and these other languages are great too!"
- Best Open Source IDE - InfoWorld heaps praise on NetBeans largely because it has *not* gone the way of an amorphous, all-encompassing "platform" and has continued to take risks to improve the overall experience of the IDE. Before the work on NetBeans 6 (don't download M10; use a daily build) I was a nay-sayer myself; having used NetBeans 6 for many months now, I can honestly say it's far better than NetBeans 5.5 and has caught up or passed Eclipse in many ways. There's more to do, but I'm extremely impressed with the progress.
topfunky: Is Free Beer Possible?
Don’t know the words / Kids already hummin’ with it. —Buck 65
Or more accurately, “Is Free, Community-Driven Open Source Documentation Possible?”
A few times a month, I receive an email directing my attention to a new plugin repository or Rails documentation site.
They are usually beautifully designed, but painfully bereft of actual plugins or useful documentation. They are a blank wall, waiting for a kid with a spray can to supply decoration. So far, that hasn’t happened.
Why not?
The ProblemPeople want to help the community, and it seems that the best way is to build a site where people can contribute. The problem is that the people who need the information aren’t able to give it, and the people who have the knowledge are too busy to write it down.
A beautiful looking site is good for attracting visitors, but it isn’t necessarily good for attracting workers. Programmers don’t visit empty sites because they are nice to look at (but graphic designers do!).
What these sites need is content! They need knowledgeable people who are willing to document the finer points of Rails for the benefit of those who are learning it. So mostly, they need a way to attract experienced developers.
In many cases, the founders want to run a job board or Google ads and make a bit of cash from the traffic to their (currently empty) site. Financial motivation is not the problem. (It has worked for me, and people thank me daily for it!) The problem is how it is implemented. It’s a “business plan” that provides no sustaining benefit for those who are actually doing the work (i.e. writing the documentation).
These sites will continue to go up and stay empty unless there is a different kind of “business plan” behind them, one that provides a tangible motivation for people to come and write documentation. Documentation is often boring to write and time-consuming. People don’t do it for fun!
Solutions Existing Sites- http://agilewebdevelopment.com/plugins/ The original plugin directory. Over 700+ plugins. Don’t launch unless you can start your site with at least this many. I love the look of Railsify, but I have no reason to search a site with 30 plugins when another one with 700 is available.
- Official Rails API Docs Submit a documentation patch and add to this. Also available in searchable format at RaisBrain, Noobkit, and probably a dozen other places.
- Wiki. Official, but often spammed and frequently out of date. Also RailsLodge, the straw that caused the camel to write the blog post you are reading now.
- Commentable API docs. Rannotate, one of the original commentable RDoc apps. Seems to only be available in source since the example sites were down when I last checked. RailsManual is also available but most of the comments in the last 6 weeks are SPAM.
- For free video, there’s Ryan Bates’ RailsCasts. I’ve supported RailsCasts financially from day one and he publishes some great information there.
- There’s also the beautiful looking Rails Documentation Project. But most of the pages are pleas for contributions.
Although there are many aggregators (Planet, Corner) and great news portals (Ruby Inside), no one has tried to organize existing blog articles. What about a system that rates posts and assembles a list of classic blog posts on various topics? (such as Jamis Buck’s classic posts)
Organize it topically, not chronologically. Treat it like a library. Use the information that people are already writing and reward them by sending traffic to their blog.
What if the proprietors could dedicate an hour or two a day toward hunting down and rating top blog posts? There is already great documentation on some topics, but it’s scattered all over the place.
Maybe the Google Ad or job board revenue could even be paid back to blog authors for writing quality posts on requested topics.
If you build it well, I would even consider buying advertising space there each month.
Your ThoughtsWhy have documentation projects failed? Am I right in thinking that continuing documentation is impossible without financial backing or a self-supporting business plan of some sort?
PeepCode Screencasts – Learn Ruby on Rails and Javascript! Hour-long screencasts for $9.: kakistocracy: Government by...
Charles Oliver Nutter: JRuby Compiler Update, and a Nice Peformance Milestone
Compiler Status
I've been working feverishly for the past several weeks to get the rest of the compiler complete. Currently, it's able to handle the majority of Ruby syntax. Here's a list of the remaining language features that do not compile:
- "rescue" blocks; exception handling in Ruby is rather complicated, and there's some particularly odd uses of rescue that will be a bit tricky to support with normal Java exception-handling.
- "class var declaration" is not yet supported. This is when you declare a class variable (@@foo) from within the body of a class or module. This primarily affects compiling class bodies, so although it prevents AOT compilation of some scripts, it doesn't usually affect individual methods.
- "opt n" execution. This is specifying "-n" to the Ruby runtime, and it loops the provided script as though it were surrounded by "while gets(); ... end". It's useful for line-by-line processing of stdin.
- "post execution" blocks. Post exe blocks are when you specify an END { ... } block somewhere in your script. These blocks are saved up and executed at the end of the script execution, regardless of where they appear in the script. They're a bit like Kernel#at_exit blocks.
- "retry". Tell me friends, do you know what "retry" actually does? Retry is used within a block/closure, and it causes the method containing the closure to be re-called anew. And as an interesting quirk, the original arguments to the method are re-evaluated, so if you call foo(bar()) and a retry is triggered within foo(), bar() will get invoked again for the retried call to foo(). Weird, eh? Update: I didn't explain this well. Here's another attempt: if you have the following code:
def foo(x = bar()); 1.times {retry}; endAnd you call foo with no arguments, allowing the default argument logic to fire, retry will cause that logic to fire again and again. It's essentially re-entering the method anew with the original arguments, but causing *argument processing* to be revisited. I'm not sure why you'd want this behavior, since it could frequently result in default arguments to re-call methods that might only be valid the first time. - Some non-local flow control is not yet complete. Non-local flow control happens any time you return, break, or next from within a block (when not immediately inside a normal loop construct). Much of non-local flow control is working, but I need to flush out any remaining cases that aren't running correctly.
a = [1, 2, (begin; raise; rescue; 3; end)]When this code is compiled, it turns into a local variable assignment. The value assigned is a literal array construction with three elements: a Fixnum 1, a Fixnum 2, and a rescued block of code. The typical way to construct the array then is to follow these steps:
- Construct an array of the appropriate size
- Dup the array reference
- Push a constant integer zero
- Push Fixnum 1
- Insert Fixnum 1 at index zero in the array. This consumes the dup'ed array, the index, and the Fixnum1.
- Dup the array reference again
- Push a constant integer one
- Push Fixnum 2
- Insert Fixnum 2
- Dup the array reference again
- Push a constant integer two
- Now it gets complicated; we must recurse in the compiler to handle the rescue block
- The rescue block is compiled and a "raise" is triggered in the code
- The exception raised is handled, resulting in the whole rescue leaving a Fixnum 3 on the stack
- Insert the Fixnum 3
- Construct a RubyArray object with the remaining object array
We will likely have to solve this complication in one of two ways:
- We could save off the stack when entering code that might trigger exception handling
- We could put exception-handling logic in a separate method and invoke it in-place, thereby protecting our executing stack from clearage.
A Nice Performance Milestone
And on the topic of performance, the recent compiler work has allowed us to reach a new milestone: we now exceed Ruby 1.8.6's performance on M. Edward (Ed) Borasky's MatrixBenchmark.
Some months back, after the Mountain West RubyConf in Salt Lake City, Ed posted an interesting blog entry where he professed a lot of confidence in JRuby's future. We emailed a bit offline, and he pointed me to this matrix benchmark he'd been using to measure the relative performance of Ruby 1.8.6 and Ruby 1.9 (YARV). I told him I'd give it a try.
Originally, we were perhaps 50% to 100% slower than Ruby 1.8.6. This was back when hardly anything was compiling, and there had been few serious efforts to optimize the JRuby runtime. Performance slowly crept up as time went on. But as recent as a week ago, JRuby performance was still roughly 20-25% slower than 1.8.6.
So last week, I dug into it a bit more. I turned on JRuby's JIT logging (-J-Djruby.jit.logging=true) and verbose logging (-J-Djruby.jit.logging.verbose=true) to log compiling and non-compiling methods, respectively. As it turned out, the "inverse_from" method in matrix.rb was not yet compiling...and it was where the bulk of MatrixBenchmark's work was happening.
The final sticking point in the compiler for this method was "operator element assignment" syntax, or basically anything that looks like a[0] += 5. It's a little involved to compile; you have to retrieve the element, calculate the value, call the operator method, and reassign all in one operation. For the ||= or &&= versions, you have to perform a boolean check against the element to see if you should proceed to the assignment. A good bit of compiler code, but it had to be done.
So then, with "OpElementAsgn" compiling, it was time to re-run the numbers. And finally, finally, we were comfortably exceeding Ruby 1.8.6 performance:
Ruby 1.8.6:
Hilbert matrix of dimension 128 times its inverse = identity? true
586.110000 5.710000 591.820000 (781.251569)
JRuby trunk, Java 6 server, ObjectSpace disabled:
Hilbert matrix of dimension 128 times its inverse = identity? true
372.950000 0.000000 372.950000 (372.950000)Or should I say vastly exceeding? By my calculation this is an easy 2x performance increase, and perhaps a 70% improvement just by getting this one extra method to compile.
On Beyond Zebra
I believe we're pretty well on-target to have the compiler completed by RubyConf in November. I'm about to embark on a refactoring adventure to prepare for the stack-juggling I'll have to do to support rescue blocks. That will mean minimal progress on adding to the compiler until the end of the month, but ideally the refactoring will make it easy to get rescue compilation complete. The others are just a matter of spending some time.
Once the JRuby compiler is complete, we will start testing in earnest against a fully pre-compiled Ruby stdlib. Along with that, we'll wire in support for pre-compiling RubyGems as they install and pre-compiling Ruby scripts as they are executed and loaded. Much of this works already in prototype form, but it waits for the completion of the compiler to go into general use.
I also have plans for a "static" compiler for JRuby that enable compiling Ruby classes into normal, instantiable, callable, static Java classes. This would bring us on par with other compiled languages on the JVM, and allow you to directly instantiate and invoke JRuby/Ruby objects from within your Java code.
Beyond all this work, Tom and I have been discussing a whole raft of performance improvements we could make to the underlying JRuby runtime. There's a lot more performance to be had, and it's just around the corner.
Exciting times, friends. Exciting times.
amy: The beauty of letterpress
<object height='353' width='425'><param name='movie' value='http://www.youtube.com/v/Iv69kB_e9KY'></param><param name='wmode' value='transparent'></param><embed type='application/x-shockwave-flash' src='http://www.youtube.com/v/Iv69kB_e9KY' height='353' wmode='transparent' width='425'></embed></object> The nicest thing as anyone's ever said about my work is 'It's always so suitable to the purpose.' Yes, make it attractive, but make it be what the text needs it to be. Whereas in the wild and wooly world of computer typography, there are no rules. The old guys got it remarkably right. There was an intuitive understanding of what constituted readable text. And so you can be at home with letterpress.
— John Kristensen, Firefly Press JK: "It will die, eventually. Because people will no longer remember how to do it."
Interviewer: "How do you feel about that?"
JK: "It's ok. I'm only responsible for my watch. I'm thankful every day... that I get to do this."
Here's the only link I could find about John Kristensen. Coincidentally, it appears to be the source of the video, and you can see a better-quality Quicktime version there. Here's Firefly Press' page on Briar Press (a letterpress community!).
stephen: LRUG StaticMatic Talk - Slides
There's not a huge amount in these slides, but they do have all the links and references that I talked about last night: StaticMatic LRUG talk slide notes
Brian McCallister: Congrats to the "Best Application Server"!
Seam is not only an application server, it is the Best Application Server. Take that JBoss AS, Geronimo, and Glassfish.
rabble: Buy my neighbor's place
In 2001 I talked my mom and brother in to taking my dad’s inheritance and buying some land with the money. I had wanted to use money i got from working at Palm, but the stock tanked and my share of the internet gold rush went down the drain with everybody elses. Oh well. We searched over an area from Mount Shasta to Mendocino in northern california. Eventually we found an amazing valley with some run down cabins and a really special creek in Trinity County that we could actually afford. We made an offer, but were slow on the draw, and were the second offer. The first one fell through and we the proud owners of 40 acres of woods, meadows, hills, and falling down hippy cabins built in the 70’s.
Eventually we searched online and discovered there was a Wintu name for the valley, Pantilokpom, so that’s what we call it. Corral Bottom, the ‘legal’ name sounds so wild west, and it was Wintu land for a lot longer than it ever was a cattle ranch.
We’ve done a lot with our land, cleared out the slash from the previous owner’s logging, built a pond, put in a water system, fixed up the old hippy cabins, built a new papercrete (recycled paper) house, built a swimming pond, satellite internet, wifi, and even put in an ultimate frisbee field. Look at the pictures.
Over time we got to know our neighbors, two of whom we really like. When everybody is up there we do potlucks, walking up / down the valley to each other’s cabins. Or everybody comes and hangs out swimming in the pond. There’s one neighbor we don’t so much like. They’re from sacramento and the guy’s an ex-marine. He makes jokes about how he doesn’t have to worry about feminists because he’s got his gun. They were never around much, they have some other property in Oregon where they spend their time. If we had the money, we were thinking we’d just contact them and make an offer on their place, but we’ve not had that kind of money sitting around, so we didn’t do anything.
Eventually we heard he’d put the place on the market. So it’s for sale! The trick in that a place remote like that you want to like your neighbors. Until now we’ve been just telling people but i finally found the listing online. They’ve had some offers, at least one fell through, but you can always do a second offer. I know they are willing to carry some of a loan.
So if you’re cool, you’re reading my little blog, which makes you cool in my book, and have a spare chunk of change to buy a $279,000 bit of land in the mountains, then check it out.
Ryan Davis: Seattle.rb batting 1000?
I'm not sure yet (still waiting on more responses on the mailing list), but I think that Seattle.rb is batting 1000 for RubyConf2007!!! A big congratulations goes out to:
- Evan Phoenix - talking about Rubinius.
- Eric Hodel - giving a talk about Über-Productivity.
- Phil Hagelberg - giving a talk on tightening the feedback loop.
And, um... my talk... titled:
Hurting Code for Fun and ProfitIt should be fun... I hope to see you there!
josh: it's easy being redgreen
I can't get by without redgreen to colorize my test output. You can get it to work with all your Rails test tasks by requiring the redgreen gem in test_helper.rb. The problem is, it messes up your test output formatting when you run tests in TextMate using Command-R. The solution is trivial - check to see if any of the TextMate execution environment variables are present:
In test_helper.rb:
require 'redgreen' unless ENV['TM_MODE']Now back to your regularly scheduled internets...
amy: The Tyranny of Lists
Another experiment. I dug up yet another scribbly half-baked essay and decided to turn it into an audio entry. I have a nice mic that I bought for this purpose and I'm learning a bit about audio production here and there (thanks Geoff!). The final result, not edited except to remove 3 "ums" (which I inserted deliberately, bizarrely enough), is a conglomeration of reading my notes and adlibbing. A cookie to anyone who can tell where the reading starts and ends (although I improvise and add to the reading in a few places as well).
You can download it here (AAC/MP4 audio format). Or just read the transcript.
I'm full of myself. I can admit it. I spend a lot of time philosophizing quietly to myself, scribbling in my notebook, you know, at night, 3 in the morning. Sometimes I'm drunk. Not usually, but sometimes.
And I've spent a lot of time thinking lately about how we relate to technology, and about how our pervasive use of technology changes us, changes the way we look at the world, changes the way we look at each other and ourselves. And, to be frank, it worries me.
I've got more than a few pages scribbled in a notebook or two on this topic, and I found one of them just now and it kinda prompted me to want to talk (to a microphone, at one in the morning, by myself). So here I am, talking to a microphone, at 1 in the morning, by myself. (Actually it's 12:55am, but who's counting?)
Anyway. What I wanted to talk about is something that I'll—well, that I already titled "The Tyranny of Lists." Let me tell you, when you're looking through a notebook and you see a line heading up a page, a line like "The Tyranny of Lists," it kinda piques your interest. Or at least it piques mine. And honestly, what piques my interest is what I'm concerned with here. Sorry, guys.
I think we spend a lot of our time organizing and thinking like a computer, just because we can, or because we're used to it. But real life isn't stateful. If real-world things can be said to have states, then they are fluid states. After all, we can't represent a day with state diagrams. We don't order our lives with lists, not really. That's artificial order that we impose on messy, organic things; that's something we learn, in order to interact with technology.
Does it change the way we interact with non-technological things as well? With our daily lives, with nature, with each other? Do we begin to think of human beings as stateful? Either this or that, and if this, then I could do x or y or z, but not a or b.
I worry that this is true. I worry that the way we reframe things to deal with technology becomes our dominant way of approaching the world, rather than another tool in our repertoire, another language we can switch to and switch out of fluidly.
Input this, wait. That didn't work, how do I rejigger it? Hive it a moment to fix itself... or try again from the beginning? Enter data, wait; follow instructions, wait. Restart
Do we think of ourselves this way, too?
I am happy, or I am sad. And if I am sad, then I have these potential avenues. Do I work on things, or hit the reset switch? Can I be introverted and extroverted in the same body/consciousness? Can I be both liberal and conservative, or must it be one or the other? Well-meaning, but ill-doing?
I also see a tendency for people to act as if other human beings are games or problems that they can solve, if they can just find the right inputs, the right levers to press and buttons to push. That they can actually come up with the right sequence of inputs to plug into some formula, to get the person to spit out the reaction they expect, that they desire.
I'm not saying this is necessarily an evil thing, wanting to get what you want out of people, and I don't think the people i'm describing are typically evil people, they just aren't considering that there's another full human being in there, in the other person they're thinking about. They're not sociopaths. If you talk to them, they know intellectually that there's another person in there, I believe. I don't think that they're crazy, and I don't think that they're likely to go on and start torturing small animals and work their way up the food chain. But, at the same time, they go through life thinking that they just need to find that right sequence, the right inputs, the right thing to do, the one way, to get what they want... and that it will work.
But that's not the way it works in reality. Humans are messy. Real life is messy. Fate is a tightly coupled system and it's non-deterministic. There's an illusion, sometimes, of causality, that if you had gone back and done one thing differently, you think you know how things turn out then, with that different input. But, but no. You never know how things will turn out. You can do everything according to plan, perfectly, and things still won't turn out the way you expected, they way they should, according to plan.
You can be so sure that this, that, or the other thing that you did led up to the result you have today. But that's also an illusion. We flatter ourselves in thinking that we understand such things, but there's no way for a human to really comprehend how the world works. And yet because of technology, because of these tools and things we interact with every day, we begin to look at the entire world as a system that we can understand and manipulate. We think we can get the full measure of it. We think that there's some way to approach it—those levers, buttons, inputs that will let us manipulate, let us get what we want. Turn the right dial, get the gumball. But I don't think that's true.
You'll have to forgive me, because when I write about this, and think about this, I feel an overwhelming urge to quote Whitman, pretentious at it may be. Whitman is the best source to cite here, on the subject of human weirdness, contradictoriness, tightly-coupledness, and non-deterministic behavior.
From his most quotable poem, Song of Myself, the three most quotable lines (although I'll say they're not my favorite). Here we go:
Do I contradict myself?Very well then I contradict myself,
(I am large, I contain multitudes.)
It may be the most hackneyed poetry quote I could insert here, but nevertheless it seems appropriate.
I think we all have to remember, a little bit more often, that we're just these fluid-filled sacs governed by hormones and chemicals and electrical impulses, rather than something harder, something more precise, something more binary, digital. We're the ultimate in analogy, really. If you think about it.
And it worries me that we often don't think about ourselves this way, day to day. It worries me that this changes the way people attempt to live their lives, the way they try to construct society or change society, affect change, you know, build governments, without thinking that Input A and Input B do not equal Output C when it comes to humanity.
And my... train has just run out of steam. I have nothing else to say. That's my point. A weak conclusion, perhaps, but that's my conclusion.
rabble: Recommended Rails Hosting
I get asked from time to time for recommendations on where to go for good rails hosting. There are tons of places out there. This is what i’m recommending at the moment. I’m sure in the future it’ll change.
If you’ve got too much money to spend on your VC funded startup and you don’t want to deal with anything go with Joyent. They are smart, use high end hardware, and charge high end prices. The only down side to joyent is that they use a Sun stack, so some standard rails / linux things don’t quite work out of the box.
Next if you have a few hundred dollars a month to spend, then i recommend Engine Yard. They really care about their customers, sponsor Rubinious development, and generally are great guys. By default you get one staging server and two production servers. It’s cool that they incorporate staging and the development cycle in to their hosting. If you get big, they will even built out a custom version of their whole setup for you to run yourself. I’d say the only downside to EY is that they’ve had some growing pains and a few down times as they worked the kinks out.
Some sites only need to scale for short periods of time. Icalico is an event scheduling social network app i work on with kellan. It gets no traffic, and is offline most of the time. But during conferences it gets a big spike in traffic. We use EC2 from amazon for icalico. It’s great, fast, and clean. We keep an image in S3 and pull it out when we need it. EC2 works out to costing $72 per month if you keep one server up and running 24/7. The really nice part is you can add more servers quickly and easily. The downside is if a box hard crashes you loose the file system changes since the last backup, and all the ip addresses are dynamic. We’ve never had a hard crash, but they do happen, and the ip addresses don’t change very often, again never happened to us.
On the cheap end, as cheap as i’d recommend to somebody, is Slicehost. They give you a bare vserver which you have to configure yourself. They put enough ram in them to be useful. I personally have a 512mg slice, but a small rails app is fine running at 256megs of ram. Some ‘other’ vserver hosters over slices with as little as 64 or 32 megs of ram. That’s crazy talk, nothing works in rails land with that little memory. Slicehost does ubuntu, which i like, and while i had to build out my hosting environment and install nginx, etc… it was worth it. I like them a lot. The only downside to slicehost on the low end is they are so popular there is a waiting list for accounts. They are smart and don’t overload boxes like some other hosters.
Things i don’t recommend. I tried Media Temple’s gridserver and didn’t like it. They charge more for less in comparison to slicehost, and they wrap you in a weird environment which makes debugging, deploying, and maintaining rails apps hard. I also recommend against a normal shared host like you’d get for a php app. Rails won’t run that way, it’s not worth trying.
What has worked for other people?
Paul Ingles: Immutable ActiveRecord Attributes
The test:
def test_cannot_change_country_name_once_constructed country = Country.new(:name => 'UK') assert_raise RuntimeError do country.name = 'USA' end endThe class:
class Country < ActiveRecord::Base extend ImmutableModel immutable :name ...The implementation:
module ImmutableModel def immutable(attr_name) define_method "#{attr_name}=" do |new_value| read_attribute(attr_name).nil? ? write_attribute(attr_name, new_value) : raise(RuntimeError, "You can't change #{attr_name} once it has been set") end end end