Channels
Displaying page 80
Favorite
Posted 7 months ago at ones zeros majors and minors

Since switching to Chrome the thing I've missed most is the ?# hotkeys for bookmarks.

In Safari you can hit ⌘1 to open the first bookmark in your bookmark bar, ⌘2 to open the second, etc. This means you can keep your bookmark bar closed and jump to any site whose number you know pretty quickly. No clicking or extra UI required!

In Chrome, ⌘N quickly switches you to the corresponding tab in the active window. Some people love this. That's great, and they're not wrong - it's a cool feature. What's wrong is having to pick sides.

Spark is a great piece of OS X software which lets you bind key combinations to anything - Applications, AppleScript, etc.

Spark

I've bound F1, F2, F3, and F4 to AppleScripts which open the sites I want.

Here's an example:

do shell script "open https://mail.google.com/a/ozmm.org/"

Spark

No more relying on the browser of the month for this functionality. Sweetness.

back to top
Posted 7 months ago at The GitHub Blog

Join us on Thursday January 28th at 8:30pm for a drink at the Irish Bank! We’d hate to have to release the hounds.

Stop by for a surprise visitor!

back to top
Posted 7 months ago at lindsaar.net - a different view

Action Mailer has long been the black sheep of the Rails family. Somehow, through many arguments, you get it doing exactly what you want. But it takes work! Well, we just fixed that.

Action Mailer now has a new API.

But why? Well, I had an itch to scratch, I am the maintainer for TMail, but found it very hard to use well, so I sat down and wrote a really Ruby Mail library, called, imaginatively enough, Mail

But Action Mailer was still using TMail, so then I replaced out TMail with Mail in Action Mailer

And now, with all the flexibility that Mail gives us, we all thought it would be a good idea to re-write the Action Mailer DSL. So with a lot of ideas thrown about between David, Yehuda and myself, we came up with a great DSL.

I then grabbed José Valim to pair program together (with him in Poland to me in Sydney!) on ripping out the guts of Action Mailer and replacing it with a lean, mean mailing machine.

This was merged today.

So what does this all mean? Well, code speaks louder than words, so:

Creating Email Messages:

Instead of this:

 class Notifier < ActionMailer::Base
   def signup_notification(recipient)
     recipients      recipient.email_address_with_name
     subject         "New account information"
     from            "system@example.com"
     content_type    "multipart/alternative"
     body            :account => recipient

     part :content_type => "text/html",
       :data => render_message("signup-as-html")

     part "text/plain" do |p|
       p.body = render_message("signup-as-plain")
       p.content_transfer_encoding = "base64"
     end
     
     attachment "application/pdf" do |a|
       a.body = generate_your_pdf_here()
     end

     attachment :content_type => "image/jpeg",
       :body => File.read("an-image.jpg")
     
   end
 end

You can do this:

class Notifier < ActionMailer::Base
  default :from => "system@example.com"
  
  def signup_notification(recipient)
    @account = recipient

    attachments['an-image.jp'] = File.read("an-image.jpg")
    attachments['terms.pdf'] = {:content => generate_your_pdf_here() }

    mail(:to => recipient.email_address_with_name,
         :subject => "New account information")
  end
end

Which I like a lot more :)

Any instance variables you define in the method become available in the email templates, just like it does with Action Controller, so all of the templates will have access to the @account instance var which has the recipient in it.

The mail method above also accepts a block so that you can do something like this:

def hello_email
  mail(:to => recipient.email_address_with_name) do |format|
    format.text { render :text => "This is text!" }
    format.html { render :text => "<h1>This is HTML</h1>" }
  end
end

In the same style that a respond_to block works in Action Controller.

Sending Email Messages:

Additionally, sending messages has been simplified as well. A Mail::Message object knows how to deliver itself, so all of the delivery code in Action Mailer was simply removed and responsibility given to the Mail::Message.

Instead of having magic methods called deliver_* and create_* we just call the method which returns a Mail::Message object, and you just call deliver on that:

So this:

Notifier.deliver_signup_notification(recipient)

Becomes this:

Notifier.signup_notification(recipient).deliver

And this:

message = Notifier.create_signup_notification(recipient)
Notifier.deliver(message)

Becomes this:

message = Notifier.signup_notification(recipient)
message.deliver

You still have access to all the usual types of delivery agents though, :smtp, :sendmail, :file and :test, these all work as they did with the prior version of ActionMailer.

Receiving Emails

