The Easy Way to Get Started with PostgreSQL on a Mac: Postgres.app and Induction

Here’s how to get started with PostgreSQL in minutes without having to touch the command line. You’ll need two applications to run and manage PostgreSQL, Postgres.app and Induction. Postgres.app is the equivalent of the MySQL server you get with MAMP and Induction is the equivalent to something like Sequel Pro if you are coming from MySQL.

Up and Running

Once you have those two applications downloaded and installed, here’s what you need to do to get your PostgreSQL server running and be able to use Induction as a GUI to manage your databases.

1. Open Postgres.app

This will start the server and if it’s the first time you’ve run the app, it will automatically create a PostgreSQL user and database named after the user you are logged in as on your system.

2. Configure Induction

Open Induction and you’ll see the login screen. Enter the following information:

  • Adapter: Select postgres
  • Hostname: Enter 127.0.0.1 (localhost)
  • Username: You can use the username Postgres.app created for you (the same name as the user for your system)
  • Password: You should be able to leave this blank if you are using the user that Postgres.app created for you
  • Database: As of this writing, it says this is optional, which it should be, but I couldn’t connect without specifying the name of a database. You can use the one Postgres.app created for you (should be the same as the username) or create one by hand with as explained later in this post.

the Induction login screen

That’s it, you should be up and running (told you it was the easy way!), but read on for a couple other tips on working with Postgres.app and Induction.

Note: There are other tools that are more full-featured than Induction, like Navicat, but Induction is the only open source GUI I’ve seen for managing PostgreSQL and it is being developed by Matt Thompson, the creator of Postgres.app, so you can be confident they are going to play nice together.

Setup the Command Line Tools

Lion and Mountain Lion come with an older version of PostgreSQL which includes a psql command line utility for managing your PostgreSQL on your machine. However, Postgres.app comes with its own psql utility as well as a slew of other useful binaries that I’m sure you’ll want to have access to at some point if you continue working with PostgreSQL.

To install these tools, just add Postgres.app’s bin directory to your PATH. You can do this by adding the following line to your shell’s configuration (.bashrc or .zshrc).

PATH="/Applications/Postgres.app/Contents/MacOS/bin:$PATH"

Then open a fresh terminal session and you should be able to run all of the command line tools directly. This will also allow you to run psql on its own, without a host, to login to the console. Try it out and make sure it’s working.

Creating Databases

In the current version of Induction (0.1.0) you can’t create databases from the app (I’m assuming you will be able to at some point) so you still need to do that from the command line using psql. Just connect by running psql, then create a database with the CREATE DATABASE command.

CREATE DATABASE database_name;

You can remove a database by using the DROP DATABASE command:

DROP DATABASE database_name;

If you’re using Rails, you can also use rake db:create to create your database without using psql. Just make sure to configure your database.yml first.

The Future

Postgres.app and Induction are relatively new and look like they are being very actively developed. Keep an eye out for new releases and additional functionality in the near future, especially with Induction since it is still in alpha.

These tools should make getting started with PostgreSQL on a Mac a lot easier and enable a lot of people who rely on GUIs to administer their databases to make the transition from MySQL to PostgreSQL. If you’re trying to decide if PostgreSQL is right for you, just Google around, there are a lot of resources highlighting the differences.

Please let me know if you have questions, comments or corrections on any of this info. I’ll make sure to update this post if these steps change as the apps evolve.

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

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

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

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.

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.

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.

<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:

# !/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.

echo "# !/bin/shnnopen -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:

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:

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

And this:

$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:

<?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:

<?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

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

As opposed to this:

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

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

As opposed to this:

<?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

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.

Cleaning Up Your CodeIgniter Controllers

One of the issues I’ve always had with CodeIgniter is that it’s kind of difficult to keep my controllers skinny and my models fat. Certain things that are typically handled in the model with other MVC frameworks are often handled in the controller in CI.

For example, it’s fairly common to see code like this in a controller:

application/controllers/products.php

class Products extends CI_Controller {

