Showing posts with label why. Show all posts
Showing posts with label why. Show all posts

Sunday, February 27, 2011

Why Haml?

When things are modular, simplicity and understanding have a chance to precipitate. Working with something that deals with a multitude of responsibilities is mentally tiring.

When using markup like HTML, there is a distinction between structure and layout. HTML provides the structure and CSS provides the layout. You should be able to separate out the two. The HTML should still make sense and be organized even without the CSS. This idea is very well demonstrated with CSS Zen Garden.

Inline CSS, I Banish Thee!

So where does Haml come into all of this? With Haml, I find it very hard to use inline CSS. Some may think this is a disadvantage because you can't do quick tweaks (read hacks). Hacks are usually done in the moment with the thought of fixing it up afterwards. Unfortunately, these usually end up sticking around permanently since it works and there is always something more important to do. You end up with HTML that does more than structure. With Haml, you are more inclined to let CSS handle the layout.

My Poor Fingers

Haml saves you a lot of keystrokes. It is much less verbose than HTML and ends up saving you a lot of time. With less characters required, it is easier to see the structure of the entire page at a glance, which helps once you move onto styling the page with CSS.

This Looks Familiar

Once you start converting your HTML to Haml, you'll notice something. It kind of looks like CSS! Because of this, it makes the CSS easier to write and understand.

Haml

If you have time, check out Haml and let me know what you think.

Friday, February 4, 2011

Rails 3.0: Devise + Mongoid + RSpec

Devise removes the mundane job of writing all the code required to handle a user account. Plus, it supports Mongoid.

The following is a non-exhaustive list of tasks Devise takes care of for you:
  • signup
  • forgot/reset password (including emails)
  • confirmation emails
  • password encryption
  • login
  • logout
  • editing account info
  • locking accounts
  • session expiration

All this is available out of the box. Along with the goodies that are pre-packaged, Devise is fully customizable.

Installation

Open Gemfile
gem 'devise'

Install
bundle install
rails generate devise:install

You will need to setup your mailer if it isn't already setup. Devise depends on the default host being set, so ensure the following is set
# ... other mailer settings
config.action_mailer.default_url_options = { :host => 'localhost:3000' }

Don't worry! Devise is smart and has already detected that you are using Mongoid at this point and not ActiveRecord. It has also created config/initializers/devise.rb. This is where you can configure Devise. Take some time to familiarize yourself with all the options and uncomment any that you would like to use. I'll wait.

Test Helpers

If you are using RSpec, create spec/support/devise.rb with
RSpec.configure do |config|
  config.include Devise::TestHelpers, :type => :controller
end

Now you have access to things like
sign_in @user
sign_out @user

Create a User model

It is time to create a User!
rails generate devise user

This generates a user model at app/models/user.rb with some Devise specific lines of code. Include the modules that you want and remove the ones you don't.

Believe it or not, Devise is now properly hooked up and ready!

Routes

Devise automagically generates all the user routes required for handling the user account. If you look in config/routes.rb, you'll notice
devise_for :users

To see all the routes
rake routes

You will notice a bunch of user routes. Fire up your server and navigate to localhost:3000/users/sign_up. Voila!

As a quick reference, here are some useful routes:
  • signup: new_user_registration_url
  • edit account: edit_user_registration_url
  • login: new_user_session_url
  • logout: destroy_new_user_session_url

References

I encourage you to take a look at the Devise home page as there is a wealth of information there.

https://github.com/plataformatec/devise

Monday, October 25, 2010

Rails 3.0: MongoDB + Mongoid

Why Mongoid?

The de facto ORM for MongoDB in Rails is Mongo Mapper, so why choose Mongoid? You can ready why straight from the horses mouth here.

To summarize, Mongoid is built for Rails 3.0 and it handles larger documents better. It also feels like NoSQL when you use it. MongoMapper was built during Rails 2.x days and when MongoDB was young. It is modeled very closely to ActiveRecord to make the transition easier. Hence, it feels more like SQL. MongoMapper is more extensible though with a larger community.

MongoDB

Grab the latest build from MongoDB's download page. At this time, it is 1.6.3.

Download and install. We make a softlink. This way, if we upgrade, we just switch the softlink and everything else stays the same.
cd /usr/local/src/
sudo wget http://fastdl.mongodb.org/linux/mongodb-linux-i686-1.6.3.tgz
sudo tar xzf mongodb-linux-i686-1.6.3.tgz
sudo rm -rf mongodb-linux-i686-1.6.3.tgz
sudo ln -s mongodb-linux-i686-1.6.3 mongodb

Add /usr/local/src/mongodb/bin to your path.
PATH=$PATH:/usr/local/src/mongodb/bin

Make /data/db and give ownership to your user. There are obviously several ways to do this, but this is the easiest.
sudo mkdir -p /data/db
sudo chown -R wesley:wesley /data

Start your engines!
mongod

Mongoid