This has not changed, except now you get a Mail::Message object instead of a TMail object.

Mail::Message will be getting a :reply method soon which will automatically map the Reply related fields properly. Once this is done, we will re-vamp receiving emails as well to simplify.

Old API

And… of course, if you still “like the old way”, the new Action Mailer still supports the old API and all the old tests still pass. We have moved everything relating to the old API into deprecated_api.rb and this will be removed in a future release of Rails.

Summary

With Mail and this refactor, Action Mailer has now finally become just a DSL wrapper between Mail and Action Controller.

blogLater

Mikel

back to top
Favorite
Posted 7 months ago at Ruby5

Looking back on the Rails 3 BugMash, we cover quite a few Rails 3-specific topics. We also talk about domain page caching, Prowl, and MockSMTP.

back to top
Favorite
Posted 7 months ago at Ruby Quicktips

You can add or subtract days or month from a Date object:

  • +(n): add n number of days
  • -(n): subtract n number of days
  • >>(n): add n number of months
  • <<(n): subtract n number of months

Here are some examples:

$ irb
>> date = Date.today     # => #
>> date.to_s
=> "2010-01-26"
>> tomorrow = date + 1   # => #
>> tomorrow.to_s
=> "2010-01-27"
>> nextmonth = date >> 1 # => #
>> nextmonth.to_s
=> "2010-02-26"

Read the documentation for a more precise description.

back to top
Posted 7 months ago at A Fresh Cup

Yesterday's catches in the link sea...

back to top
Posted 8 months ago at the { buckblogs :here } - Home

This is the fourth (and final) article in a series titled “There is no magic, there is only awesome.” The first article introduced the four cardinal rules of awesomeness, the second was about knowing thy tools, and the third encouraged you to know thy languages .

First off, I apologize for dragging this out. It’s really become a weight on my shoulders. I’ve been fretting and fretting about writing the last two or three posts in this series, and I just couldn’t find the inspiration to make them come out like I wanted…and they’ve been holding up other posts I’ve been wanting to write.

So I’m going to cheat. You’re going to get a braindump, more or less, of the last two rules of awesomeness. Yes, I am entirely cognizant of the irony here. Nonetheless, here goes.

Rule #3: Know thy libraries!

If you want to be awesome, know your dependencies. At the very least, understand what each plugin, library, and technique you use, does. If called on to explain why you are using a particular design pattern, could you justify it? If someone asked you to compare plugin X and plugin Y, could you explain what their different strengths and weaknesses are? If you discover a particular library behaving erratically, would you be able to dig into the library’s guts to tell the author roughly where the problem is? Or would you be one of those who has to tug on the author’s sleeve and say, metaphorically, “it hurts when I do this”?

By libraries, I mean (essentially) any bit of code that you depend on, that has a life of its own outside your application. I’m including design patterns in this, although they aren’t really code, but they do represent a “library” of possibly ways to architect code. Basically, if you’re using someone else’s code, algorithms, or techniques, know why you’re using them. Make sure you can answer the four questions:

  1. What does this do best?
  2. What does this do worst?
  3. Why should I use this in particular?
  4. When was the last time I learned something new about this?

Rule #4: Know thy communities!

The last rule says that if you want to be awesome, you can’t do it in a vacuum. By writing code, you automatically join an ecosystem, whether it be a network of coworkers who will help you write, debug, deploy, and maintain that code, or a community of hobbyists who might wish to use your code in applications of their own (or who are writing code that you want to use). Even if all you do is pop up out of your cave long enough to toss some code into the public domain, you’re still contributing to a community, and if you’re using other people’s code, then you’re a consumer as well.

Don’t be blind to those communities. Stop for a minute and think about the communities you belong to, whether explicitly (where you’re a card-carrying, due-paying member) or implicitly (where you’re passively consuming someone else’s code), or somewhere in-between.

Why is this important? Mostly because communities are resources. Each community will be good for different kinds of help, collaboration, or criticism, and if you want to make the most of those resources (which, if you’re really awesome, you will), you need to know where each shines. Again, apply the four questions. What does this community do best? What is it worst at? Why should I participate in this particular community, over all the possible alternatives? And when was the last time I learned from this community?

That last is important, and surprisingly deep. If you are no longer learning from a community, what are you still doing there? Some of you are no doubt saying “but, but, but” and eagerly pointing out that maybe someone is part of a community so that they can lift others up, but note: if you’re doing that right, you’re still learning from those you teach. You learn new ways that your craft can be confusing to people. You learn new ways of looking at things that you’ve been taking from granted. You learn new ways to rephrase concepts that have grown stale in your own mind. It keeps you fresh. If you’re doing it wrong, though, then the only reason you remain in a community that teaches you nothing is complacency. And complacency is on the opposite end of the excellence spectrum from awesomeness.