    public function edit($product_id)
    {
        $this->form_validation
            ->set_rules('name', 'Name', 'required')
            ->set_rules('price', 'Price', 'required|decimal')
            ->set_rules('short_description', 'Short Description', 'required')
            ->set_rules('long_description', 'Long Description', 'required');

        if ($this->form_validation->run())
        {
            $attributes = array(
                'id' => $product_id,
                'name' => $this->input->post('name'),
                'price' => $this->input->post('price'),
                'short_description' => $this->input->post('short_description'),
                'long_description' => $this->input->post('long_description')
            );

            if ($this->company_model->update($attributes))
            {
                $this->messages->success('Product updated successfully!');
                redirect('products');
            }
            else
            {
                $this->messages->error("There was an error updating this product's attributes...");
            }
        }

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

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

and a model like this:

application/models/product_model.php

class Product_model extends CI_Model {

    public function find($product_id)
    {
        return $this->db
            ->where('id', $product_id)
            ->limit(1)
            ->get('products')
            ->row();
    }

    public function update($product_id, $attributes)
    {
        return $this->db
            ->where('id', $product_id)
            ->update('products', $attributes);
    }

    public function get_product_price_breaks($product_id)
    {
        return $this->db
            ->where('product_id', $product_id)
            ->get('product_price_breaks');
    }
}

Room for Improvement

At first glance this controller may not look too bad, and if you’re used to working with CodeIgniter you’ve probably seen something close to this pattern a lot. You may think that, “we are separating our code well and we aren’t running queries in our controller or anything so we’re good to go!”, but I think this is a common misconception in the CI community and that there are a few things we can do here to clean up our controllers and fatten up our models.

Move Validation Rules

In MVC frameworks that use an ORM you can setup validations for your data in the model, which helps keep controllers skinny. Since CodeIgniter doesn’t come with an ORM and the form validation class is all we have, it’s a good idea to make use of the ability to save validation rules to a config file.

application/config/form_validation.php

$config = array(
    array(
        'field' => 'name',
        'label' => 'Name',
        'rules' => 'required'
    ),
    array(
        'field' => 'price',
        'label' => 'Price',
        'rules' => 'required|decimal'
    ),
    array(
        'field' => 'short_description',
        'label' => 'Short Description',
        'rules' => 'required'
    ),
    array(
        'field' => 'long_description',
        'label' => 'Long Description',
        'rules' => 'required'
    )
);

Although your config file can get a little long when you are working on a large application (not so much a problem if you are using Modular Extensions and can have module-level config files), it’s still better than fattening your controllers with validation rules all over.

Prep Form Data in the Model

Once we’ve validated our form in the controller and are ready to submit the data to the database, we may as well setup the associative array we need for the update inside the model.

public function update($product_id, $input)
{
    $attributes = array(
        'name' => $input['name'],
        'price' => $input['price'],
        'short_description' => $input['short_description'],
        'long_description' => $input['long_description']
    );

    return $this->db
        ->where('id', $product_id)
        ->update('products', $attributes);
}

Assign Secondary Queries to Object Attributes

One last optimization we can do is perform all of our queries for the view data and return them as a single object. This way we cut down on clutter in the controller and provide a more logical placeholder for the view data. In this case, we’ll make a product’s price breaks available via the price_breaks attribute ($product->price_breaks). We’ll also remove a couple lines of assigning the results from the model to the $view_data variable.

application/models/product_model.php

public function get_all_product_info($product_id)
{
    $product = $this->find($product_id);
    $product->price_breaks = $this->get_product_price_breaks($product_id);

    return $product;
}

application/controllers/products.php

$view_data['product'] = $this->product_model->get_all_product_info($product_id);

Summary

With just a few simple changes we’ve drastically simplified the controller and made it responsible for only what it needs to be. Take a look at our refactored code compared to our original code and look how much cleaner it is.

Refactored

application/controllers/products.php

class Products extends CI_Controller {

    public function edit($product_id)
    {
        if ($this->form_validation->run())
        {
            if ($this->product_model->update($product_id, $this->input->post()))
            {
                $this->messages->success('Product updated successfully!');
                redirect('products');
            }
            else
            {
                $this->messages->error('There was an error updating this product's attributes...');
            }
        }

        $view_data['product'] = $this->product_model->find($product_id);

        $this->load->view('products/edit', $view_data);
    }
}

application/models/product_model.php

class Product_model extends CI_Model {

    public function find($product_id)
    {
        return $this->db
            ->where('id', $product_id)
            ->limit(1)
            ->get('products')
            ->row();
    }

    public function get_all_product_info($product_id)
    {
        $product = $this->find($product_id);
        $product->price_breaks = $this->get_product_price_breaks($product_id);

        return $product;
    }

    public function update($product_id, $input)
    {
        $attributes = array(
            'name' => $input['name'],
            'price' => $input['price'],
            'short_description' => $input['short_description'],
            'long_description' => $input['long_description']
        );

        return $this->db
            ->where('id', $product_id)
            ->update('products', $attributes);
    }

    public function get_product_price_breaks($product_id)
    {
        return $this->db
            ->where('product_id', $product_id)
            ->get('product_price_breaks');
    }
}

application/config/form_validation.php

$config = array(
    array(
        'field' => 'name',
        'label' => 'Name',
        'rules' => 'required'
    ),
    array(
        'field' => 'price',
        'label' => 'Price',
        'rules' => 'required|decimal'
    ),
    array(
        'field' => 'short_description',
        'label' => 'Short Description',
        'rules' => 'required'
    ),
    array(
        'field' => 'long_description',
        'label' => 'Long Description',
        'rules' => 'required'
    )
);

Note: Another very significant benefit to putting more code in the models is that your code will be much easier to test. Models are easy to test because they almost always return something while controllers are difficult because they usually just display a view. Breaking your code up this way will make it a lot easier if you decide to provide test coverage for your application.

Initial Code

application/controllers/products.php

class Products extends CI_Controller {

    public function edit($product_id)
    {
        $this->form_validation
            ->set_rules('name', 'Name', 'required')
            ->set_rules('price', 'Price', 'required|decimal')
            ->set_rules('short_description', 'Short Description', 'required')
            ->set_rules('long_description', 'Long Description', 'required');

        if ($this->form_validation->run())
        {
            $attributes = array(
                'id' => $product_id,
                'name' => $this->input->post('name'),
                'price' => $this->input->post('price'),
                'short_description' => $this->input->post('short_description'),
                'long_description' => $this->input->post('long_description')
            );

            if ($this->company_model->update($attributes))
            {
                $this->messages->success('Product updated successfully!');
                redirect('products');
            }
            else
            {
                $this->messages->error('There was an error updating this product's attributes...');
            }
        }

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

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

application/models/product_model.php

class Product_model extends CI_Model {

    public function find($product_id)
    {
        return $this->db
            ->where('id', $product_id)
            ->limit(1)
            ->get('products')
            ->row();
    }

    public function update($product_id, $attributes)
    {
        return $this->db
            ->where('id', $product_id)
            ->update('products', $attributes);
    }

    public function get_product_price_breaks($product_id)
    {
        return $this->db
            ->where('product_id', $product_id)
            ->get('product_price_breaks');
    }
}

Changing Default Error Delimiters in CodeIgniter

One thing that I end up doing in almost every CodeIgniter project is changing the default error delimiters from a plain ol’ paragraph

<p></p>

to a fancy shmancy paragraph with an error class on it

<p class="error"></p>

Not a big deal, but I always want a CSS hook for styling my form errors. There are two ways I used to handle this:

  1. Set error delimiters on an as-needed basis in my controller, but that resulted in a lot of code duplication and calling set_error_delimiters() all over the place.
  2. Set error delimiters in the construct of a base controller. It always annoyed me that there wasn’t a config option or something for this and that I still had to put this in a controller and call it on every request.

My Current Solution

One day I was looking through the form validation library and I realized that the error prefix and suffix are set as private variables for the class so I could override them if I extend the form validation library. I just created a MY_Form_validation.php file and dropped it into application/libraries with the following code overriding the default delimiters.

class MY_Form_validation extends CI_Form_validation {

    public function __construct()
    {
        parent::__construct();

        $this->_error_prefix = '<p class="error">';
        $this->_error_suffix = '</p>';
    }
}

My Path To Vim Enlightenment

It’s been about 2 months now since I began using Vim as my full-time editor and I can easily say that my productivity has increased as a result. I’m still only scratching the surface of what the editor can do, but I’m confident that this is going to be one of the single best moves I make in my programming career. Not only will it save me time and money  by not trying out every new editor that comes out on the market, but it is a tool that I can use for the rest of my programming career and on any machine I will ever have to code on. I highly recommend integrating Vim into your workflow and hopefully the following resources will make it a lot easier to do so.

I wanted to write and share some of my experiences with the editor, but there are already so many good articles our there I figured I would just share some of the more helpful ones I’ve come across rather than trying to re-invent the wheel. I tried to list the articles in the order I think it would be most beneficial to read them in, but don’t be afraid to jump around or cherry pick through them. Like I said, I’m only scratching the surface with what the editor is capable of so I will make sure to curate this list over time.

Everyone Who Tried to Convince Me to use Vim was Wrong

An awesome article by Yehuda Katz which talks about his transition to Vim. He lets you know that it’s OK to hangout in insert mode most of the time and stick to your usual editing habits when you’re starting out. This way you can at least continue being productive while trying out the editor so you won’t have to switch back to your old editor if you are feeling pressure of a looming deadline.

A Starting Guide to VIM from Textmate

Even if you’re not coming from TextMate, this article has some practical advice for getting started with Vim. This article is what got me to fire up vimtutor for the first time which was a great way to start editing some text and getting a glimpse of the power of Vim.

Learn Vim Progressively

Probably my favorite Vim article I’ve ever read, or at least the one I got the most out of. It has some great advice on learning Vim and covers some incredibly helpful commands. It was also the first time I saw the power of out Vim Macros.

The Vim Cheat Sheet for Programmers

There are a lot of Vim cheat sheets out there, but this is the one that I keep on-hand and have found to be the most complete and easy to find what I’m looking for.

Anything Else?

Well that’s a starting point, but definitely not a complete list of the articles that have helped me in learning to use Vim. I’m sure this will continue to grow over time.

User Group-specific Controllers in CodeIgniter

I’ve been building out an application that has 2 types of users, corporate and operations. Each user type has access to a lot of the same methods, but operations has access to a little more than corporate. I’ve been struggling with how to break up the code for these two types of users since a lot of it is shared. At first, I thought I had a couple options:

1. Separate the logic into different directories

This would mean that I have completely separate controllers and I would be duplicating methods that are shared for each type of user. I started building this out as an HMVC application with a module for operations that provided the extra methods available to that type of user. This gave me regular URLs like products/edit/48 and operations users would get operations/products/edit/48.

Issues:

I found myself duplicating a lot of code for methods that were shared for each user type and I didn’t really want 2 URLs to access the same method.

2. Create user-specific methods in the same controller

I thought about prefixing methods with “operations_” or “corporate_” so I would have methods like “operations_edit”. Doing things this way I would have had to:

  1. See what type of user is trying to access the method
  2. See if a method with a prefix of their user type exists
  3. Route them accordingly

Issues:

I didn’t like this approach because my controllers would be huge and I’d have to manage 2 of the same method for each type of user, even though I’d try to share private methods with each user type to limit code duplication.

My Current Solution

I thought about it a little more and I decided the way I would like it to work is if I could have a single controller that both user types share, and then be able to provide a controller with user-specific methods if there is anything that I want to override or add only for one user type. I ended up with a file structure like this:

  • modules/products/controllers/products.php – The default
  • modules/products/controllers/operations.php – Operations only
  • modules/products/controllers/corporate.php – Corporate only

Then I use CodeIgniter’s _remap() method to route the user accordingly. This method will:

  1. Check if there is a controller that has methods specific to that user type (corporate.php or operations.php)
  2. Check to see if the requested method exists in that controller
  3. If the method exists, execute it, otherwise try to execute it from the default controller
public function _remap($method, $arguments)
{
    $controller = strtolower($this->router->class);

    if ($controller === $this->uri->segment(1))
    {
        if ($this->acl->is_admin())
        {
            $user_type = 'operations';
        }
        else
        {
            $user_type = 'corporate';
        }

        if ($module = $this->load->module($controller .'/'. $user_type))
        {
            if ( ! method_exists($module, $method))
            {
                $module = $this->load->module($controller);
            }
        }
    }
    else
    {
        $module = $this->load->module($this->uri->segment(1) .'/'. $controller);
    }

    call_user_func_array(array($module, $method), $arguments);
}

Break It Down Now Ya’ll

We start out with CodeIgniter’s _remap() method and setup the $controller variable to be the requested class name lowercased.

public function _remap($method, $arguments)
{
    $controller = strtolower($this->router->class);
}

Then we add a check to see if the requested controller is the default controller for the module. I do this because I don’t want to always override the requested controller, I still want to be able to have controllers for things like product images and categories in the same module. If it’s not the default controller for the module, I just load the requested controller.

if ($controller === $this->uri->segment(1))
{

}
else
{
    $module = $this->load->module($this->uri->segment(1) .'/'. $controller);
}

If they are requesting the default controller, I check to see what type of user they are and assign to to a variable. This could, and probably should, be setup dynamically in most cases.

if ($this->acl->is_admin())
{
    $user_type = 'operations';
}
else
{
    $user_type = 'corporate';
}

Next, I attempt to load the module and their respective controller. If the controller exists, I check to see if the requested method exists. If the method doesn’t exist, that means that I haven’t created a group-specific method for that type of user so I load the default controller.

if ($module = $this->load->module($controller .'/'. $user_type))
{
    if ( ! method_exists($module, $method))
    {
        $module = $this->load->module($controller);
    }
}

And finally, we call the actual method.

call_user_func_array(array($module, $method), $arguments);