TDD Example in Rust

Posted on

This is an example of how I worked through the Prime Factors Kata using Test Driven Development in Rust (specifically rustc 1.0.0-dev 928e2e239 2015-03-25). I'm assuming you've read The Rust Programming Language Book through the Testing chapter, so I won't be explaining much of the Rust syntax.

The kata, as I decided to interpret it, is:

Write a function that takes an integer greater than 1 and returns a vector of its prime factors, which are the prime numbers that divide that integer exactly, in ascending order. For example, the prime factors of 12 are 2, 2, 3.

If you'd like to try it yourself without spoilers, here is where you should stop reading and pick up again when you're ready!

If you'd like to see the full code at each step that I describe below, take a look at the commits in this repo. Additionally, the output from cargo test at that commit is in each commit message.

So! I generated a new library using cargo new, then started with a failing test:

fn prime_factors_of_two() {
    assert_eq!(prime_factors(2), [2]);

And, if I run cargo test, it fails to compile:

$ cargo test
   Compiling prime_factors v0.0.1
src/ 3:29 error: unresolved name `prime_factors`
src/     assert_eq!(prime_factors(2), [2]);
<std macros>:1:1: 9:39 note: in expansion of assert_eq!
src/ 3:39 note: expansion site
error: aborting due to previous error
Build failed, waiting for other jobs to finish...
Could not compile `prime_factors`.

In my mind, TDD in Rust has two "red" states-- failing to compile and failing tests. I'm in the first kind right now. I don't necessarily hit both states every time, nor do they always happen in the same order. I feel like I've even stopped distinguishing the two in my mind-- it doesn't really matter whether it's the compiler or the tests that are helping me make my code better. The next step is the same: read the first problem and do the simplest thing you can do to respond to that problem.

The first message here is "error: unresolved name prime_factors", and the simplest thing I can do is define that function without any arguments and with the unit type return value:

fn prime_factors() {

I also decided to add the attribute to override the dead code lint check since I'm not going to have any non-test code calling this function. Silencing that warning will make the test output clearer. So now I get:

src/ 7:32 error: this function takes 0 parameters but 1
parameter was supplied [E0061]
src/     assert_eq!(prime_factors(2), [2]);

Easy enough, I do indeed want the function to take 1 integer parameter:

fn prime_factors(num: i64) {

And now I get a warning and a different error:

src/ 2:21 warning: unused variable: `num`,
src/ fn prime_factors(num: i64) {
<std macros>:5:24: 5:35 error: mismatched types:
 expected `()`,
    found `[_; 1]`
(expected (),
    found array of 1 elements) [E0308]
<std macros>:5 if ! ( ( * left_val == * right_val ) && ( * right_val ==
* left_val ) ) {
<std macros>:1:1: 9:39 note: in expansion of assert_eq!

I'm going to let this warning continue to happen for now because I should be using this variable eventually, but I'm not going to address it this step. I'm more concerned with the first error that says in the test, the things I'm trying to assert are equal aren't the same type. One, the left side, is the unit type, and the right side is an array of one element.

So I'm going to fix this error first by just specifying the return type:

fn prime_factors(num: i64) -> Vec<i64> {

which gets me:

src/ 2:2 error: not all control paths return a value [E0269]
src/ fn prime_factors(num: i64) -> Vec<i64> {

"Not all"? Try "none", rustc ;) Anyway, let's get this compiling and the test passing with the simplest implementation:

fn prime_factors(num: i64) -> Vec<i64> {

And I'm green! Woo! There isn't anything to refactor here, so onto another failing test:

fn prime_factors_of_three() {
    assert_eq!(prime_factors(3), [3]);

which compiles, but the test fails:

---- prime_factors_of_three stdout ----
    thread 'prime_factors_of_three' panicked at 'assertion failed:
`(left == right) && (right == left)` (left: `[2]`, right: `[3]`)',

Yep, as I expected. So... the next simplest thing to get both these tests to pass is returning the argument as a vector, which should work for any prime number:

fn prime_factors(num: i64) -> Vec<i64> {

This compiles, passes the tests, and gets rid of those warnings about not using num. Onward!

fn prime_factors_of_four() {
    assert_eq!(prime_factors(4), [2, 2]);

Aha, something a bit more interesting since 4 isn't prime. This fails as expected:

---- prime_factors_of_four stdout ----
    thread 'prime_factors_of_four' panicked at 'assertion failed:
`(left == right) && (right == left)` (left: `[4]`, right: `[2, 2]`)',

I decided to go with a recursive solution here, but I didn't really like it at this point. It also took me a while to get the syntax for "return the combination of two vectors as a new vector without any variables" to work right, but it turns out + with a reference to another vec works the way I want:

fn prime_factors(num: i64) -> Vec<i64> {
    if num % 2 == 0 && num > 2 {
        vec![2] + &prime_factors(num / 2)
    } else {

There's a lot of conditionals and a lot of "2"s duplicated around. I could have refactored some of those at this point, but I didn't. This is where experience and judgement calls come in... I knew this wasn't the general solution, and I knew I didn't really like my implementation anyway. Thus, I knew there was going to be a lot of change coming up, and refactoring at this point would potentially do more harm than good and just have to be undone later. But don't let this become an excuse to not refactor!

If you look at the repo, you'll see I went ahead and added tests for 5, 6, 7, and 8 that all passed without changing the code. In Uncle Bob's solution, he skips 5 and 7, ostensibly because he is confident enough in his coverage of prime numbers with tests for 2 and 3 that tests for more primes are no longer interesting. Again, judgement call. It's also totally ok to write a whole bunch of tests while you're test driving, but once you understand the domain better, you delete some tests that are covering the same cases before finishing so that you have fewer to wait for to run and fewer that will all break at once if something changes.

And actually, before I ran my test for 6 for the first time, I expected it to fail since 6 isn't made up of only factors of 2, but my solution was more general than I thought it was!

But 9 is the next interesting test case that fails because it isn't prime and 2 is not any of its prime factors:

---- prime_factors_of_nine stdout ----
    thread 'prime_factors_of_nine' panicked at 'assertion failed:
`(left == right) && (right == left)` (left: `[9]`, right: `[3, 3]`)',

So. Because I was feeling a little meh about the recursive solution, I decided to switch to an iterative approach. This means I made 3 things mutable: the argument, a vector to hold the result, and a temporary variable that iterates over potential factors. Now, Rust tries to discourage you from making things mutable by making all variables immutable by default, but that doesn't mean it's bad or wrong necessarily. It's just a bit wordier.

fn prime_factors(mut num: i64) -> Vec<i64> {
    let mut result = vec![];
    while num != 1 {
        let mut i = 2;
        while i <= num {
            if num % i == 0 {
                num = num / i;
            } else {
                i += 1;

Now I'm starting to feel like I have a general solution. 9 passes; in the repo you'll see I added two more tests-- one for a larger prime (101 => [101]) and one for a larger non-prime (48 => [2, 2, 2, 2, 3]). Again, these aren't really necessary since they aren't covering any cases that aren't already covered (and they do pass right away). But in this case, they don't add much time to the test run and they could have caught problems that might not show up with smaller numbers. It all depends.

Refactoring time! I wanted to see if I could get rid of the mutable i variable by switching the while loop to be a for loop over a range, since that's all it's doing anyway.

fn prime_factors(mut num: i64) -> Vec<i64> {
    let mut result = vec![];
    while num != 1 {
        for i in 2..num + 1 {
            if num % i == 0 {
                num = num / i;

Still passes tests, looks a little better. I still wasn't happy about it though, since I read in Uncle Bob's description that he was able to solve the kata in 3 lines of code. I couldn't spot anything I could change, so at this point I gave up and looked at his solutions in his slides. Now, he did it in Java and his solution was:

for (int candidate = 2; n > 1; candidate++)
    for (; n%candidate == 0; n/=candidate)

And now it makes sense. This feels a bit too clever, though, with the for loop conditions not matching the iterator index. It's neat code golf though. I couldn't get it down quite this small since Rust doesn't have this for loop syntax, but this is probably the closest translation and is better than what I ended up with in that it's not going back out to the outer loop if we can continue to divide by the candidate factor over and over:

let mut result = vec![];
let mut i = 2;
while num > 1 {
    while num % i == 0 {
        num /= i;
    i += 1;

But is this the most idiomatic Rust solution? It didn't really feel like it, with all those muts still in there. So at this point I decided to give the recursive solution a try again:

fn prime_factors(num: i64) -> Vec<i64> {
    for i in 2..num {
        if num % i == 0 {
            return vec![i] + &prime_factors(num / i)
        i += 1;

This feels better to me, after having explored the iterative solutions. What do you think? Again, there's no one right answer :)

I've been meaning to learn how to, and write a post on, how to benchmark Rust and analyze the runtime and memory usage, perhaps I'll use these different implementations as material for that :)

Dev URLs without Pow

Posted on

TL;DR: I had to do a bunch of research in order to set up pretty URLs to apps running on my localhost at a particular port, so I decided to write up the steps I followed in one place in case anyone else wants to do this. Scroll down past the reasons I wanted to do this for the instructions.

I recently decided to use a non-admin user with OSX Yosemite on a daily basis, mostly on the recommendation of a security researcher who discovered a vulnerability in OSX, and because it sounds like a good idea in general.

The only problem I've encountered so far is in installing Pow-- the script to install it wants sudo, but it also wants to be run as the current user. There are instructions on the wiki for installation as a standard user, but they appear to be out of date; I got errors when trying to use npm run-script. I also got errors when trying to install it from source. So ¯\_(ツ)_/¯.

The thing is, I was only using Pow for its pretty URL creation anyway; I use foreman or grunt to run my apps instead of Pow's rack server. So I set out to get URLs like to serve up a rails app that I would usually access at http://localhost:3000.

My first thought was that I could just use /etc/hosts, but that only works for host names, not host names and ports. Luckily, Apache can do this and, conveniently enough, is included with OSX!

BUT WAIT! I do still need to use /etc/hosts, so that the host goes to localhost where Apache will handle it.


So, to spell it all out, I logged in as my admin user (since I'm running from a non-admin day-to-day now) and edited /etc/hosts using sudo:

$ login admin
admin$ sudo vim /etc/hosts

In order to add a new entry for So now, my /etc/hosts file looks like:

# Host Database
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##   localhost broadcasthost
::1             localhost

At this point, still as the admin user, I started up apache by doing:

admin$ sudo apachectl start

And then I could go to and see the Apache "It works!" page. We're halfway there!

Now, edit /etc/apache2/httpd.conf, find this part about Virtual Hosts and uncomment the Include line so it looks like this:

# Virtual hosts
Include /private/etc/apache2/extra/httpd-vhosts.conf

Then, edit THAT file, /private/etc/apache2/extra/httpd-vhosts.conf, remove the two sample <VirtualHost>s, and insert a new one that looks like this, as recommended by this ServerFault answer:

NameVirtualHost *:80

<VirtualHost *>
    ProxyPreserveHost On

    # setup the proxy
    <Proxy *>
        Order allow,deny
        Allow from all
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/

Then restart apache:

admin$ sudo apachectl restart

And, if you've got your app running at port 3000, you should be able to visit in your browser and get to your app!

Ruby, Rust, and Concurrency

Posted on

I mostly do Ruby these days, but I've just recently started getting into Rust. I'm finding it super interesting! It's definitely expanding the way I think about programming, and I'm excited about the future it's foreshadowing.

I'm a visual and experiental learner though, so when I see statements like "Race conditions Data races are compile-time errors" (thank you for the clarification, dbaupp :)) I wonder what that looks like in the code, what kind of error message you get, and how that differs from what I know in Ruby.

So I went out hunting for a trivial race condition in Ruby that I could port to Rust to see what would happen. Stack overflow to the rescue! Here's a slightly modified version of the Ruby code in that post that suited my purposes better. Note that this is totally contrived and you would never actually want to have a bunch of threads help you increment a number from 1 to 500:

COUNT   = 50

$x = 1 { |t| {
    COUNT.times { |c|
      a  = $x + 1
      sleep 0.000001
      puts "Thread #{t} wrote #{a}"
      $x =  a

if $x != THREADS * COUNT + 1
  puts "Got $x = #{$x}."
  puts "Expected to get #{THREADS * COUNT + 1}."
  puts "Did not reproduce the issue."

This causes a race condition most of the time that I run it in Ruby 2.0-- I've got a global variable that the threads read, then they sleep, then they increment, and in the time that one thread sleeps, another thread reads and/or writes that global. Stuff happens all out of order. Here's parts of the output from one of the times I ran it:

Thread 0 wrote 2
Thread 0 wrote 3
Thread 1 wrote 78
Thread 3 wrote 29
Thread 3 wrote 59
Thread 4 wrote 29
Thread 4 wrote 78
Thread 3 wrote 60
Thread 0 wrote 50
Thread 0 wrote 51
Got $x = 51.
Expected to get 501

So what would it look like if I tried to do this in Rust, as faithfully as possible to the contrived example? Here's my attempt, critiques welcome:

use std::io::timer::sleep;

fn main() {
  let threads = 10;
  let count   = 50;

  let mut x = 1u;
  for num in range(0u, threads) {
    spawn(proc() {
      for num in range(0u, count) {
        let a = x + 1;
        x = a; // error: cannot assign to immutable
               // captured outer variable in a proc `x`

  println!("The result is {}", x);

Sure enough, if I try to compile this with rust 0.11.0, I get a compile error! Cool! I've marked its location and text with a comment. This error says that the compiler captures x and makes it immutable while in the proc. I can write to it all I want in main where it's declared as mutable, but because I could create race conditions if I was allowed to write to it in a spawned thread, Rust doesn't let me do that.

I tried to make a version of this program in Rust done The Right Way that would compile and run, but a lot of what I'm seeing is basically saying "don't do that" to me (and this is a super contrived example). I tried a little bit with mutexes, a little with futures, but they ended up changing the logic happening so that one thread was locking the value for its whole existence, then the next thread would lock it, etc. I never got it to compile, run, and illustrate everything I wanted it to, so I'm leaving that as an exercise for the reader :) This experiment in fork/join parallelism in Rust looks relevant to my interests but I haven't digested it all yet.

Hope this helps someone else to understand the different choices that Ruby and Rust make in this area! I'd love to hear what you think, how I could make this example better, or how you'd implement this example to compile and run in Rust :) <3

On Stack Overflow

Posted on

On Dec 24, 2013, Michael Richter wrote a post about why he no longer contributes to Stack Overflow. I don't feel the same way as he does, but it made me do a lot of thinking and, eventually, a lot of writing. I left these thoughts as a comment on his post but I decided to make my own post as well. Here they are, slightly modified from their comment form to make a bit more sense standing on their own.

Background: I've got a little over 3k in Stack Overflow points currently and I mostly read, ask, and answer questions in the [ruby] and [ruby-on-rails] topic tags.

The reason I think Michael's post hit me so hard is that in the community organizing stuff I do, I've been trying to be very deliberate about making welcoming environments for everyone. So if there are people who don't feel that Stack Overflow is a welcoming environment, I'm interested in seeing what we can do to change that, and possibly extrapolating the results to my other communities too.

Michael mentions that answers written hastily after a quick google search often get more points than answers that took a long time to write. He also notes that he's earned thousands of points while being inactive. I agree that SO doesn't directly incentivize thoughtful answers to complex questions. To me, though, it's much more about whether I helped someone or not (as Jay Hanlon mentioned in the comments). I enjoy knowing that some content I put on the internet a few years ago is still helping someone today. I would hate to lose that feedback, but I agree it doesn't necessarily make sense to tie so much information to the one reputation number. Perhaps privileges should be separated more from votes, but I don't know what would be a better fuzzy metric for "this person knows about these topics and cares about the quality of the content".

The other useful thing about votes on answers is to indicate which answers are better than others, both from the point of view of the original asker and from the point of view of future searchers with the same question. I wonder if this could be fixed with, instead of showing the raw count of upvotes per answer, showing a percentage of votes a particular answer got out of all the votes cast on the answers for that question. This would be a pretty radical change for SO though...

Michael also noticed that, after he posted a controversial answer, people were downvoting all of his answers. I'm not sure when this was implemented, but Stack Exchange actually has detection for serial voting (both up and down) in place and I've seen the system automatically reverse some serial downvoting of my answers within 24 hours.

Michael has been feeling a creeping authoritarianism in the culture of Stack Overflow lately. I agree that the culture of SO has changed, but I don't remember exactly when, why, or how it happened (my SO activity has waxed and waned a few times). Today, I would probably vote to close some of the questions I asked a few years ago, but as far as I know they were within the site guidelines for good questions at the time. I'm a little confused when putting this section together with the poor pedagogy section though-- many of the situations you cite there of people not attempting to solve their own problems first are handled by moderating them as duplicates, needing more information about what the asker has tried and why that didn't work, etc. Which would be more authoritarianism, but this section seems like you'd prefer less. I'm just not sure if it's possible to go back to the way SO used to be now that it's at this scale.

I definitely think SO could use improvement in the experience of a new user. As pointed out by the commenter Mike and others, not being able to comment unless you've gotten 50 points is incredibly frustrating and off-putting, and I've seen it cause poor content to be created (answers that start with "I can't comment on X but..."). Yet another case where reputation is being used for multiple purposes-- in this case I think mostly to prevent spam and sock puppets.

It's also really hard to explain what makes a question high quality for this format and guide a new user towards providing the information that will help them get the information they're looking for fastest. The current process of closing questions, even with the close reasons given to the asker as feedback, does feel very authoritarian and unwelcoming. This would require much more effort, but perhaps instead of closing, they could be put in a "mentoring" queue that has more affordances for back-and-forth discussion than the main Q&A format. Maybe that's what chat is for and more questions need to be moved there? I don't really use chat much.

One final comment I'd like to make is that it's really tough to paint "the SO community" with one brush, given the number of users and breadth of subtopics. As prolific as he is, I actually rarely see any answers from Jon Skeet because I don't do any C# and he doesn't do any Ruby. There are definitely subcultures in SO (although I'd be hard pressed to define them). I suppose my point here is that I'm not convinced that the structure of SO is entirely responsible for the "community" aspect since the same structure has enabled different cultures to exist (although it's definitely a large factor).

Michael, thank you again for sharing your thoughts-- I appreciate by your "poor community counter" that this isn't easy.

And we're back

Posted on

Sigh. My wordpress blog apparently got hacked, my host shut it down, so I've spent the last few days converting this blog to a Jekyll site hosted on github pages. I really can't recommend wordpress to anyone anymore, given the massive botnets that are attacking every wordpress site out there right now. For non-technical folks or lazy technical people who don't want to have to spend time keeping up with updates or fighting off attacks, it's just not a viable solution.

So here we are. I still have a lot of work to do... the links between posts are all broken, I had some google juice on some of the posts at least, so it'd be nice if links to my old posts still redirected. I haven't decided whether to add commenting via disqus or similar-- I like hearing that my posts have helped people, but do I really need them? They're really just another avenue for spam. I'm also not wild about this theme, it's nice enough, but it's just not really me (but I also don't have the time/talent to make something I like better).

Oh, and it's a good thing I'm not very prolific because I ended up converting my posts by hand. I had a sql dump file, not a wordpress xml export, and apparently the jekyll-import gem only supports connecting to a database or importing from the wp xml file. And I had enough problems just getting the jekyll import process to tell me that that I didn't exactly have much confidence that the import process was going to go well anyway.

Technology sucks. Everything's broken.

Wordpress 3.5.1 multisite subdirectory problem

Posted on

I recently created a new wordpress 3.5.1 install with the intention of enabling multisite. I followed all the official instructions and everything seemed to be working until I got to actually creating a second site in the network with a subdirectory.

I created the site (ex: named 'blah'), but when I tried to go to or, it was like I was looking at the main site in the network.

I tried many different recommended .htaccess variations, checked every gotcha that official wordpress documentation, the wordpress stackexchange, and other wordpress blogs mentioned, to no avail.

Finally it took some help from my life pair Jake Goulding to spot that in the site info for the subsite, I had '/blah' for the path setting, and since the main site had '/' as the path, perhaps it should be '/blah/'.

Adding the trailing slash in the path for the site allowed wordpress to recognize it and going to immediately started working.

I admittedly am not very experienced with wordpress, so perhaps this is something everyone else was able to figure out, especially since I didn't see anyone else recommending that you check this.

But I found the help text in the Add a Site form to be misleading:

It says "Only lowercase letters (a-z) and numbers are allowed." To me, that says "You should not enter a trailing slash", when in fact the behavior I see is that you MUST enter a trailing slash. Either the help text should be changed or, even better, this should work whether you enter a trailing slash or not.

Enable SSL with Heroku for https access

Posted on

For, we've been meaning to enable ssl/https for a long time. I'm pleased to announce that we've finally gotten around to it, and everything seems to be working now!

What was the hold up? On heroku (where we started hosting, then we weren't, now we are again), it used to cost $100/mo for the ssl hostname addon. I love, but not that much. Recently, however, heroku came out with the SSL Endpoint addon which is only $20/mo. This is much more within my budget :)

I also wanted to make sure that the Certificate Authority we went with was in line with' values. This is a project that started on the values of openness and simplicity, so I agonized a bit over our choice of CA. We ended up going with a free certificate from StartSSL for the reasons I mentioned in that thread.

Once you have a certificate, the instructions for the SSL Endpoint are pretty good. There are a few places that I either had issues with or think could use some further clarification:

Intermediate certs

In the SSL endpoint docs, there's a part that says "If you have uploaded a certificate that was signed by a root authority but you get the message that it is not trusted, then something is wrong with the certificate. For example, it may be missing intermediary certificates." This doesn't say what you need to do to add the intermediary certificates that you may be missing.

Some certificate authorities will have intermediate certificates that have to be included in your .crt file. The "Purchasing an SSL Certificate" heroku docs explain how to cat your certificate with a root certificate. If you have an intermediate certificate file as well, first cat your certificate as they show in the instructions, then cat the intermediate certificate, then cat the root certificate. I figured this out by trying it and it worked, but I felt unsure since the docs from heroku and the CA didn't explicitly say what order they should go in.

Add vs Edit CNAME

This may be obvious to everyone but me, but I thought I'd mention it anyway in case someone else has the same brain fart I did. The SSL endpoint docs say "Next, add a CNAME record in the DNS configuration that points from the domain name that will host secure traffic e.g. to the SSL endpoint hostname, e.g."

So I did exactly that-- added a CNAME record. But we already HAD a CNAME record for since we had already followed the heroku custom domains instructions. And CNAMES aren't additive, hah. So yeah, if you already have a CNAME for the domain name you're trying to enable ssl with, just edit that one.

Naked domain

This is the part I struggled with for a week. I got SSL all working for according to the SSL endpoint docs-- worked great! I also had a 301 URL Redirect set up in our DNS records with NameCheap to redirect the naked domain to www. This may be unpopular, but naked domains can't be CNAMES and using A records for the naked domain is highly discouraged for availability reasons (see the naked domain section).

However, 301 redirects don't care about the protocol-- if you go to, it redirects you to, and if you go to it (supposedly) redirects you to What I was seeing, though, if you went to, was that the SSL handshake would just hang. This was very visible when doing a curl -v on the command line-- it would just get to the SSL handshake and wait forever.

The certificate was good for both and, so that wasn't the problem. It looks like an ordering issue to me (correct me if I'm wrong)-- request, do the SSL handshake since it's SSL, and THEN do whatever the DNS says to do-- but the CNAME with www that makes SSL work is AFTER the 301 redirect specified in the DNS settings for the naked domain.

Heroku's documented solution to this is "only circulating and publicizing the subdomain format of your secure URL." It is left as an exercise for the reader to determine why this is an unacceptable solution.

Not mentioned in that page, but linked in its references, is a blog post by DNSimple introducing ALIAS records. This is something that, as far as I can tell, only DNSimple has implemented, and it basically turns a CNAME into an A record behind the scenes without any need for user intervention should the IP addresses that the CNAME resolves to change.

This StackOverflow question confirmed that the DNSimple ALIAS record would solve the problem I was having-- so I set up a DNSimple account ($3/mo for up to 10 domains at the moment, but use my referral link and we both get a month free!), set up the following records:


and changed the settings with NameCheap, where we have registered, to use DNSimple's DNS instead of NameCheap's. Indeed, the ALIAS record magically makes all variations of http/https and naked domain/www work as desired!

Can I have my devops merit badge now?

Interesting Times

Posted on

So today I put in my 2 weeks' notice at Careerimp-- for a variety of reasons that I'm not going to go into publicly, I no longer think the position is the right thing for me at this point in my career.

So what is the right thing? I don't know yet :D I feel very lucky to be in a position where I can afford to take a few months off, and I feel lucky to be fairly certain that I have several options open to me.

In my first month, my main goals are:

  • Put some focused work into
  • Work on my house (one of my longest-lasting contributions to this world may very well be making this house able to stand for another hundred years!)
  • Cook new things that use all the fresh vegetables we're getting from a farm share before they go bad
  • Figure out goals for the month after that :D

And of course there's Steel City Ruby! I'll now have the week before the conference to concentrate on making it super awesome, and that I'm definitely excited about :D

Thank you to those of you who have been advising me lately-- you know who you are. <3 You helped make this a lot less scary for me.

Updating gems in rvm's global and default gemsets

Posted on

This is mostly for my own reference; I know I've looked this up before and it's always hard to find, so at least now I'll have one place to look.

If you want to update gems that you have in your default or global gemsets because you see 2 versions of, say, bundler when you do gem list, you can install and uninstall from them by using a command like this (including the parentheses):

(rvm use @global; gem uninstall -x bundler)

Switching global and default as necessary, and uninstall and install, and bundler and rake (the 2 gems I get in this situation with).

UPDATE: Just talked with Michal Papis (@mpapis) in IRC and he recommends using:

rvm @global do gem uninstall -x bundler

which looks much nicer. As an aside, I was having an issue yesterday and Michal fixed it by the time I got into work today! Thank you so much for your help and work on rvm, Michal!!

Sinatra:Base rackup: rubyeventmachine.bundle: [BUG] Segmentation fault ruby 1.8.7

Posted on

I was just saying yesterday that I haven't run into any strange errors lately. I guess I forgot to knock on wood!

Today I started a brand new sinatra app. I haven't written my own sinatra app from scratch before, so I'm copying pieces from some other apps that I have cloned on my machine. Here's what my code looked like:

# Gemfile
source :rubygems

gem 'sinatra'
gem 'thin'
# salmon_test.rb
require 'sinatra'

class SalmonTest < Sinatra::Base
  get "/" do
require './salmon_test'
run SalmonTest

Then I bundled and ended up with this Gemfile.lock:

    daemons (1.1.8)
    eventmachine (0.12.10)
    rack (1.4.1)
    rack-protection (1.2.0)
    sinatra (1.3.2)
      rack (~> 1.3, >= 1.3.6)
      rack-protection (~> 1.2)
      tilt (~> 1.3, >= 1.3.3)
    thin (1.3.1)
      daemons (>= 1.0.9)
      eventmachine (>= 0.12.6)
      rack (>= 1.0.0)
    tilt (1.3.3)



Also note that I'm using rvm with ruby 1.9.2-p290 and a brand new gemset for this project.

When I ran rackup to start the server, I got this error message:

$ rackup
~/.rvm/gems/ruby-1.9.2-p290@salmon_test/gems/eventmachine-0.12.10/lib/rubyeventmachine.bundle: [BUG] Segmentation fault
ruby 1.8.7 (2010-01-10 patchlevel 249) [universal-darwin10.0]

Abort trap

Why is it doing something with 1.8.7??? Who knows! Right after that I did an rvm list:

$ rvm list

rvm rubies

   ruby-1.8.7-p358 [ i686 ]
=* ruby-1.9.2-p290 [ x86_64 ]
   ruby-1.9.2-p318 [ x86_64 ]
   ruby-1.9.3-p125 [ x86_64 ]

Yep, using 1.9.2...

The one thing I changed in the code before running rackup again was in salmon_test.rb:

- require 'sinatra'
+ require 'sinatra/base'

Then the next time I ran rackup everything worked fine. shrug Hope this helps someone else.

← Newer Page 1 of 3