Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

Matt Scilipoti

« Newer Snippets
Older Snippets »
Showing 1-4 of 4 total  RSS 

Connect to MS SQL Server via ODBC vs OLEDB.

From http://wiki.rubyonrails.org/rails/pages/HowtoConnectToMicrosoftSQLServer:

Connecting via the OLEDB adaptor seems to have it’s quirks. Another posibility is to connect via ODBC (tested with Rails 1.1.6)

e.g. for a trusted connection
development:
  adapter: sqlserver
  mode: odbc
  dsn: Driver={SQL Server};Server=<your server>;Database=<your db>;Trusted_Connection=yes;

ActiveRecord and SQL Server

From http://www.softiesonrails.com/articles/2006/06/28/activerecord-with-sqlserver-without-rails:

Ensure you done the initial setup for SQL Server and ActiveRecord (ADO.rb).

require 'rubygems'
require_gem 'activerecord'

ActiveRecord::Base.establish_connection(
  :adapter  => "sqlserver",
  :dsn => "instance_name_goes_here",
  :host => "machine_name\\instance_name",
  :database =>  "db_name",
  :username =>  "my_username",
  :password =>  "my_password"
)

class MsSqlTable < ActiveRecord::Base
  def method_missing(method, *args)
    respond_to?(method) ? super : send(method.to_s.camelize, *args)
  end
end

class Item < MsSqlTable
  set_primary_key "sku"
  set_table_name "item"
end


I'll walk through it real quick:

1. The :dsn needs to be your SQL Server instance name
2. The :host needs to a path like "myserver\myinstance", even though you've already specified the instance name in the :dsn parameter
3. The rest of the settings should be obvious. If your password is blank, don't specify :password at all.
4. Our legacy column names are things like OldDescription. So I created an intermediate base class that would provide ruby-like aliases. Now I can use item.old_description instead if I want to.
5. Finally, I declare one class for each table I want to access. I have to set the primary key and table name manually, since our tables don't correspond to any Rails conventions.

I saved this script as legacy.rb, and then fired up irb from that directory:
irb> load 'legacy.rb'
=> true
irb> Item.find("191191").old_description
=> "Table In A Bag"
irb>

pretty tables for rails models

From http://www.rubyinside.com/columnized-text-datasets-in-rails-71.html:
Inspired by: http://blog.caboo.se/articles/2006/06/10/pretty-tables-for-ruby-objects

It gives a MySQL-command-line-client style textual view of data stored in your Rails database. The syntax worked like this:
Something.find(:all, :conditions => β€˜whateverβ€˜).pretty_print


class Array

  protected

    def columnized_row(fields, sized)
      r = []
      fields.each_with_index do |f, i|
        r << sprintf(β€?%0-#{sized[i]}sβ€œ, f.to_s.gsub(/\n|\r/, β€˜β€™).slice(0, sized[i]))
      end
      r.join(’ | β€˜)
    end

  public

  def columnized(options = {})
    sized = {}
    self.each do |row|
      row.attributes.values.each_with_index do |value, i|
        sized[i] = [sized[i].to_i, row.attributes.keys[i].length, value.to_s.length].max
        sized[i] = [options[:max_width], sized[i].to_i].min if options[:max_width]
      end
    end

    table = []
    table << header = columnized_row(self.first.attributes.keys, sized)
    table << header.gsub(/./, β€˜-β€˜)
    self.each { |row| table << columnized_row(row.attributes.values, sized) }
    table.join(β€?\nβ€œ)
  end
end

class ActiveRecord::Base
  def columnized(options = {})
    [*self].columnized(options)
  end
end



To use:
>> puts Post.find(:all).columnized(:max_width => 10)
updated_at | title      | private | url | thumb      | metadata | movie      | id  | views | content    | user_id | created_at
β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
Wed May 31 | tetwer     | 0       |     |            |          |            | 909 | 0     | video:xyzz | 1       | Wed May 31
Wed May 31 | bbbb       | 0       |     |            |          |            | 1   | 15    | // descrip | 1       | Tue May 23
Wed May 31 | cxzcxzx    | 0       |     |            |          |            | 906 | 19    | // descrip | 1       | Tue May 23
Wed May 31 | jklklkl;   | 0       |     |            |          |            | 907 | 35    | // descrip | 1       | Tue May 23


If you want to use it with your project, put the code into lib/columnized.rb, use require β€˜columnized’, and you’re ready to roll. Unlike courtenay’s version, mine only supports max_width, but I didn’t consider changing the column separator too important.

Rails: Inner joins by association names

From http://habtm.com/articles/2006/05/10/inner-joins-by-association-names:

We can enjoy eager loading with association names.
Member.find(:all, :include=>[:group, :profile])

But :joins option forces us to write raw SQL like this.
Member.count(:joins=>"INNER JOIN groups ON groups.id = members.group_id ...")

Why should we do it by hand although those AR classes know their reflections? It’s too boring and painful, and far from DRY.
expand join query

So, why don’t you put this code to β€˜vendor/plugins/expandjoinquery/init.rb’?
class ActiveRecord::Base
  class << self
    private
    def add_joins!(sql, options, scope = :auto)
      scope = scope(:find) if :auto == scope
      join = (scope && scope[:joins]) || options[:joins]
      sql << " #{expand_join_query(join)} " if join
    end

    def expand_join_query(*joins)
      joins.flatten.map{|join|
        case join
        when Symbol
          ref = reflections[join] or
            raise ActiveRecord::ActiveRecordError, "Could not find the source association :#{join} in model #{self}"
          case ref.macro
          when :belongs_to
            "INNER JOIN %s ON %s.%s = %s.%s" % [ref.table_name, ref.table_name, primary_key, table_name, ref.primary_key_name]
          else
            "INNER JOIN %s ON %s.%s = %s.%s" % [ref.table_name, ref.table_name, ref.primary_key_name, table_name, primary_key]
          end
        else
          join.to_s
        end
      }.join(" ")
    end
  end
end

Now, we can enjoy :joins option as same as :include one!
# simply inner join
Member.find(:first, :joins=>:group)
=> SELECT * FROM members INNER JOIN groups ON groups.id = members.group_id LIMIT 1

# two inner joins
Member.count(:joins=>[:group, :profile])
=> SELECT count(*) AS count_all FROM members
   INNER JOIN groups   ON groups.id = members.group_id
   INNER JOIN profiles ON profiles.member_id = members.id 

# symbol and raw SQL
Member.find(:all, :joins=>[:group, "INNER JOIN addresses USING(address_id)"])
=> SELECT * FROM members
   INNER JOIN groups ON groups.id = members.group_id 
   INNER JOIN addresses USING(address_id) 

restrictions

This is just an idea and not deeply considered yet. So, there are following restrictions.

* cascading is not supported
* not work with :include option (i think)

I hope someone will polish this up :)
« Newer Snippets
Older Snippets »
Showing 1-4 of 4 total  RSS