Chris Schmitz

Pimp Your Chrome Dev Tools With Custom Stylesheets

Did you know that Chrome gives you a stylesheet you can use to customize the look of your dev tools? I didn’t either until I looked over at my buddy Zach’s screen and saw him rockin’ a dark color scheme in his dev tools when we were working at a coffee shop a couple weeks ago.

He informed me that you can put custom styles in ~/Library/Application\ Support/Google/Chrome/Default/User\ StyleSheets/Custom.css and these will override the default dev tool styles. Obviously, I spent the next couple hours looking for the perfect color scheme and I finally settled on this Readable Theme. To install it you just drop the theme’s Custom.css over Chrome’s. The theme even has some SCSS you can pull down and tweak to configure the scheme to your liking if you don’t like some of the defaults.

Develop Faster With iTerm Profiles and Window Arrangements

My friend, Jon Kinney, was showing me how he’s able to jump into dev mode with his server, Rails console, database console, test suite and Vim all running at once using tmux and the tmuxinator gem. I was obviously jelly and I wanted to find a way to do something similar, but since I don’t really use terminal Vim for regular development I thought tmux was overkill for just starting up my server, consoles and tests so I decided to find a way to be more productive in iTerm 2.

Using split panes, profiles and window arrangments we can create a workspace that has everything we need to be productive and we can launch it with a single click. Here’s a preview of the kind of thing you can do:

Above we have a regular terminal session, Rails console, database console and server running in 4 different panes.

Getting Started With Laravel 4

With the release of Laravel 4 just around the corner a lot of people are trying to decide whether to start a new project with a stable 3.2 build or wait for the new version. I found myself in that position earlier this week so I decided to pull down Laravel 4 and work off that since I figured the transition would be smoother once a stable version 4 is released.

There isn’t really any documentation on how to get started with Laravel 4, and if you aren’t familiar with Composer, you might not know where to begin. That’s why I’m writing this. If you want to get started with Laravel 4 today, here’s how.

Extending ActiveModel via ActiveSupport::Concern

In a project I’ve been working on we have some functionality that is shared across multiple models – assigning a default record on a has_many association. Obviously we didn’t want to duplicate the methods in each model, so we explored our options for sharing the logic. We figure we could:

  1. Setup a HasDefault base class that we could extend our models from (i.e. class CreditCard < HasDefault)
  2. Extend the functionality of ActiveRecord::Base

Inspired by how has_secure_password is setup, we decided to extend the functionality of ActiveRecord::Base so we could just call a method inside of a model we wanted to expose the default record assignment methods and callbacks to. Here’s what we ended up with:

File: lib/active_model_extensions.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
module HasDefault
  extend ActiveSupport::Concern

  module ClassMethods
    def has_default
      attr_accessible :is_default

      before_create  :set_default_if_none_exists, unless: :is_default?
      before_save    :set_default,                if: :is_default?
      before_destroy :set_fallback_default,       if: :is_default?
    end
  end

  def set_default
    current_default = self.class.first conditions: { user_id: self.user_id, is_default: true }
    current_default.update_column(:is_default, false) if current_default
    self.update_column(:is_default, true) unless self.new_record?
  end

  def set_fallback_default
    if self.is_default?
      fallback = self.class.first conditions: { user_id: self.user_id, is_default: false }
      fallback.update_column(:is_default, true) if fallback
    end
  end

  def set_default_if_none_exists
    current_default = self.class.first conditions: { user_id: self.user_id, is_default: true }
    self.is_default = true unless current_default
  end
end

class ActiveRecord::Base
  include HasDefault
end

This allows us to call has_default in any model to expose the three callback methods for assigning the default record. Now all we need to do to in our model is

1
2
3
class CreditCard < ActiveRecord::Base
    has_default
end

and the default record assignment will be taken care of automatically. This assumes there is an is_default column in the table, but has_secure_password makes similar assumptions so that doesn’t really bother me.

The Breakdown

The big thing here is to make sure we are using ActiveSupport::Concern to extend the core Rails classes. This makes our lives a litter easier by helping us setup our class and instance methods. It takes everything inside the ClassMethods module and makes them available as, you guessed it, class methods. All the other methods in the HasDefault module get turned into instance methods.

From the code above, you can see we setup the has_default class methods

