A couple more items from last week:
Q: What’s a good way to bulk insert a bunch of joined-up models? A: insert into a view. MySQL has updatable views now. This is also a great trick to use in Oracle.
A couple more items from last week:
Q: What’s a good way to bulk insert a bunch of joined-up models? A: insert into a view. MySQL has updatable views now. This is also a great trick to use in Oracle.
Today’s the big day: the Palm® Pre™ has launched.
We’ve been happy to be partner with Palm and we’ve been working very hard towards this day.
We are happy to have several applications in the App Catalog:
When the Mojo™ SDK is publicly available, we will be releasing various open-source tools to aid development:
There was a problem uploading files to s3 through Paperclip with # characters in the name (s3 doesn’t like # characters). There’s a fix on Paperclip trunk, but that hasn’t been packaged into a gem. Perhaps the Paperclip people could be convinced to cut a release?
One team is seeing files on s3 disappear occasionally. They’re using v2 of the s3 api, where the s3 gem uses v1. The team has now turned on s3 logging (which is off by default) – which they recommend everyone turn on as a general good practice.
Sadly, after you do upgrade, when you start doing “git push”, your console will start to be littered with the following oddly patronizing message:
warning: You did not specify any refspecs to push, and the current remote warning: has not configured any push refspecs. The default action in this warning: case is to push all matching refspecs, that is, all branches warning: that exist both locally and remotely will be updated. This may warning: not necessarily be what you want to happen. warning: warning: You can specify what action you want to take in this case, and warning: avoid seeing this message again, by configuring 'push.default' to: warning: 'nothing' : Do not push anything warning: 'matching' : Push all matching branches (default) warning: 'tracking' : Push the current branch to whatever it is tracking warning: 'current' : Push the current branch
While I’m generally in favor of verbose warnings, this one is kind of bizarre. Essentially, it’s saying, “Warning! The command you just ran will continue to operate exactly as it did before!” Guys, telling us about new options is great but that’s what release notes are for.
Worse, they don’t provide keystroke-level instruction beyond the offhand gerund “configuring” on how to shush it. Here’s the result of my 8-minute speluking inside the output of “git help config”:
git config push.default matching
[Or, thanks to Alastair Brunton below
git config --global push.default matching
There, now, that wasn’t so hard after all, was it?
As we’ve been working on applications for the Palm Pre, lots of people have been asking us a lot of questions, most of which we couldn’t really answer yet.
One of the big areas people asked about was what the phone was like. And we just weren’t allowed to say that much to date. But with the launch only two days away, the press has been given a look at the phone, and the response has been overwhelming. And I’m not talking about the Palm trade press, but folks who have been pretty hard to impress, including some big fans of Apple products for years, people like David Pogue, and Walter Mossberg.
So I thought I’d share with you some of the recent articles:
We’re excited to see such leading journalists in the tech space share our enthusiasm for this great new platform. We’re ready to build more great apps for the platform, too, so if you’re interested in how we can help, give us a shout.
It’s the first Wednesday of the month again, and that means it’s time for the Pivotal Labs/Outside.In monthly Ruby Happy Hour. It’s the first one since GoRuCo, so there’s even more to talk about than usual. (Thanks Josh, Francis, and everyone else who made this a great conference again this year.)
Where: Outside.in, 20 Jay St Suite 1019 (10th Fl), Brooklyn, NY
When: 7-9PM today, Wednesday June 3rd
Who: If you’re a developer who uses Ruby and would like to meet some other Ruby folks, toss around ideas, or just have a few beers, we welcome you with open arms!
Last night Pivotal participated in the first ever New Tech Meetup Showcase. The Showcase offered 60 NYC technology companies a chance to show off their wares to a large and enthusiastic crowd, and Pivots Mark Michael, Dan Podsedly, and Ian McFarland held down the Pivotal table, demoing Tracker and seeing what other companies had to offer. The New York New Tech Meetup is the biggest meetup in the world with over 10,000 members, and—this being Internet Week in NYC—many of them were out in force. After the Showcase the action moved to 700-person auditorium where 7 companies gave 5-minute live demos to a rapt house.
The meetup presenters were varied and impressive, running the gamut from human-powered search to some cool geoloco apps (one for social networking and another for 3D mobile iPhone wayfinding) to it-just-works in-browser live video-streaming and production apps, to the NY State Senate’s cutting edge use of social technology to make government more responsive and accountable. The Pivots-in-attendance were especially blown away by two in particular. Aviary is a suite of fully-powered in-browser content creation tools which does for Photoshop and Illustrator what Google Docs did for Microsoft Office: it makes them cheap, available to any computer with a net connection, and facilitates collaboration and sharing. The fact that these apps are fast enough and robust enough to compete with desktop software is pretty inspiring. The second super-uber-cool demo we saw is called MakerBot, a company that’s building and marketing and community-organizing a $750 open-source desktop 3D printer. The kit is open-source, so you don’t actually need to pay MakerBot to get all the parts, but sourcing them yourself is kind of a pain. MakerBot is making it easier for everyone to have and use and imagine a robot on your desk that can build anything you can imagine. Very inspiring stuff, and proof that there’s awe-inspiring cutting-edge tech on both coasts.
A Scrum team found they were doing too much context-switching, so they applied a dash of Kanban. It’s an interesting example of Kanban principles in action.
We used the term Feature Flow to describe the goal of the team: to let features flow through the team without interruptions. Any feature that is in a state of waiting, or is simply taking more than a few days is analysed. It’s moved to done as quickly as possible by scrambling more team members. When we encounter features getting stuck, we don’t pick up more work, we try to find the root-cause of the stickiness and solve that. We increased the quality and capabilities of our build environment a few times for that very reason: to prevent future blockage in our flow of features.
When we introduced the ‘work-in-progress’ limit, we also temporarily stopped doing planning meetings, as our first target was getting the w.i.p. down to 8. The interesting side effect was, that we were working for a few weeks without the need for a planning session. So we stopped the fixed-date planning session and replaced it with an ad-hoc planning session whenever the ‘sprint-backlog’ was drying up. From our coarsely estimated product backlog our product owner introduced a couple of days worth of features each planning session. The great thing was that the priorities could change at the last moment, as long as the team hadn’t started working on a feature. As the Sprint planning meetings were always quite strenuous, the just-in-time one-hour planning sessions kept the teams energy at a constant.
Yehuda’s GoRuCo talk was on the subject of Rails as a Ruby citizen – that while Rails was already a pretty good Ruby Citizen with 2.3, 3.0 is about making it a better citizen.
Many are building apps on top of Rails, not considering making an extension, just building on what’s available. Others are building extensions full-time. In the vast many are power users working on long-term projects, building apps primarily, but in the course of it making tweaks and extensions to Rails.
Rails is built on many other Ruby libraries: Rack, Test::Unit, Erb (soon to be replaced with Erubis).
Other libraries use Rails as a library, e.g Spree, ActiveMerchant, Radiant, Sproutcore.
Also, Rails works with other libraries, and can be optionally used with them, for example as in the case of Haml.
Prior to Rack, frameworks would right special handlers for each of its interfaces, with all sorts of attendant inconsistencies. Rack, when introduced, seemed to solve this problem, and so was incorporated into Merb.
But Rack is actually much more than this. It enables you to write Middleware, which is components of code integrated to the generic Rack interface. This enables functionality to be consolidated into single-purpose middleware components, with all other components remaining ignorant of the others.
In Rails 2.3, they applied Rack to Rails, making each controller a middleware endpoint selected by the router, which was another middleware component.
But good Rack endpoints don’t do dispatching, they just pass-through one-to-one. So in 3.0, the router will point at a specific action.
As with ruby libraries in general, Rails is a citizen in the Rack ecosystem, using Rack, working with other Middleware, and providing its own which is then used in other frameworks.
To this end, Rails 3.0 will split out things like rescuing, params parsing and session handling into middleware which is then usable downstream without pulling in all of Rails.
In Rails you can use middleware via “config.middleware.use Foo”
By generalizing Rails via Rack, Rails is able to use generalized Integration testing by simply treating Integration test as a Server which issues commands to the Rails stack via the standard Rack interface. Already Rails 3.0 works with rack-test.
Why does ORM agnosticism matter? ActiveRecord is Ruby, DataMapper is Ruby, one should be able to just require the alternative and use the library.
But Rails has dependencies on the ORM, for example in the form_for helper, which works for a specific interface.
Merb 1.0 offered “Agnosticism” by offering 2 interfaces, one for ActiveRecord, one for DataMapper. If you wanted to work with merb, you had to offer one of those interfaces, as CouchDB did.
To provide a general solution, Rails needs to provide a standard abstract interface which anyone can implement in order to interface with Rails.
One can meet this interface by:
Rails will ship with the prototype version of this, Yehuda is planning to write the jQuery equivalent, Mootools and others will provide their equivalents as well.
In Rails 2.3, simple actions would spend 20% of their time in filters. Filters are important in small applications which do a lot of traffic and performance-intensive apps.
Historically, parts of Rails filters (Before, After, Conditions) had been factored out into ActiveSupport, but Around filters and skipping were more difficult to filter out, and so hadn’t been. Rails 3.0 integrates all the rails filtering in a performant way.
In 2.3, Rails asks the filter a bunch of questions, even if it’s a simple filter, which you’d expect to be fast, then sends. This checking is runtime, when all the necessary information is available in advance.
Rails 3.0 uses metaprogramming to compile the various filters down into a single method which is simple and quick.
Action Mailer and Action Controller had diverged and require separate implementations on many fronts. The better way is to call use modules to attach functionality to either class, from a common base. It uses super to iterate over each modules implementation in order.
The result is a bunch of layers doing a single thing, taking and producing normalized data. You can remix and insert your own equivalents.
In Rails 3.0 one can set _action_view method with a renderer object which then implements alternatives to or extensions on the Rails action_view helpers.
Equivalent to ActionController, with expensive modules excluded, to which you can attach your own functionality.
On of Yehuda’s goals: “How easy would it be to implement Sinatra on top of Rails?”
Likewise, how can Rails be made such that it’s functionality is more available to other projects such as CloudKit.
In Q & A, Yehuda notes that in Rails you can get away without knowing too much about inheritance and subclassing, while “more crazy” languages force you to know this. He hopes that Rails 3.0 will bring more awareness of this to Ruby.
Ben Stein of Mobile Commons is giving a talk on Cross-platform Mobile App development. They hadn’t done any client mobile work, but lately clients have been asking “what about iPhone?,” “what about Android?” and the like. Whether or not this question of navigating the mobile client world is important to you now, Ben predicts it will soon be, as that’s where we’re headed.
Thoughts and experiences from Mobile Commons’ first mobile client apps:
Mobile give you capabilities not available elsewhere:
This is a big list – serious stuff.
“There are only so many hours in the day to learn new technologies.”
Also defines a mechanism for enabling intelligent client-side caching.
Ben then demos a sticky-note app which works currently in Safari, and works with client-side persistent storage.
This makes cookie resurrection easy, so the designers include a same-domain policy in the spec, to reduce access.
Currently uses the app-cache and asynchronous updates to enable offline access.
jQuery minus all the browser compatibility code, optimized for Webkit & Mobile phones.
Don’t use Curl to test these apps, use HttpClient, which deals with much of the basics, including authentication
The phone number is linked with the a ‘tel:// ‘ URI which then allows initiating a call from within the phone.
These projects can be built and managed out of eclipse for Android and XCode for iPhone.
What about Migrations?
There’s no easy answer, this is one of the reasons we switched to Web development, because we have more control and the easy ability to push updates. Client migration support is also theoretically possible, but has yet to be implemented.
All of Sandi’s code is available here.
Fact: your application is going to change. How will your application handle that change?
Robert Martin says your app can behave a couple of different ways:
In the beginning, though, your app was perfect. “Dependencies are killing you!”
The Design Stamina Hypothesis says that, after a certain point, you’ll have done better if you had designed first.
“Skip design, if you want your app to fail.”
To avoid dependencies, your design should be:
SOLID principles we can ignore in ruby:
Really only a problem for statically-typed, compiled languages. Because we’re in Ruby, we don’t have this problem! Win!
“Dynamic languages obey this rule in the most extreme way possible: duck typing.”
When you design, don’t break the contract of the superclass in the subclass.
Sandi draws her examples of applicatoin change from the source code at: http://skmetz.home.mindspring.com/img28.html.
Lesson #1: Resistance is a Resource.
If testing seems hard, examine your design. Tests depend upon the design of the code. “TDD will punish you if you don’t understand design.”
During refactoring, ask yourself:
The answers should all be ‘yes’.
Sandi references her code to demonstrate when and how to mock and use dependency injection to achieve Single Responsibility, in which a class both downloads and acts upon the downloaded data.
She urges developers to do the simplest possible refactoring when extracting responsibilities from a class.
“Refactor, not because you know the abstraction, but because you want to find it.”
Sandi uses a very interesting example of building a Config class which behaves differently in different Rails environments. The first version had a lot of smell, and with a combination of hash parameters, YAML file, and metaprogamming, she demonstrates how to be open for extension, but closed for modification.
Sandi explains that paying attention to your classes’ dependencies is important. If a relatively static class is dependent on a class that changes more often, that’s a smell! Use dependency injection to avoid Dependency Inversion.
“TDD, BDD and DRY are all good, but they are not enough.”
“Design because you expect your app to succeed, and the future to come.”
Sandi recommends reading:
Over lunch with Jake, I’d wondered aloud “where are all the wide-eyed optimistic presentations?” and Jake starts by saying he’s sorry that this will not be one of those talks.
We’ve been programming in Rails for several years now, and now more than ever we’re left with the problem of how to deal with, maintain and correct projects which may be riddled with out-dated thinking, mistaken ideas and problematic implementations.
In other skilled enterprises there are core ideas which are repeated by for practice and for their general utility. In martial arts, these are called “katas,” in programming, we have “patterns.” Patterns are general, reusable solutions to common problems in software engineering, which are often arrived at through emergent design. Anti-patterns, likewise, emerge in the general work on a project, but their presence is harmful. They’re the mistakes we make again and again in our projects.
Jake then laid out a few patterns and anti-patterns for your consideration:
Some of the most egregious anti-patterns come from simple ignorance about the APIs available, and the consequential re-implementation of basic Ruby or Rails functionality. The Rails and Ruby APIs are both well-documented and important to your work. There’s no excuse not to know them.
While we must install a plugin or gem to use it, often we move on without doing the important job of cleaning up after ourselves.
People litter ‘self’ all over the place. The only place you need self is on assignment. And all this could be replaced with the simple line:
@value ||= 600
What does this even mean? ‘nil?’ is false unless inside NilClass
Occasionally we hack away in IRB and, once we get the results we’re looking for, drop the code into our app without a second thought. This can produce some very buggy, obtuse, far-from-minimal code. Once we discover a mechanism, better to revisit the problem and produce the code in a more stable context.
Confusing. Not to be used outside of a predicate method.
Will you remember what your boss tells you to do a year ago? Will you unknowingly violate these past decisions and understandings? To avoid doing so it’s important to maintain active specs against your app.
Jake recommends Cucumber + Webrat for carrying this out.
There’s a gem called metric_fu, a gem full of analytics. One in particular is known as Reek, which sniffs out code smells.
Run reek against your app, and it will find long methods, for example, and return all of the methods that are longer than 5 lines. And you can make your tests fail on the existence of these methods, to keep yourself and your team in check.
Orphans are methods, models, views or controllers, or any other bit of functionality which is disconnected from the rest of your app. Like un-used plugins or gems, orphan code is noise which keeps your code from being easily maintainable.
We can look to the more modular, merb-style project organization as a way of better structuring our projects. Likewise the Fat-model, Thin-controller design pattern helps us to create easily-testable, well-organized apps.
assert_equal 2, User.count
This test fixtures, and activerecord, and its very presence hinders us by interfering with our view of more meaningful tests.
Any slow test has a cost of both slowing the testing feedback loop and making it less likely that we’ll run the tests as often as we should.
Coupled tests mean that a test depends on the side-effects of other tests, or on the effects of an outside service or application. Instead we can mock out the outside web service or operation
Discuss your code conventions and style with the team, settle on a set of best practices, and write them down. Store them in a style guide in the project root or document directory.
Jake recommends using Integrity Continuous Integration Server. Whether you use that or Cruise Control, or any other option, continuos integration insures your specs and tests are frequently and consistently run.
Generating and maintaining build artifacts, such as statistics reports from your reek run or performance tests can enable you to track your progress over time. In addition, you put minimal expectations on these
Taking time every few months to review your recent progress, and discuss problems and progress.
Someone mentions a particularly egregious example of a test which deleted its own application code in the process of running.
Jake responds that in cases where tmp deletion and file generation, it may be appropriate to have a safe version of the test which runs locally, and a separate exhaustive test which runs in a sandbox staging environment. This allows you to exercise the more dangerous tests in a safe environment.
Yehuda mentions one way to do this is to mock in the safe version, and turn of that mock in the sandbox environment.
Jake then shows a 45-line login method and points out how difficult it is to immediately grok. Newer-code built in the REST-ful style is much simpler to work with.
By discussing these approaches with old-hands and newbies alike, we can all improve the quality of our code, spend less time dealing with bugs or code comprehension, and more time building out the next great Rails projects.