Upgrade to Pro — share decks privately, control downloads, hide ads and more …

November 2011 - Plain Ol' Ruby, Part 2, DB Conn...

dallasruby
November 01, 2011

November 2011 - Plain Ol' Ruby, Part 2, DB Connections

Barrett Clark continues a mini series on using Ruby without external frameworks. This session focuses on builds on the previous while adding database connections without an ORM.

Source available at: https://github.com/barrettclark/DallasRubyPOR

Barrett can be found on Twitter at http://twitter.com/barrettclark

dallasruby

November 01, 2011
Tweet

More Decks by dallasruby

Other Decks in Programming

Transcript

  1. What’s So Great About Me? • I work at Geoforce

    • I have a Yellow lab • I’m a recovering perler (4 years!) @barrettclark Tuesday, November 1, 2011
  2. Recap • We have a class or two • Read

    a file and create objects • There are tests Tuesday, November 1, 2011
  3. # test_helper.rb require 'rubygems' require 'bundler/setup' Bundler.require $LOAD_PATH << File.join(File.dirname(__FILE__),

    '..', 'lib') ENV['SCRIPT_ENV'] ||= 'test' require 'db_base' Bam! You’re using Bundler! Application environment Database connection hides in here Not using a database ORM, so you have to handle the connection yourself Note also that there is no framework handling your database setup/cleanup, so you are responsible for that too. No migrations either. Tuesday, November 1, 2011
  4. class DBConnection attr_reader :conn def initialize config = database_config @conn

    = PGconn.open( :dbname => config['dbname'], :user => config['user'], :port => config['port'] ) rescue puts "Unable to connect to the #{ENV['SCRIPT_ENV']} database" end def exec(sql) @conn.exec(sql) end private def database_config puts "Attempting to connect to the #{ENV['SCRIPT_ENV']} database" filename = File.join(File.expand_path(File.dirname(__FILE__)), '..', 'config', 'database.yml') config = YAML.load(File.read(filename)) config[ENV['SCRIPT_ENV'] || 'development'] end end Yes, we are using PostgreSQL via the pg gem. We will work on those puts statements next time. Using the same database.yml that you are already used to working with. You may or may not care about database portability -- something to consider as you build your CRUD and error handling Tuesday, November 1, 2011
  5. class ZipCode < DBBase # snip # We can insert

    records into the database easily def self.create(attributes = {}) zipcode = ZipCode.new(attributes) zipcode.create zipcode end # We can also find records in the database and reconsititute them into ZipCode objects. def self.find(zipcode) sql = "SELECT * FROM zipcode WHERE zip = '#{zipcode}'" result = connection.exec(sql) attributes = Hash.new result.fields.each_with_index do |field, idx| attributes[field.to_sym] = result.column_values(idx).first end ZipCode.new(attributes) end def create fields = [ # NOTE: The 'E' is to tell postgres that the string is (potentially) escaped 'E' + PGconn.quote_connstr(@zip), 'E' + PGconn.quote_connstr(@city), 'E' + PGconn.quote_connstr(@state), @latitude, @longitude, @timezone, @dst ] sql = "INSERT INTO zipcode VALUES (#{fields.join(',')})" result = ZipCode.connection.exec(sql) puts "#{sql}\n Tuples: #{result.cmd_tuples}" if ENV['SCRIPT_ENV'] == 'test' # NOTE: insert queries do not return a result set result rescue PGError=>e puts "#{e}: Unable to insert the zipcode: #{@zipcode}" end end Like inheriting from ActiveRecord::Base Tuesday, November 1, 2011