1
2
3
4
5
6
7
8
9
module ClassMethods
  def has_default
    attr_accessible :is_default

    before_create  :set_default_if_none_exists, unless: :is_default?
    before_save    :set_default,                if: :is_default?
    before_destroy :set_fallback_default,       if: :is_default?
  end
end

and then setup the methods used in the callbacks in the HasDefault module.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def set_default
  current_default = self.class.first conditions: { user_id: self.user_id, is_default: true }
  current_default.update_column(:is_default, false) if current_default
  self.update_column(:is_default, true) unless self.new_record?
end

def set_fallback_default
  if self.is_default?
    fallback = self.class.first conditions: { user_id: self.user_id, is_default: false }
    fallback.update_column(:is_default, true) if fallback
  end
end

def set_default_if_none_exists
  current_default = self.class.first conditions: { user_id: self.user_id, is_default: true }
  self.is_default = true unless current_default
end

Note: ActiveSupport::Concern used to support a module called InstanceMethods, but recently changed this to make anything outside of the ClassMethods module an instance method.

The last part of this example includes the HasDefault module in ActiveRecord::Base, which actually adds the module and exposes the has_default method to all classes extending ActiveRecord::Base, in other words, all of your models.

1
2
3
class ActiveRecord::Base
  include HasDefault
end

Why ActiveSupport?

It’s true, there are other ways to extend classes in Ruby, but using ActiveSupport::Concern makes things a little easier and definitely cleaner. It can also handle dependency resolution, which we didn’t need here, but is quite useful.

Further Reading

Code Highlighting and Marked Preview Styles in nvALT

Everyone loves nvALT, but the markdown preview you get out of the box isn’t anything special. Although there are some instructions on customizing the markdown preview in nvALT, he doesn’t go into specifics about where to find new styles or exactly how to import them.

Personally, I like the previews that I get in Marked, another one of Brett Terpstra’s creations. Knowing that the markdown preview styles are stored in a plain CSS file in nvALT, I figured it was the same for Marked.

The first place I looked was in ~/Library/Application Support/Marked, but I only found a Custom CSS folder that stored all of the custom stylesheets I had added. This makes sense since these are user settings. The core styles that aren’t editable by the user came with the application, which is why I checked the package contents of the application next, this is where I found the CSS files.

Note: You can view the package contents by going to the Marked.app file, right-clicking and selecting “Show Package Contents”.

I opened up github.css, copied the entire stylesheet and brought it over to my ~/Library/Application Support/Notational Velocity/custom.css file for nvALT. I restarted the program selected a different note (thanks Brett) and the new styles were live!

Further Customizations

If you look in the ~/Library/Application Support/Notational Velocity directory, you’ll notice that the template for the markdown preview is actually just an HTML file. As you can see, jQuery is being loaded from the Google CDN, so you should be able to import any external JS/CSS you’d like.

1
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script></code>