Words of caution

So, those are the four rules. There is one overriding caveat to all of this, though, and that is: use moderation. You’re not going to master all of this in a day. Or even a week, or month, or year. I don’t know anyone that is perfect at all four things (though I know many who are much, much better than I am). To sound all zen and mysterious: awesomeness is a journey, not a destination. Enjoy the trip, appreciate the view, but don’t overdo it.

When you overdo it, you risk burning out. I’ve been riding that line for a couple years now, which was frightening. When writing code is your bread and butter, paying the bills and putting food on the table for you and your family, it is scary to contemplate “what do I do when I suddenly don’t want to do what I’ve been doing”. This is a big reason why I had to let go of Capistrano and other projects, and why I’ve discovered other hobbies (like woodcarving, string figuring, and cooking) that do not involve computers. I’m trying to find the middle ground, so that I can recapture the joy of writing code.

So: be awesome. But only in moderation.

back to top
Posted 8 months ago at RubyLearning Blog

Ruby Programming Challenge For Newbies

RPCFN: Fair Distribution (#6)

By John Trupiano

About John Trupiano

John TrupianoJohn Trupiano (twitter) is the co-founder of SmartLogic, the premiere Ruby development team in Baltimore, Maryland. He is an active member in the technology and business communities in the mid-Atlantic region. He is highly involved with the local Ruby user group (Bmore on Rails) and recently organized the first ever Maryland TechCrawl, a show and tell event showcasing the exciting and innovative technologies being developed in the region. He is also very active in the open source community having authored timecop and Rack::Rewrite and contributing to a slew of projects including rails, capistrano, shoulda, factory_girl, gemcutter and multitest.

John has this to say about the challenge:

I think the Ruby challenge is great because it instills from the very start the idea that you need to practice to become a great programmer. Even as a problem setter, I have found the exercise of defining a problem and iterating through various solutions to be extremely educational and beneficial. Satish has cultivated a fantastic program here that provides access for beginners to seasoned Ruby programmers. Furthermore, the Ruby challenge serves as a notice to the Ruby community that it is important for us to provide a welcoming and nurturing environment for newcomers.

Our Awesome Sponsors

This monthly programming challenge is co-sponsored by Backup My App and Caliper.

Backup My App

Backup My App is an automatic backup service for Ruby on Rails applications. You simply install the plugin to your Rails application and they handle the rest of the process. They store backup history for several weeks and you can restore any of them automatically. Try out their 1 GB plan for free. Backup My App has co-sponsored this challenge and is proud to make this contribution to the Ruby community.

Caliper

Caliper provides free, hosted metrics for Ruby programmers. Find duplication, code smells, complex code and more! Get set up with just one click!

Prizes

  • The participant with the best Ruby solution (if there is a tie between answers, then the one who posted first will be the winner) will be awarded any one of PeepCode’s Ruby on Rails screencasts and a free 10 GB account for a year from Backup My App.
  • From the remaining working Ruby solutions, three participants would be selected randomly and each one would be awarded any one of Pragmatic’s The Ruby Object Model and Metaprogramming screencasts.
  • All the participants in this challenge (except the participant with the best Ruby solution) will get a free 5 GB account for 6 months from Backup My App.

The four persons who win, can’t win again in the next immediate challenge but can still participate.

The Ruby Challenge

RPCFN

The Challenge

Imagine that you manage a t-shirt printing company. Each morning you review all orders placed the prior day and determine how long each order will take to fulfill. On any given day, only a certain number of your printing machines are operational. Your job is to schedule each printing job with one of the operational printing machines in such a manner that (a) all t-shirts are printed in the least amount of time, and (b) the distribution of work across machines is as fair as possible (i.e. the standard deviation of the time each machine spends working is minimized).

Your objective is to write a FairDistribution class that satisfies the following test cases. The code in the test cases is sufficient to define the methods you must implement.

This is an NP complete problem, and as such I have only provided very small datasets in the test cases. Test case #3 takes the longest to solve (See **Notes below about how to run the Test Case #3) and you may find it easier to comment it out early in your development phase. On a MBP Pro with a 2.4 GHz dual core processor and 4GB RAM, it took just over 3 minutes to solve. The other three test cases took only a couple of seconds.

Note that test cases 2 and 4 define specific distributions against which you can verify. Test cases 1 and 3 have more than one acceptable distribution and as such I have not provided a specific distribution to test against.

Note also that there is a well known algorithm that provides a much faster though not optimal solution. It will pass all tests except for test case #3. If you are only able to determine this particular solution, please still consider submitting your solution for consideration.

** Notes: To accommodate the fact that Test Case #3 takes a long time to run, you can run the test normally, and TC#3 will not run. When you want the TC#3 to run, then you can run the following:

ruby test_solution_acceptance.rb full

The word “full” will signal it to run all the test cases.

The Test Suite

test_solution_acceptance.rb

Requirements

The solution to the challenge has to be a pure Ruby script, using only the Ruby Standard Libraries (meaning, no external Gems). You do not need to build a gem for this. Pure Ruby code is all that is needed.

How to Enter the Challenge

Read the Challenge Rules. By participating in this challenge, you agree to be bound by these Challenge Rules. It’s free and registration is optional. You can enter the challenge just by posting the following as a comment to this blog post:

  1. Your name:
  2. Country of Residence:
  3. GIST URL of your Solution (i.e. Ruby code) with explanation and / or test cases:
  4. Code works with Ruby 1.8 / 1.9 / Both:
  5. Email address (will not be published):
  6. Brief description of what you do (will not be published):

Note:

  • As soon as we receive your GIST URL, we will fork your submission. This means that your solution is frozen and accepted. Please be sure that is the solution you want, as it is now recorded in time and is the version that will be evaluated.
  • All solutions posted would be hidden to allow participants to come up with their own solutions.
  • You should post your entries before midnight of 20th Feb. 2010 (Indian Standard Time). No new solutions will be accepted from 21st Feb. onwards.
  • On 21st Feb. 2010 all the solutions will be thrown open for everyone to see and comment upon.
  • The winning entries will be announced on this blog before end of Feb. 2010. The winners will be sent their prizes by email.

More details on the RPCFN?

Please refer to the RPCFN FAQ for answers to the following questions:

Donations

RPCFN is entirely financed by RubyLearning and sometimes sponsors, so if you enjoy solving Ruby problems and would like to give something back by helping with the running costs then any donations are gratefully received.

Click here to lend your support to: Support RubyLearning With Some Love and make a donation at www.pledgie.com !

Acknowledgements

Special thanks to:

  • John Trupiano.
  • Sponsors Caliper and Backup My App.
  • GitHub, for giving us access to a private repository on GitHub to store all the submitted solutions.
  • The RubyLearning team, namely Jeff Savin (Canada), Mareike Hybsier (Germany), Peter Crawford (Italy) and Satoshi Asakawa (Japan).

Questions?

Contact Satish Talim at satish [dot] talim [at] gmail.com OR if you have any doubts / questions about the challenge (the current problem statement), please post them as comments to this post and the author will reply asap.

The Participants

There are two categories of participants. Some are vying for the prizes and some are participating for the fun of it.

In the competition

  1. Rajesh Tripathi, USA
  2. Aleksey Gureiev, Australia
  3. Aldric Giacomoni, USA
  4. Adam Lum, USA
  5. Brad O’Connor, Australia
  6. Martin Linkhorst, Germany
  7. Elijah Miller, USA
  8. Guillaume Petit, France

Just for Fun

  1. Dominik Masur, Germany

Previous Challenge

RPCFN: Mazes (#5) by Peter Cooper.

Note: All the previous challenges, sponsors and winners can be seen on the Ruby Programming Challenge for Newbies page.

Update

  • The (#7) challenge by James Edward Gray II, USA is scheduled for 1st Mar. 2010.

Technorati Tags: Ruby, The Ruby Programming Language, Ruby Programming Challenge For Newbies, Programming, RPCFN, John Trupiano

back to top
Posted 8 months ago at Ryan Tomayko

Aristotle explains how he uses git’s index and how it makes git unique among VCSs. I've raved about git’s index before in The Thing About Git. It’s great.

# | Discuss

back to top
Favorite
Posted 8 months ago at Ruby Best Practices

Ever since 2005, I’ve been attending and speaking at Ruby events. But the one thing I always wanted to do was run training sessions. Thankfully, over the last couple years, LSRC has allowed me to get my feet wet — but only as one of many excellent choices in a lineup of Ruby’s best and brightest. Until last weekend, I had never participated in professional training event that stood on its own.

What eventually became “The Compleat Rubyist” training, was originally an idea for “The Compleat Rubyist” book promotion. Jeremy McAnally, David A. Black, and myself have all written Ruby books, and they seem to compliment each other well. But in doing this, we realized that it would be more valuable, and more fun, to bring our show out on the open road rather than package it up in a box set.

Thus, our training event was born, and we set our sights on Tampa, FL for its first incarnation.

The Training

Instead of having a linear, specific set of bullet points to teach from, we broke our training into four half-day sessions that are representive of some of the most important topics in the Ruby ecosystem. This gave us a lot of leeway to adjust our materials and discussions based on individual student needs. The topics we picked were “Ruby Versions and Implementations”, “Metaprogramming”, “Testing”, and “Style and Substance”. Though these may seem a bit amorphous on first sight, they do a pretty good job of covering four key topics that a budding Rubyist must understand and come to appreciate.

Here are just a few thoughts from each of the modules, after seeing how things played out in class.

Ruby Versions and Implementations

One of the main things that keep people from trying out the alternative Ruby implementations and the various versions of Ruby is that they’re understandably afraid of messing up their systems. So David took a three-pronged approach to helping students overcome that fear.

The easiest stepping stone, perhaps, was to use ruby-versions.net. This great resource (maintained by David), lets you try out all sorts of ruby versions and implementations via a shell account so that you don’t need to worry about touching anything on your own machine. While this isn’t meant to be a long term solution, it’s probably the easiest way that you can try out pretty much any version of Ruby without having to go hunt down, install, and configure their packages.

In addition to this, David showed folks how to make use of multiruby (a tool that’s part of ZenTest). My favorite example of the whole day was one showing that using Ruby 1.8.7, it’s possible to write code that works on neither 1.8.6 nor 1.9.1, which lead into a whole other interesting discussion:

  $ multiruby -e "p 'hello'.map(&:upcase)"

  VERSION = 1.8.6-p388
  CMD     = ~/.multiruby/install/1.8.6-p388/bin/ruby -e p 'hello'.map(&:upcase)

  -e:1: wrong argument type Symbol (expected Proc) (TypeError)

  RESULT = pid 3988 exit 1

  VERSION = 1.8.7-p249
  CMD     = ~/.multiruby/install/1.8.7-p249/bin/ruby -e p 'hello'.map(&:upcase)

  ["HELLO"]

  RESULT = pid 3991 exit 0

  VERSION = 1.9.1-p378
  CMD     = ~/.multiruby/install/1.9.1-p378/bin/ruby -e p 'hello'.map(&:upcase)

  -e:1:in `<main>': undefined method `map' for "hello":String (NoMethodError)

  RESULT = pid 3995 exit 1

  TOTAL RESULT = 2 failures out of 3

  Passed: 1.8.7-p249
  Failed: 1.8.6-p388, 1.9.1-p378

We also took a look at rvm , which is another neat tool for managing multiple Ruby versions. While not necessarily a tool for every possible need, it is a very easy way of managing multiple rubies side by side without trashing your system-wide configurations.

Between these three tools, the students ended up with all they needed to explore the different implementations and versions for themselves. But that was really just the beginning. David then went on to discuss the various peculiarities across the board, and was sure to discuss where certain implementations or versions excel, and where they fall behind.

I’m happy to say that while very few of the students in our class had even tried Ruby 1.9 before our training, every one of them had the opportunity to do so before this session ended.

Meta-programming

At one point in time, everyone using Ruby thought meta-programming was some sort of magic. But in a post-Rails world, it is increasingly easy to help folks understand that all of this “voodoo” we do is really just making use of public method calls provided by Ruby objects that allow you to modify Ruby itself. Once a decent understanding of Ruby’s object model is established, all of the rest of the puzzle pieces just seem to fall into place.

This session had a lot of great discussions, and several exercises to encourage students to actively learn the tricks of the trade. Along the way, we stumbled across this interesting distinction between undef_method and remove_method:

  class A
    def foo
      "bar"
    end
  end

  class B < A
    def foo
      "baz"
    end

    remove_method :foo
  end

  class C
    def foo 
      "bar"
    end
  end

  class D < C
    def foo
      "baz"
    end

    undef_method :foo
  end

  p B.new.foo # "bar"

  p D.new.foo # raise NoMethodError

Testing

Fortunately, virtually all of our students had experience with test driven development of some sort or another. I think that’s a big difference between the Ruby ecosystem today and of say, 5 years ago. But similar to versions and implementations, there are so many choices out there that it’s hard to know what’s what. Jeremy kicked off this module with a state of the union address, breaking down the various different philosophies and toolchains there are out there, and what each of them bring to the table.

Once we got people thinking about the different options for testing out there, we decided to give them a glimpse behind the curtain to realize just how non-magical testing could be. To do this, we demonstrated not one, but two minimal testing frameworks that we built in less than a page or two of code to demonstrate the key concepts. While neither of these tools would be sensible to use in production, they both show how non-magical a test runner is under the hood.

Finally, David gave an open ended testing exercise that was a big hit. Pizza came, but some of our students ignored it until we reminded them to take a break. Many kept working on through lunch, all pairing together and actively discussing all sorts of language questions that went far beyond the scope of the exercise.

Style and Substance

This was my topic, and it went way better than I could have expected it to. I had a lot more content prepared than what I ended up getting to, mainly because we decided to collect some of the open questions that had come up in class and discuss those before running our scheduled content. The infamous class variable problem was discussed in great detail, and while I thought I had mastered their weaknesses, I even managed to mess up one of my assumptions about their behavior. Incase you’ve never been exposed to this fun before:

  class A
    @@foo = "from A"
  end
   
  class B < A
    @@foo = "from B"
  end
   
  # What's the value of @@foo in A now...?
   
  class A
    puts @@foo
  end
   
  # => from B
   
  # They're shared up the hierarchy?? BOOOO!!!
  # What's even worse? This ->
   
  class C
  end
   
  class D < C
    @@bar = "Magically different..."
  end
   
  class C
    @@bar = "And delicious."
  end
   
  class D
    puts @@bar
    # => Magically different...
  end
   
  class C
    puts @@bar
    # => And delicious.
  end
   
  # ZOMG THEY'RE NOT SHARED NOW.

Of course, the only sensible style advice here is to not use class variables at all, and since class instance variables can do the job just as well, that’s not really a big deal. We discussed how to do that, and then moved on to the regularly scheduled content.

I’m not sure whether we had an especially strong set of students or if people are just starting to “get” basic Ruby style idioms, but based on the first day and a half, it was evident that our students didn’t need to be told these basic things. Instead, I talked about “Ruby Style and Substance” at a more philosophical and design-oriented level, which is where I think our community tends to be weakest. Without giving too much away, a lot of my examples stemmed from discussions we’ve been having about refactoring Prawn before it’s 1.0 release, so you can check out our mailing list for a whole bunch of interesting design discussions if you want access to some of the raw materials I used for this session.

In the end, we gave everyone a chance to try their hand at basic API design for a fictional library we cooked up. I’m proud to say that every one of our students produced something that would be passable in an open source project. Ideally speaking, I’d like to say some of them took inspiration from what they learned in class, but no matter how they ended up there, I’m happy to see people writing code that looks like it comes from Ruby. This is especially encouraging considering that every one of our students came to Ruby after Rails was popularized.

The Event

We wanted “The Compleat Rubyist” to be not just a training, but an “event” as well. Because we were trying to keep registration costs low, we didn’t have much officially scheduled for this, but Tampa.rb really helped us pull through. Folks congregated at the nearby bar and restaurant Bahama Breeze from the time class ended until late into the evening Friday night. It was nice to have a mixture of students from the training and locals who just stopped by to hang out and say hi. I can honestly say that the sort of conversations I was having that night were on par with any I’ve had at the various conferences I’ve been at, but without all the associated commotion.

Pizza lunch on Saturday was a great way for us to leave a large chunk of semi-unscheduled time to discuss whatever topics students had on their mind. With a relatively small class size, I was able to get to know a number of the attendees, unlike my experience at most conferences these days.

While I expected to have a good time, I ended up having a blast. Based on my discussions with Jeremy and David, and the feedback from our students, I gather most others did as well.

The Future

While the Tampa, FL Compleat Rubyist event is now a thing of the past, we’re already thinking about how we can bring this session to other places. I was a little worried before the event that I wouldn’t want to just go somewhere else and do the same show, but now I know that every one of these is going to be different, since so much of the content was based on interaction with our attendees.

So, if the stuff I’ve said here interests you, you should follow compleatrubyist on twitter. We used our account actively during the event to share various little tips, and probably will continue to do that over time. But that’s also the place where you’ll see announcements about upcoming events, or ask us any questions you might have.

While I don’t typically like to use this blog for active marketing, I can honestly say that “The Compleat Rubyist” was a lot of fun, and that I think our students learned a ton. If folks like these summaries, I’ll try to get one out after each event. But it will be more fun, of course, if you come join us!

back to top
Posted 8 months ago at A Fresh Cup

It was a busy weekend - apparently for other people as well as for me.

back to top
Posted 8 months ago at The GitHub Blog

Rebase: good for reorganizing commits, squashing down changesets, and repairing dentures.

Featured Project

vanity is an experiment driven development framework for Ruby on Rails that uses A/B Testing to maximize how people interact with your site. The simple case is testing out switching out two different page layouts to see which drives more signups. Set up and track metrics such as referrals or acquisitions, and then check it out in the built in dashboard using Redis. It’s also quite easy to extend and bring in other services, such as Google Analytics. Get started split testing your app here.

Notably New Projects

ptex is a high-quality, production ready texture-mapping system created by Walt Disney Animation Studios. This C++ library has just recently been released here on GitHub, after being used extensively in BOLT and integrated into Pixar’s RenderMan. There’s plenty of documentation about the file formats, API, and papers on the new texture mapping procedures used in the library on the project’s website. You can also see ptex in action with a high-resolution model of a T-Rex here on YouTube or check out some sample projects.

couch-crawler is a search engine that’s built on top of CouchDB and uses couch-lucene to index data. Created in an experiment to index work intranet pages, the neat part about this project is that there’s no web tier between the browser and CouchDB. Couch serves up static HTML/CSS, and AJAX calls hit Couch directly and then the UI is built up with the help of mustache.js. The spider uses Python along with httplib2 and Beautiful Soup to extract data. I’d love to see this apply to more than just corporate intranets, because knocking out a whole layer of glue code is a really neat idea.

gitcharts is a small C# app that generates a graph for lines of code in a given git repository over time, and supports multiple projects in one repository. This would be really cool to see applied as a service built on top of GitHub API …hint hint!

base64ize is a small JavaScript-based site that applies base64 to any file you drag onto it, courtesy of some new APIs in Firefox 3.6. This is just a fun hack, but definitely worth a bookmark if you’re doing this often to images or data while testing. Also, the author’s blog post shows off a part of the Mozilla developer world I haven’t seen before: hacks.mozilla.org. If you’re interested in the bleeding edge of Firefox development, keep an eye on that site to see some of the recent developments coming out from that community.

Open-Quark is a framework for functional programming that’s heavily inspired by Haskell, built on top of the JVM, and was just recently pushed to GitHub. Its Wikipedia article describes the framework’s underlying language, CAL, as “a strongly typed, lazily evaluated functional language, supporting algebraic functions and data types with parametric polymorphism and type inferencing”. Code samples of the language and how it interops with the JVM are available, along with plenty of resources and videos to get started using it with your applications.

back to top
Posted 8 months ago at Railscasts

Use checkboxes to edit multiple records in one form, where each one has an individual set of form fields.

back to top
Favorite
Posted 8 months ago at Ruby Quicktips

With Date.civil(y, m, d) (or its alias .new(y, m, d)), you can create a new Date object. The values for day (d) and month (m) can be negative in which case they count backwards from the end of the year and the end of the month respectively.

>> Date.civil(2010, 02, -1)
=> Sun, 28 Feb 2010
>> Date.civil(2010, -1, -5)
=> Mon, 27 Dec 2010

See the documentation on civil method.

back to top
Posted 8 months ago at lindsaar.net - a different view

The past month has seen a flurry in activity on the Mail gem but I just pushed 2.0.3 to GemCutter, it is quite a release!

If you haven’t heard of mail, you can get some background here, here, here and here

Mail is a very Ruby way to handle emails.

Version 2.0.3 is the first gem release I have in the last couple of weeks, this is because I went through and (in good BDD style) refactored major parts of the Mail gem so it handles better.

Some of the major things were:

SMTP Delivery Agent revamped

I went through the SMTP delivery agent and cleaned it up, also adding examples for how you use Mail with GMail and MobileMe so there is no more guess work here.

Delivery agents are now instance based

This means that each mail object that you instantiate can have its own delivery method. Why is this important?

Well, say you are writing a web based email client for multiple users, but each user has their own SMTP hosts, when you make a mail object for that user, you could assign the delivery method for that user to that mail object, then delivery is just calling .deliver! on the mail object, and away it goes.

There is still default class wide settings for all the major delivery agents (SMTP, Sendmail and File) however, you can now over ride these.

mail1 = Mail.new
mail1.delivery_method #=> #<Mail::SMTP:0x101381c18 @setting
mail2 = Mail.new
mail2.delivery_method :sendmail
mail2.delivery_method #=> #<Mail::Sendmail:0x101381c18 @setting
mail1.delivery_method #=> #<Mail::SMTP:0x101381c18 @setting

Attachments are now just parts

Before, an Attachment had its own object type in Mail. This was nice and all, but was just added cruft that got in there during the BDD cycle. I ripped out the entire attachment class, and an attachment is now just a plain old Mail::Part. This makes the code simpler, which is good for everyone.

Mail also now has a very cool attachments API:

mail = Mail.new
mail.attachments #=> []
mail.attachments['filename.jpg'] = File.read('filename.jpg')
mail.attachments['file.pdf'] = {:content_type => 'application/x-pdf',
                                :content => File.read('file')
mail.attachments.length #=> 2
mail.attachments[0].filename #=> 'filename.jpg'
mail.attachments['filename.jpg'] #=> <# Mail::Part, filename = 'filename.jpg' ...>

Yes, that is an ArrayHashThingy™ class, and, it rocks :) It is actually an AttachmentsList object that inherits from Array and implements a custom [] class.

Thanks to David and Yehuda who were brainstorming on the new ActionMailer 3.0 API with me, which I used for inspiration for this implementation. (more on the ActionMailer 3.0 API that I am pair programming with José later :)

Mail returns default values for fields, that can be modified

Mail returns an array of address specs when you call mail.to and would re-initialize that array with new values when you called mail.to=.

However, this array object was just a result of a method, it was not a representation of the addresses within the address field, so then doing mail.to << value would seem to work (no error) but the address would get lost, for example:

# Old (unintuitive method)
mail = Mail.new("To: mikel@test.lindsaar.net")
mail.to #=> ['mikel@test.lindsaar.net']
mail.to << 'ada@test.lindsaar.net'
mail.to #=> ['mikel@test.lindsaar.net']

This now works on all Address fields that can take more than one address, so

# New (intuitive) method
mail = Mail.new("To: mikel@test.lindsaar.net")
mail.to #=> ['mikel@test.lindsaar.net']
mail.to << 'ada@test.lindsaar.net'
mail.to #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']

Thanks to Sam for suggesting this feature.

Access returned to the Address objects

When you call mail.to you get a list of address spec strings (‘mikel@test.lindsaar.net’ for example), but it will not give you the display name, or formatted address etc.

To handle this, you can now call mail[:to] to get the actual ToField object, and then you can call #display_names, #formatted, and #addrs, the last of which will give you the actual Address objects in an array (the original behaviour of Mail), like so:

mail = Mail.new("To: Mikel Lindsaar <mikel@test.lindsaar.net>")
mail.to #=> ['mikel@test.lindsaar.net']
to = mail[:to]  #=> #<Mail::Field:0x10137c718...
to.addrs #=> [#<Mail::Address:2165620900 Address: |mikel@test.lindsaar.net| >]
to.addrs.each do |addr|
  puts "Formatted: #{addr.format}"
  puts "Display:   #{addr.display_name}"
  puts "Address:   #{addr.address}"
end
# Produces:
Formatted: Mikel Lindsaar <mikel@test.lindsaar.net>
Display:   Mikel Lindsaar
Address:   mikel@test.lindsaar.net
=> [#<Mail::Address:2165518560 Address: |Mikel Lindsaar <mikel@test.lindsaar.net>| >]

Thanks to Karl for suggesting this would be handy :)

More methods added to address fields

You can also access an array of the formatted, display_names or addresses directly from address fields:

mail = Mail.new("To: Mikel Lindsaar <mikel@test.lindsaar.net>")
mail[:to].addresses   
#=> ["mikel@test.lindsaar.net"]
mail[:to].formatted
#=> ["Mikel Lindsaar <mikel@test.lindsaar.net>"]
mail[:to].display_names
#=> ["Mikel Lindsaar"]

Remaining Stuff

There are a lot of other small bug fixes, parts now get sorted recursively on encode, body objects will accept an array of strings and call join on them, and many other small things that are in the commit and change logs. Check it out.

As always, tickets (and patches) are always welcome, I use GitHub’s Tracker for this. Or you can talk to us on the Mail Google Group

Happy Mailing!

blogLater

Mikel

back to top