This builds on top of my previous post on installing Rails 3.0 with BDD. This assumes that the Rails application was created without ActiveRecord using -O. Check out Rails 3.0 agnosticism for an explanation.

Add mongoid to Gemfile. bson_ext is installed for a speed boost.
gem 'mongoid', '2.0.0.rc.6'
gem 'bson_ext', '~>1.2'

Install mongoid.
bundle install
rails generate mongoid:config

Cucumber

Add a cucumber environment to mongoid.yml.
cucumber:
  <<: *defaults
  database: myproject_cucumber 

Cucumber makes use of Database Cleaner. There are posts saying Database Cleaner doesn't work with Mongoid. However, it seems like it is now according to the official documentation. We need to modify features/support/env.rb this is not recommended as it is regenerated on a cucumber-rails upgrade. Instead, we will create features/support/local_env.rb.
require 'database_cleaner'
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.orm = "mongoid"
Before { DatabaseCleaner.clean }

RSpec 2

RSpec includes ActiveRecord specific lines in spec/spec_helper.rb. You need to comment out the following 2 lines.
# config.fixture_path = "#{::Rails.root}/spec/fixtures"
# config.use_transactional_fixtures = true

To properly clean the database, RSpec needs to know how to do that with Mongoid. Again, we can use Database Cleaner for this.

Open up spec/spec_helper.rb and add the following in the RSpec.configure block
RSpec.configure do |config|    
  # Other things

  # Clean up the database      
  require 'database_cleaner'   
  config.before(:suite) do     
    DatabaseCleaner.strategy = :truncation
    DatabaseCleaner.orm = "mongoid" 
  end

  config.before(:each) do
    DatabaseCleaner.clean      
  end
end 

References


Updates

December 2, 2010: Changed Cucumber local_env.rb for database cleaning.
December 2, 2010: Added a section for RSpec database cleaning.
February 1, 2011: Updated Mongoid version in the Gemfile
February 26, 2011: Added a note to clean out ActiveRecord specific lines in RSpec.

Saturday, October 9, 2010

Why MongoDB?

MongoDB is a NoSQL implementation that I've decided to use for my project. One of the major deciding factors is that I deal with MongoDB at work and have experience with it. Unfortunately, this reason alone will not help you decide whether to use MongoDB, so I've outlined some other points below. Feel free to add more in the comments!

What is MongoDB?

MongoDB is a document-based database system. It stores everything in BSON, which is the binary format of JSON. A database holds a bunch of collections (tables). Each collection holds a bunch of documents (records/rows). Each document can be thought of as a large hash object. There are keys (columns) with values and the values can be anything represented in JSON, such as hashes, arrays, numbers, serialized objects, etc. MongoDB has been implemented with ease and speed as its main goals. Every design decision is made with this in mind, which leads to priorities in certain areas over others.

MongoDB vs RDBMS

This is similar to my previous post about NoSQL, but more specifically applied to MongoDB.

Advantages

Schema-less

Documents in a collection don't have to have the same format. This allows more flexible migrations, such as "lazy-loaded" migrations. Basically, there are certain migrations that don't have to happen en masse. They can occur individually when the document is read or written to. This allows for less downtime.

Scalable

Sharding is one of the goals MongoDB is concentrating on. Data is dispersed over two or more servers relieving the load on any single server which increases speed. Downtime is decreased because if a shard goes down, data on the other shards are still accessible. Being able to add shards lends to easier horizontal scaling. MongoDB sharding has been in active development for a while and was unleashed as of version 1.6. Rough spots still exist but MongoDB is looking to patch those up in the coming future.

Failover

Database servers are often setup in a master-slave format. This is not always easy to do. It's even better when the master fails and the slave is automatically upgraded to be the master. This is even harder to do. MongoDB does this seamlessly with replica sets. The servers in a set elect one server to be the master while the others replicate. If the master goes down, the others detect this and elect another server to be the master. New servers can be added without disturbing the setup. The application never has to know if the master has changed. No downtime. Elegant!

Speed

Speed is always a religious-like debate with a million benchmarks showing a million winners. MongoDB has documented a slew of benchmarks. What I take from this is that MongoDB is fast enough. It may or may not be the fastest, but it's definitely blazing. Coupled with the other advantages, I'd say this is a bonus.

GridFS

Ever needed to store large files? You've probably used the file system, Amazon S3, blobs etc. They may or may not have been easy to integrate, but it was another thing you had to deal with. Not with MongoDB. It implements a file storage specification called GridFS. It allows you to store large objects into the database as if it was a normal document. Not only is it one less thing to learn, it makes it easier to move your data since everything is in the database.

Disadvantages

Single server durability

MongoDB does not support this. Yet. Durability is the concept that anything committed to the database is actually committed to the database and resides in there permanently. Single server durability is the idea that a single server alone will maintain durability. However, MongoDB has a different stance on this. They believe that single server durability is not the goal but durability itself is and that durability should be attained through the use of multiple servers and replication. This is a goal MongoDB is actively working towards and which I believe they will achieve.