I haven’t played around with this much yet, but I did setup highlight.js to provide code highlighting. All I had to do was include a JS and CSS file from the download instructions and then call the init method. You can copy and paste the following code right above the `

Work Faster With Basic Shell Commands

Writing your own shell scripts may seem a little intimidating at first, but it’s actually quite simple and can drastically improve your workflow. Any sequence of commands you would run from the command line you can put into a shell script.

For example, when I want to start coding on a project, I usually end up opening my editor from the terminal and a new tab in my browser to view the project. This doesn’t take very long, but since it’s something I do multiple times every day, I figured I should try to automate it.

Let’s Scriptify It

I wanted to be able to pull up my editor and open the new browser tab right from the terminal so I came up with the following script to do just that:

1
2
3
4
# !/bin/sh

open -g 'http://localhost/chris-schmitz.com'
subl .

Breaking this down, here’s what each line does:

  1. # !/bin/sh – Invokes the shell, a standard starting line for a shell script
  2. open -g 'http://localhost/chris-schmitz.com' – Opens the URL for the project in a new tab of my default browser
  3. subl . – Opens the current directory in Sublime Text 2 (using TextMate the command would be mate .)

Now, assuming I saved the file as open.sh, I can run sh open.sh from the command line to open my editor and the browser tab. This was a great next step, but I thought I could do a little better.

A Shortcut for the Shortcut

I love TextExpander and any time I have text that I need to type on a regular basis I make a snippet for it. I figured this shell script is a perfect candidate for that.

I didn’t want to have to create a new file and then use a snippet to insert those three lines, so I use the following snippet to create the file with those three lines all in one step from the terminal.

1
echo "# \!/bin/sh\n\nopen -g 'http://localhost/%fill:site_name%'\nsubl ." >; open.sh

It’s just a one-liner with some escaped characters and line breaks that get inserted into the open.sh file. I set the shortcut for the snippet to qlp, short for Quick Launch Project.

Now I can create these shell scripts with ease, but I still didn’t like having to type sh open.sh all the time. I decided I wanted to make it shorter, so I aliased that to dev with the following command:

1
alias dev='sh open.sh'

Note: I’m using ZSH in my terminal, but I believe this command is the same for Bash.

My New Workflow

Now when I create a new project, all I have to do to get setup is:

  1. cd to the directory
  2. Expand my qlp snippet
  3. Run the dev command, and I’m ready to go

The main takeaway from this shouldn’t be the actual code, but the idea of how easy it is to automate repetitive tasks. A few basic shell commands can go a long way.

If you want to learn more about shell scripting, I highly recommend the Bash Guide for Beginners.

The MacBook Air and Web Development

I migrated to a MacBook Air as my primary development machine a few months ago and I think it is the ideal computer for a web developer. I think it’s the future of personal computing and that everyone should do themselves a favor and pick one up the first chance they get.

There are already some great articles reviewing the specs of the computer and why it is well-suited for web development, but I just wanted to point out a few, hopefully less-obvious, benefits of the machine for others who are considering making the switch.

Pros

There are a lot of things I like about the machine, but here are the big ones.

Focus

I actually enjoy the restrictions of the smaller screen. I no longer need to worry about where I’m going to position windows. They are either full screen or half screen, no more lost time organizing my windows.

As a result of the more minimalistic setup I’ve become accustomed to, I’ve found that I am less tolerant of distractions. Now, I turn off anything that can potentially distract me from the task at hand and I’ve been much more productive as a result.

Efficiency

At first I didn’t like them, but I use spaces all the time now. I can switch back and forth between personal and work space very efficiently.

Speed

I’ve never had a computer with an SSD before, and I completely underestimated how big of a difference this makes. It’s amazing. I’ve found my Air to be much more responsive than the much more powerful computers I was using previously. Like I said, I don’t want to get too technical here, so if you want more details on this stuff, I would check out Apple’s Performance page for more details.

Portability

I really didn’t think I would care too much about the portability of the machine, but now that I have been carrying it with me everywhere for the past few months I don’t think I could ever go back to a MacBook Pro. Even my wife’s 13” MBP feels clunky (and slow) relative to my Air.

One thing a lot of people don’t seem to realize is that the resolution of the Air is actually the same as a 15” MBP. This makes it feel a lot bigger than it is, and it has a Thunderbolt port if you want to hook it up to a larger display.

Cons

None… just kidding, but they are fairly obvious. You’re clearly getting a machine with less screen real estate and a slower processor, but you will not notice the difference unless you are doing a lot of graphics/video editing or 3D modeling.

Conclusion

Computers are typically reviewed on specs, and if you compare the MacBook Air to a more powerful machine, the MacBookAir might look limited, but if you compare it based on the user experience provided by the machine, nothing comes close.

Note: I am a complete Apple fanboy, but I was a Windows user for the majority of my life. I’ve even had a Windows 7 laptop that I worked on for about a year so I am able to make a somewhat fair comparison.

Other Relevant Articles

The CodeIgniter Decorator Library

I’ve been thinking a lot lately about how I can clean up my CodeIgniter code, specifically my controllers and views. CodeIgniter is dead simple to work with, but on larger, more complex projects I find that my controllers get a little long and my views get messy. Here are my main issues and how I’ve decided to address them.

Controllers

The main thing I don’t like doing in my controllers is all of the data retrieval and preparation to pass data to the view. Things like this:

1
2
$product = $this->product_model->find($product_id);
$company = $this->company_model->find($product->company_id);

And this:

1
2
3
4
5
$view_data = array(
    'product' => $product,
    'company' => $company
);
$this->load->view('products/view', '$view_data');

They just don’t feel right to have in the controller because they get in the way of the core function of a controller.

The controller receives user input and initiates a response by making calls on model objects. A controller accepts input from the user and instructs the model and a view port to perform actions based on that input.

Wikipedia

Views

I’ve always disliked putting any sort of logic in my views. In fact, anything beyond looping through an object or array and echoing its values makes me feel dirty. Things like setting a default value if an attribute is empty:

1
<?php echo empty($product->price) ? $product->price : 'N/A'; ?>

Or updating the layout of a page based on the type of user that is viewing it:

1
2
3
4
5
6
7
8
<?php if ($user->company_id == $product->company_id): ?>
    <div class="product-admin-links">
        <?php echo anchor('products/edit/' . $product->id, 'Edit Product Info'); ?>
        <?php echo anchor('products/inventory/' . $product->id, 'Edit Product Inventory'); ?>
    </div>
<?php else: ?>
    <?php echo anchor('cart/add/' . $product->id, 'Add to Cart'); ?>
<?php endif; ?>

Not only does this clutter up my views, but it also has to be repeated anywhere that I want to display information for a resource, in this case a product. I would much prefer to have this data prepared outside of the view and the controller, but it doesn’t really belong in the model either.

My Solution: Decorators

After seeing how a couple other frameworks handle this (FuelPHP and Rails) and thinking through what my ideal solution would be, I’ve started writing a decorator library and created a spark out of it.

The library allows you to put all of the data retrieval and preparation into a decorator, which is stored in application/decorators. A decorator must extend the CI_Deocrator class which gives it access to the CodeIgniter super global ($this) so you can load models and everything else like you are working in a controller or model. Going back to our earlier example, if you removed the data retrieval from the controller and preparation logic form your views, you would end up with something likes this:

File: application/controllers/products.php

1
2
3
4
public function view($product_id)
{
    $this->load->view('products/view', $this->decorator->decorate('product', 'view', $product_id));
}

As opposed to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
public function view($product_id)
{
    $this->load->model('product_model', 'company_model');

    $product = $this->product_model->find($product_id);
    $company = $this->company_model->find($product->id);

    $view_data = array(
        'product' => $product,
        'company' => $company
    );
    $this->load->view('products/view', $view_data);
}

Tip: By default, the decorate() method will look for a class/method that matches the controller class/method, otherwise you can specify them as parameters (i.e. decorate('products', 'view')). It will also accept a third parameter as an array of parameters to pass to the decorator.

Going back at our views, we can now do this:

File: application/views/products/view.php

1
2
<?php echo $product->price; ?>
<?php echo $product_links; ?>

As opposed to this:

1
2
3
4
5
6
7
8
9
<?php echo $product->price ? $product->price : 'N/A'; ?>
<?php if ($user->company_id == $product->company_id): ?>
    <div class="product-admin-links">
        <?php echo anchor('products/edit/' . $product->id, 'Edit Product Info'); ?>
        <?php echo anchor('products/inventory/' . $product->id, 'Edit Product Inventory'); ?>
    </div>
<?php else: ?>
    <?php echo anchor('cart/add/' . $product->id, 'Add to Cart'); ?>
<?php endif; ?>

And our decorator looks like this:

File: application/decorators/products_decorator.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Product_decorator extends CI_Decorator {

    public function view($product_id)
    {
        $this->load->model('product_model', 'company_model');

        $this->view_data->company = $this->company_model->find($product->id);
        $product = $this->product_model->find($product_id);

        if (empty($product->price)) $product->price = 'N/A'

        $this->view_data->product = $product;

        if ($this->session->userdata('company_id') == $product->company_id)
        {
            $product_links = '<div class="product-admin-links">';
            $product_links .= anchor('products/edit/' . $product->id, 'Edit Product Info');
            $product_links .= anchor('products/inventory/' . $product->id, 'Edit Product Inventory');
            $product_links .= '</div>';
        }
        else
        {
            $product_links = anchor('cart/add/' . $product->id, 'Add to Cart');
        }

        $this->view_data->product_links = $product_links;
    }
}

Tip: The class variable, $view_data, that I’m referencing here is a variable that is automatically returned by the decorate() method. Using this, you don’t have to worry about explicitly returning the data, but if you do return something, decorate() will use that instead of the $view_data class variable.

Help Me Out

It’s definitely not perfect, and I certainly make no claims of it being bug-free, but it’s a start and I hope to keep improving it based on the feedback I receive (Hint, hint!). I’ve been using this on a couple of my larger projects the last month or so and it has really helped me clean up my controllers and views. Hopefully others find it useful too.