ACID

MongoDB does not support ACID. This prevents MongoDB being used in certain situations, but the trade-off is worth it for applications that don't require ACID. That gain is in speed. And it's noticeable.

Transactions

Transactions can be viewed as part of ACID, but I thought I'd make this explicit. If you require transactions, MongoDB is out of the question unless you roll your own. Again, for many applications out there, transactions are unnecessary.

Relational

MongoDB does not handle highly relational databases as well as RDBMS. I think this one is obvious, but many forget to take this into consideration when hopping feet first into MongoDB. You've been warned.

MongoDB vs Other NoSQL Implementations

Unfortunately, I haven't worked too much with other implementations of NoSQL. However, most popular NoSQL implementations are in use in production by notable companies. MongoDB is a little easier to wrap your mind around since it still retains quite a lot of similarities with RDBMS, but still gives you that extra kick. One other thing to consider is that MongoDB provides commercial support. This is not currently available with all NoSQL implementations. If you have experience with this, I'd like to hear about it in the comments below.

Conclusion

I'm choosing MongoDB because I've worked with it and have really enjoyed the experience over RDBMS. However, if you're at a crossroads, I'd recommend MongoDB in your next project unless you have a highly relational database or you need ACID.

Saturday, October 2, 2010

Why NoSQL?

Recently, there has been a movement to NoSQL and a disdain for traditional RDBMS when it comes to web development. There have been many discussions pitting the two against each other, almost reaching a religious fervor. With the movement, there have been several new databases available:

Why NoSQL?

Hasn't RDBMS served us well for decades? They're mature, well thought out, and optimized for their task. SQL is a powerful querying language that allows you to do almost anything. So why the change?

PITA

It's human nature at its best. We're given a tool for a task. We use it to its fullest and try to increase the efficiency of the tool. However, there will always be frustrations and clumsiness inherent with the tool. No tool is ever perfect for the job at hand. Working with a tool for many years, the frustrations accumulate until, one day, we can't take it anymore. It's a PITA. We invent something new, even if it isn't as good yet. It at least solves the frustrations of the previous tool, which at this point, is all that matters. Why do I say this is human nature at its best? Because this is how we improve. This is how we take it to the next level. Human beings are never satisfied with the status quo for long.

Scaling

So what's so frustrating with RDBMS? Scaling. It's that simple. RDBMS has problems with scale. When an RDBMS gets large, think about what happens with the following:
  • migrations
  • expansion
  • backups
  • failover
  • locking

Migrations

What happens when you need to migrate data in a table that has millions of rows? Hours of downtime. Downtime for your site means frustrations for your customers. That's not a good thing.

Expansion

How easy is it to tack on another database server? Well, you're going to have to worry about sharding first in the application itself before you can even try. Don't have that code from the beginning? Well, start coding now.

Backups

Don't have sharding? Your backups are going to be huge. This isn't as much of a PITA these days with such large disk space, but no matter what, it's still easier to handle smaller pieces of data.

Failover

The current RDBMS implementations don't make it easy to setup failover. It's usually tacked on afterwards.

Locking

With ACID and transactions, locking is inevitable in RDBMS. With a large scale, there are bound to be long waits. Unfortunately, the larger the database, the more waiting. There are ways around this, but it's a PITA.

Variety

It's not to say that RDBMS isn't good. It's very good at what it does. But, for certain web applications, the tool just doesn't fit. The PITA factor goes through the roof. Does this mean we should default to NoSQL everytime? No. The point is variety. It's not about RDBMS vs NoSQL vs something else. It's about which tool fits best for the job. We should be glad that there's a choice. We can even decide to use RDBMS alongside NoSQL if it works better. Variety is the spice of life.

Where does it fit?

If we can't throw out RDBMS, then when should we use NoSQL? It seems like the jury is still out on this as not all NoSQL implementations are built the same. No implementation solves all the frustrations of RDBMS. Plus, NoSQL hasn't reached the age in production environments to tell what the side-effects are. You will need to do research on this front and see which implementation, if any, of NoSQL fits your problem. Here's a quick guideline though:
  • not many relations (low number of joins)
  • scaling required
  • read-intensive
  • ACID and transactions are not important
  • you just want to geek-out and live on the edge :D

Wednesday, September 15, 2010

Why RVM?

Ubuntu 10.04 comes with Ruby 1.9.1-p378. That's it for 1.9.1. Want another patch level or 1.9.2? Compile it yourself. This is ugly.

Enter RVM.

RVM allows you to install a plethora of Ruby versions and switch between them in a snap. This is a no brainer for Ruby developers as we move forward. Along with Ruby versions, RVM provides the ability to create gemsets to allow the changing of gems depending on projects.

Installing Ruby 1.9.2:
rvm install 1.9.2

Using Ruby 1.9.2:
rvm use 1.9.2

It's that easy. Here's a good installation guide. Look out for instructions after installing RVM. Make sure you do everything it tells you to, especially removing the return from your .bashrc.