hgimenez-peegee 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.textile CHANGED
@@ -7,8 +7,6 @@ h1. Why?
7
7
  This project started with the need to improve the performance of PostgreSQL's CLUSTER command. While clustering your database tables improves query performance significantly, the actual process of clustering takes unacceptable amounts of time. For instance, it may take roughly 20 hours on a moderately big set of tables (around 60GB). Your milage may vary, of course.
8
8
  Refactoring the clustering functionality surfaced a clean set of utilities that resulted in the creation of this gem. Some are useful, and some are just pointless.
9
9
 
10
- The initial code for this gem was created during the Boston.rb hackfest at Thoughtbot, on April 7th, 2009.
11
-
12
10
  h1. Example usage
13
11
 
14
12
  Assuming we're in a Rails app, you can simply do:
@@ -27,12 +25,11 @@ After the call to drop, the @dependent_foreign_keys instance variable on the peo
27
25
  The strategy used for clustering a table is to store all dependencies in order to restore them later (as viewed above), and move all of the table's data on the order given by a certain index. This is all executed in a database transaction in case it blows up. The result should be just like the pgsql native CLUSTER command:
28
26
  <pre><code>people_table.cluster('people_pk') #must specify an index by which to cluster</code></pre>
29
27
 
30
- h2. Todo
28
+ h1. Todo
31
29
 
32
30
  The first order of business will be to create specs where applicable.
33
31
 
34
- Then, the idea is to keep adding functionality that may be useful for DBAs or application developers and other PostgreSQL users. Some that come to mind are:
35
-
32
+ Then, the idea is to keep adding functionality that may be useful for DBAs or application developers and other PostgreSQL users. Some that come to mind are:
36
33
  * Ability to clean out all of table's index and foreign key names, following a given pattern. On occasions, table names are altered leaving behind pesky legacy names for related objects.
37
34
  * Ability to identify database stinks. For instance:
38
35
  ** tables without primary keys, or indexes (which are not pure join tables)
@@ -49,6 +46,18 @@ I would also like to make this code ORM agnostic. Right now, it depends on Activ
49
46
 
50
47
  Please fork away and help improve it.
51
48
 
49
+ h1. Revision History
50
+
51
+ * Version 0.1.1 (April 13th, 2009):
52
+ ** Set up RSpec testing environment. Started creating test suite.
53
+ ** Added the Configuration singleton class, which for now allows the user to specify which indexes to cluster each table by.
54
+ ** Added exists? class method to Peegee::Table class. Creating a Peegee::Table instance now fails if the table does not exist in the database.
55
+ ** Added bang (!) methods to Peegee::Table class, which force the lookup of foreign_keys!, constraints!, indexes!, etc, even when they're already cached.
56
+ ** Fixed bug in cluster method.
57
+
58
+ * Version 0.1.0 (April 10th, 2009):
59
+ ** First release.
60
+
52
61
  h1. License
53
62
 
54
63
  Copyright (c) 2009 Harold A. Gimenez, released under the MIT license.
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 0
3
3
  :minor: 1
4
- :patch: 0
4
+ :patch: 1
data/lib/peegee.rb CHANGED
@@ -1,6 +1,8 @@
1
- require 'peegee/table'
2
- require 'peegee/constraint'
3
- require 'peegee/unique_constraint'
4
- require 'peegee/primary_key'
5
- require 'peegee/foreign_key'
6
- require 'peegee/index'
1
+ require File.dirname(__FILE__) + '/peegee/table'
2
+ require File.dirname(__FILE__) + '/peegee/constraint'
3
+ require File.dirname(__FILE__) + '/peegee/unique_constraint'
4
+ require File.dirname(__FILE__) + '/peegee/primary_key'
5
+ require File.dirname(__FILE__) + '/peegee/foreign_key'
6
+ require File.dirname(__FILE__) + '/peegee/index'
7
+ require File.dirname(__FILE__) + '/peegee/configuration'
8
+ require File.dirname(__FILE__) + '/peegee/table_does_not_exist_error'
@@ -3,32 +3,34 @@ module Peegee
3
3
 
4
4
  # Clusters this table. See http://www.postgresql.org/docs/8.3/interactive/sql-cluster.html
5
5
  # Optionally specify the index to cluster by (by name or Peegee::Index object).
6
- # If the index is not specify, it will try to induce which index to
7
- # use by looking at postgresql's internals. If it can't find out,
8
- # an exception will be raised.
6
+ # The index to use would ideally be specified using the <tt>Peegee::Configuration</tt>
7
+ # instance. If the index is not specified, it will try to induce which index to
8
+ # use by looking at postgresql's internals.
9
+ # If a proper index can't be found, an exception will be raised.
9
10
  def cluster(cluster_index = nil)
10
11
  cluster_index = find_cluster_index(cluster_index)
11
12
  puts "Cluster index is: #{cluster_index.inspect}"
12
13
  puts "Cluster index type is: #{cluster_index.class.name}"
13
- dependencies = remember_dependencies
14
+ dependencies, dependent_foreign_keys = remember_dependencies
14
15
  ActiveRecord::Base.transaction do
15
- puts "Clustering #{@table_name} by #{cluster_index.index_name} (with order => #{cluster_index.order})"
16
- dependencies.map { |dep| dep.drop }
16
+ dependent_foreign_keys.map { |dfk| dfk.drop }
17
17
  create_tmp_table
18
18
  move_data(cluster_index)
19
19
  drop_original_and_rename_tmp_table
20
20
  dependencies.reverse.map { |dep| dep.create }
21
+ dependent_foreign_keys.map { |dfk| dfk.create }
21
22
  end
22
23
  end
23
24
 
24
25
  private
25
26
 
26
- # Retrieves the Peegee::Index object that will be used
27
- # for clustering this table. The cluster_index parameter can
28
- # be either a string representing the index name, or a Peegee::Index object.
27
+ # Retrieves the <tt>Peegee::Index</tt> object that will be used
28
+ # for clustering this table. The <tt>cluster_index</tt> parameter can
29
+ # be either a string representing the index name, or a <tt>Peegee::Index</tt> object.
29
30
  # Raises an exception if either a proper index was not found
30
- # or more than one index was found given a cluster_index name.
31
+ # or more than one index was found given a <tt>cluster_index</tt> name.
31
32
  def find_cluster_index(cluster_index)
33
+ cluster_index = Peegee::Configuration.instance.cluster_indexes[self.table_name.to_sym].to_s if cluster_index.nil?
32
34
  return cluster_index if cluster_index.kind_of?(Peegee::Index)
33
35
  the_index = nil
34
36
  if cluster_index #cluster_index is specified
@@ -67,7 +69,7 @@ module Peegee
67
69
  # drop the table being clustered (to clean out the dependency on
68
70
  # the sequence).
69
71
  # This method is called after having created the tmp table, otherwise it will fail.
70
- #
72
+ #--
71
73
  # The method for finding a table's sequence is hackish.
72
74
  # TODO: Find a better method for finding a table's sequence.
73
75
  def reasign_sequence_to_tmp_table
@@ -89,8 +91,6 @@ module Peegee
89
91
  seq[2].match /nextval\('[\"']{0,2}(\w*)[\"']{0,2}.*'::regclass\)/
90
92
  sequence_name = $1 #the match above...
91
93
  ActiveRecord::Base.connection.execute("ALTER SEQUENCE \"#{sequence_name}\" OWNED BY #{@table_name}_tmp.#{seq[0]}")
92
- else
93
- puts "\n\n\t*****#{@table_name} apparently doesn't have a sequence"
94
94
  end
95
95
  end
96
96
 
@@ -110,8 +110,8 @@ module Peegee
110
110
  # dependent foreign keys, and indexes.
111
111
  def remember_dependencies
112
112
  dependencies = []
113
- dependencies << foreign_keys << dependent_foreign_keys << indexes
114
- dependencies.flatten
113
+ dependencies << foreign_keys << indexes
114
+ return dependencies.flatten, dependent_foreign_keys
115
115
  end
116
116
 
117
117
  end
@@ -0,0 +1,23 @@
1
+ require 'singleton'
2
+ module Peegee
3
+
4
+ class Configuration
5
+ include Singleton
6
+
7
+ # The mappings between tables and indexes, used
8
+ # for executing Peegee's implementation of the Postgres CLUSTER command.
9
+ # The hash maps tables to indexes. You may pass
10
+ # either a 'string' or a :symbol.
11
+ # For example:
12
+ # <tt>cluster_indexes = {:posts => :ix_posts_on_active_and_created_at,
13
+ # 'users' => 'ix_user_on_active_and_person_id'}</tt>
14
+ @cluster_indexes = {}
15
+ attr_accessor :cluster_indexes
16
+
17
+ def self.run(&block)
18
+ yield Configuration.instance
19
+ end
20
+
21
+ end
22
+
23
+ end
data/lib/peegee/table.rb CHANGED
@@ -3,35 +3,93 @@ module Peegee
3
3
 
4
4
  class Table
5
5
  include Peegee::Clustering
6
+
7
+ attr_accessor :table_name
6
8
 
9
+ # Creates a new instance of Peegee::Table.
10
+ # Receives an +opts+ hash paramater, which expects
11
+ # to contain a key called <tt>:table_name</tt>.
12
+ # A TableDoesNotExistError is thrown if the table
13
+ # with the supplied name is not found in the database.
7
14
  def initialize(opts = {})
8
- @table_name = opts[:table_name]
15
+ if Peegee::Table.exists?(opts[:table_name])
16
+ @table_name = opts[:table_name]
17
+ else
18
+ raise TableDoesNotExistError, "Table #{opts[:table_name]} does not exist", caller
19
+ end
9
20
  end
10
21
 
22
+ # Class method that finds out if a given table name exists in the database.
23
+ def self.exists?(table_name)
24
+ sql = "select * from pg_class where relname = '#{table_name}' and relkind = 'r'"
25
+ !(ActiveRecord::Base.connection.execute(sql).entries.flatten.size == 0)
26
+ end
27
+
28
+ # The postgresql OID for this table.
11
29
  def oid
12
30
  @oid ||= fetch_oid
13
31
  end
14
32
 
33
+ # Returns an array of all foreign keys for this table, as <tt>Peegee::ForeignKey</tt> objects.
34
+ # The first time this method is called, foreign keys are retrieved from the database
35
+ # and cached in an instance variable. Subsequence calls will use the cached values.
36
+ # To force a lookup of foreign keys use the <tt>foreign_keys!</tt> method instead.
15
37
  def foreign_keys
16
38
  @foreign_keys ||= fetch_foreign_keys
17
39
  end
18
40
 
41
+ def foreign_keys!
42
+ fetch_foreign_keys
43
+ end
44
+
45
+ # Returns an array of all dependent foreign keys for this table, as <tt>Peegee::ForeignKey</tt> objects.
46
+ # The first time this method is called, dependent foreign keys are retrieved from the database
47
+ # and cached in an instance variable. Subsequence calls will use the cached values.
48
+ # To force a lookup of dependent foreign keys use the <tt>dependent_foreign_keys!</tt> method instead.
19
49
  def dependent_foreign_keys
20
50
  @dependent_foreign_keys ||= fetch_dependent_foreign_keys
21
51
  end
22
52
 
23
- def primary_keys
24
- @primary_keys ||= fetch_primary_keys
53
+ def dependent_foreign_keys!
54
+ fetch_dependent_foreign_keys
55
+ end
56
+
57
+ # Returns an array of primary keys for this table, as <tt>Peegee::PrimaryKey</tt> objects.
58
+ # The first time this method is called, primary keys are retrieved from the database
59
+ # and cached in an instance variable. Subsequence calls will use the cached values.
60
+ # To force a lookup of primary keys use the <tt>primary_key!</tt> method instead.
61
+ def primary_key
62
+ @primary_key ||= fetch_primary_key
63
+ end
64
+
65
+ def primary_key!
66
+ fetch_primary_key
25
67
  end
26
68
 
69
+ # Returns an array of unique constraints for this table, as <tt>Peegee::UniqueConstraint</tt> objects.
70
+ # The first time this method is called, unique constraints are retrieved from the database
71
+ # and cached in an instance variable. Subsequence calls will use the cached values.
72
+ # To force a lookup of unique constraints use the <tt>unique_constraints!</tt> method instead.
27
73
  def unique_constraints
28
74
  @unique_constraints ||= fetch_unique_constraints
29
75
  end
30
76
 
77
+ def unique_constraints!
78
+ fetch_unique_constraints
79
+ end
80
+
81
+ # Returns an array of indexes for this table, as <tt>Peegee::indexes</tt> objects.
82
+ # The first time this method is called, unique constraints are retrieved from the database
83
+ # and cached in an instance variable. Subsequence calls will use the cached values.
84
+ # To force a lookup of unique constraints use the <tt>indexes!</tt> method instead.
31
85
  def indexes
32
86
  @indexes ||= fetch_indexes
33
87
  end
34
88
 
89
+ def indexes!
90
+ fetch_indexes
91
+ end
92
+
35
93
  # Returns the DDL for this table as a string.
36
94
  def ddl
37
95
  sql = 'SELECT a.attname, ' +
@@ -62,8 +120,8 @@ module Peegee
62
120
  ddl.gsub('\\','')
63
121
  end
64
122
 
65
-
66
123
  private
124
+ # Retrieves this table's OID from the database.
67
125
  def fetch_oid
68
126
  sql = 'SELECT c.oid ' +
69
127
  ' FROM pg_catalog.pg_class c ' +
@@ -73,9 +131,8 @@ module Peegee
73
131
  return ActiveRecord::Base.connection.execute(sql).entries[0]
74
132
  end
75
133
 
76
-
77
-
78
- def fetch_primary_keys
134
+ # Retrieves this table's primary key from the database.
135
+ def fetch_primary_key
79
136
  sql = 'select conname ' +
80
137
  ' , pg_get_constraintdef(pk.oid, true) as foreign_key ' +
81
138
  ' from pg_catalog.pg_constraint pk ' +
@@ -92,7 +149,7 @@ module Peegee
92
149
  end
93
150
  end
94
151
 
95
-
152
+ # Retrieves this table's unique constraints from the database.
96
153
  def fetch_unique_constraints
97
154
  sql = 'select conname ' +
98
155
  ' , pg_get_constraintdef(uc.oid, true) as foreign_key ' +
@@ -110,6 +167,7 @@ module Peegee
110
167
  end
111
168
  end
112
169
 
170
+ # Retrieves this table's foreign keys from the database.
113
171
  def fetch_foreign_keys
114
172
  sql = 'select conname ' +
115
173
  ' , pg_get_constraintdef(fk.oid, true) as foreign_key ' +
@@ -128,6 +186,8 @@ module Peegee
128
186
 
129
187
  end
130
188
 
189
+ # Retrieves this table's dependent foreign keys from the database.
190
+ # A dependent foreign key, is any foreign key that references this table.
131
191
  def fetch_dependent_foreign_keys
132
192
  sql = 'select pg_constraint.conname,' +
133
193
  'dep_table.relname, ' +
@@ -144,6 +204,7 @@ module Peegee
144
204
  end
145
205
  end
146
206
 
207
+ # Retrieves indexes for this table from the database.
147
208
  def fetch_indexes
148
209
  sql = "SELECT pg_get_indexdef(i.indexrelid, 0, true) as index_definition " +
149
210
  ", c2.relname as index_name " +
@@ -151,7 +212,6 @@ module Peegee
151
212
  "FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i " +
152
213
  "WHERE c.oid = '#{@table_name}'::regclass AND c.oid = i.indrelid AND i.indexrelid = c2.oid " #+
153
214
  #"AND i.indisprimary = false" #don't get primary key constraints...
154
- #indexes = ActiveRecord::Base.connection.execute(sql).entries.collect{ |i| i[0] + ';'}
155
215
  indexes = ActiveRecord::Base.connection.execute(sql).entries
156
216
  return indexes.collect do |i|
157
217
  Peegee::Index.new(:table_name => @table_name,
@@ -161,8 +221,6 @@ module Peegee
161
221
  end
162
222
  end
163
223
 
164
-
165
-
166
224
  end
167
225
 
168
226
  end
@@ -0,0 +1,4 @@
1
+ module Peegee
2
+ class TableDoesNotExistError < Exception
3
+ end
4
+ end
data/peegee.gemspec CHANGED
@@ -1,12 +1,12 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
- Gem::Specification.new do |s|
3
+ Gem::Specification.new do |s|
4
4
  s.name = %q{peegee}
5
- s.version = "0.1.0"
5
+ s.version = "0.1.1"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Harold A. Gimenez"]
9
- s.date = %q{2009-04-10}
9
+ s.date = %q{2009-04-13}
10
10
  s.email = %q{harold.gimenez@gmail.com}
11
11
  s.extra_rdoc_files = [
12
12
  "README.textile"
@@ -17,15 +17,21 @@ Gem::Specification.new do |s|
17
17
  "VERSION.yml",
18
18
  "lib/peegee.rb",
19
19
  "lib/peegee/clustering.rb",
20
+ "lib/peegee/configuration.rb",
20
21
  "lib/peegee/constraint.rb",
21
22
  "lib/peegee/foreign_key.rb",
22
23
  "lib/peegee/index.rb",
23
24
  "lib/peegee/primary_key.rb",
24
25
  "lib/peegee/table.rb",
26
+ "lib/peegee/table_does_not_exist_error.rb",
25
27
  "lib/peegee/unique_constraint.rb",
26
28
  "peegee.gemspec",
27
- "spec/peegee_spec.rb",
28
- "spec/spec_helper.rb"
29
+ "spec/factories.rb",
30
+ "spec/fixtures/activerecord_models.rb",
31
+ "spec/fixtures/structure.sql",
32
+ "spec/peegee_helper.rb",
33
+ "spec/spec_helper.rb",
34
+ "spec/unit/peegee_table_spec.rb"
29
35
  ]
30
36
  s.has_rdoc = true
31
37
  s.homepage = %q{http://github.com/hgimenez/peegee}
@@ -35,8 +41,11 @@ Gem::Specification.new do |s|
35
41
  s.rubygems_version = %q{1.3.1}
36
42
  s.summary = %q{A set of utilities for doing PostgreSQL database related stuffs from ruby.}
37
43
  s.test_files = [
38
- "spec/peegee_spec.rb",
39
- "spec/spec_helper.rb"
44
+ "spec/factories.rb",
45
+ "spec/fixtures/activerecord_models.rb",
46
+ "spec/peegee_helper.rb",
47
+ "spec/spec_helper.rb",
48
+ "spec/unit/peegee_table_spec.rb"
40
49
  ]
41
50
 
42
51
  if s.respond_to? :specification_version then
data/spec/factories.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'faker'
2
+ Factory.define :user do |u|
3
+ u.name { Faker::Name.name }
4
+ u.email { Faker::Internet.email }
5
+ u.login { Faker::Internet.user_name }
6
+ u.password { Faker::Lorem.words.join('') }
7
+ u.created_at { Time.now }
8
+ u.updated_at { Time.now }
9
+ end
@@ -0,0 +1,8 @@
1
+ class User < ActiveRecord::Base
2
+ has_many :posts#, :foreign_key => 'created_by_id'
3
+ end
4
+
5
+ class Post < ActiveRecord::Base
6
+ belongs_to :created_by, :class_name => User, :foreign_key => 'created_by_id'
7
+ belongs_to :updated_by, :class_name => User, :foreign_key => 'updated_by_id'
8
+ end
@@ -0,0 +1,62 @@
1
+ DROP TABLE IF EXISTS posts;
2
+ DROP TABLE IF EXISTS users;
3
+
4
+ -- Table: users
5
+ CREATE TABLE users
6
+ (
7
+ id serial NOT NULL,
8
+ "name" character varying(100),
9
+ email character varying(255) NOT NULL,
10
+ "login" character varying(40) NOT NULL DEFAULT ''::character varying,
11
+ "password" character varying(40),
12
+ "admin" boolean NOT NULL DEFAULT false,
13
+ notes text,
14
+ lock_version integer DEFAULT 0,
15
+ salt character varying(255),
16
+ created_at timestamp without time zone,
17
+ updated_at timestamp without time zone,
18
+ CONSTRAINT users_pkey PRIMARY KEY (id)
19
+ )
20
+ WITH (OIDS=FALSE);
21
+ ALTER TABLE users OWNER TO peegee;
22
+
23
+ -- Index: "login"
24
+ DROP INDEX IF EXISTS "login";
25
+
26
+ CREATE UNIQUE INDEX "login"
27
+ ON users
28
+ USING btree
29
+ (login);
30
+
31
+ -- Table: posts
32
+
33
+
34
+ CREATE TABLE posts
35
+ (
36
+ id serial NOT NULL,
37
+ title character varying(255),
38
+ body text,
39
+ status_id integer NOT NULL DEFAULT 1,
40
+ created_at timestamp without time zone NOT NULL,
41
+ updated_at timestamp without time zone NOT NULL,
42
+ published_at timestamp without time zone,
43
+ created_by_id integer NOT NULL,
44
+ updated_by_id integer NOT NULL,
45
+ CONSTRAINT posts_pkey PRIMARY KEY (id),
46
+ CONSTRAINT fk_posts_created_by_id FOREIGN KEY (created_by_id)
47
+ REFERENCES users (id) MATCH SIMPLE
48
+ ON UPDATE NO ACTION ON DELETE NO ACTION,
49
+ CONSTRAINT fk_posts_updated_by_id FOREIGN KEY (updated_by_id)
50
+ REFERENCES users (id) MATCH SIMPLE
51
+ ON UPDATE NO ACTION ON DELETE NO ACTION
52
+ )
53
+ WITH (OIDS=FALSE);
54
+
55
+ ALTER TABLE posts OWNER TO peegee;
56
+
57
+ -- Index: ix_posts_on_status_id
58
+
59
+ CREATE INDEX ix_posts_on_status_id
60
+ ON posts
61
+ USING btree
62
+ (status_id);
@@ -0,0 +1,71 @@
1
+ require 'active_record'
2
+ prefix = defined?(JRUBY_VERSION) ? 'jdbc' : ''
3
+ require "active_record/connection_adapters/#{prefix}postgresql_adapter"
4
+ require 'yaml'
5
+
6
+ class PeegeeHelper
7
+
8
+ attr_accessor :host, :username, :password
9
+ #attr_reader :path
10
+
11
+ def initialize
12
+ @path = File.expand_path(File.dirname(__FILE__))
13
+ @host = 'localhost'
14
+ @username = 'peegee'
15
+ @password = 'peegee'
16
+
17
+ # if you want to overwrite defaults for testing,
18
+ # do it on spec/fixtures/database.yml
19
+ if File.exist?('spec/fixtures/database.yml')
20
+ config = YAML.load(File.open('spec/fixtures/database.yml'))
21
+ @host = config['host']
22
+ @username = config['username']
23
+ @password = config['password']
24
+ end
25
+ end
26
+
27
+ def setup_pgsql
28
+ #Adapter => http://raa.ruby-lang.org/project/postgres-pr/
29
+ ActiveRecord::Base.establish_connection(
30
+ :adapter => 'postgresql',
31
+ :database => 'peegee_test',
32
+ :username => @username,
33
+ :password => @password,
34
+ :host => @host
35
+ )
36
+
37
+ ActiveRecord::Base.logger = Logger.new(active_record_log_file)
38
+
39
+ structure = File.open('spec/fixtures/structure.sql') { |f| f.read.chomp }
40
+ structure.split(';').each { |sql|
41
+ ActiveRecord::Base.connection.execute sql unless sql.start_with? '--'
42
+ }
43
+
44
+ #File.open('spec/fixtures/data.sql') { |f|
45
+ #while line = f.gets
46
+ #ActiveRecord::Base.connection.execute line unless line.blank?
47
+ #end
48
+ #}
49
+ end
50
+
51
+ def configure_peegee
52
+ Peegee::Configuration.run do |config|
53
+ config.cluster_indexes = {
54
+ :users => :users_pkey,
55
+ :posts => :ix_posts_on_status_id
56
+ }
57
+ end
58
+ end
59
+
60
+ def reset
61
+ setup_pgsql
62
+ end
63
+
64
+ AR_LOGFILE = 'tmp/active_record.log'
65
+ private
66
+ def active_record_log_file
67
+ FileUtils.mkdir_p 'tmp'
68
+ File.new(AR_LOGFILE, 'a') unless File.exists?(AR_LOGFILE)
69
+ end
70
+
71
+ end
data/spec/spec_helper.rb CHANGED
@@ -4,6 +4,10 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
4
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
5
  require 'peegee'
6
6
 
7
+ require 'spec/peegee_helper'
8
+ require 'factory_girl'
9
+
7
10
  Spec::Runner.configure do |config|
8
-
11
+ Kernel.const_set :RAILS_ROOT, "#{Dir.pwd}/tmp" unless defined?(RAILS_ROOT)
12
+ require 'spec/fixtures/activerecord_models'
9
13
  end
@@ -0,0 +1,95 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe 'Peegee::Table' do
4
+
5
+ before :all do
6
+ @peegee_helper = PeegeeHelper.new
7
+ @peegee_helper.reset
8
+ end
9
+
10
+ describe 'when creating a Peegee::Table object' do
11
+ describe 'when the table does not exist in the DB' do
12
+ it 'should raise an error' do
13
+ lambda {
14
+ Peegee::Table.new(:table_name => 'foo')
15
+ }.should raise_error(
16
+ Peegee::TableDoesNotExistError
17
+ )
18
+ end
19
+ end
20
+
21
+ describe 'when the table exists on the DB' do
22
+ before :each do
23
+ @users_table = Peegee::Table.new(:table_name => 'users')
24
+ end
25
+ it 'should create a Peegee::Table instance' do
26
+ @users_table.should be_kind_of(Peegee::Table)
27
+ end
28
+ end
29
+ end
30
+
31
+ describe 'clustering a table' do
32
+
33
+ def do_cluster
34
+ @users_table.cluster
35
+ end
36
+
37
+ before :each do
38
+ @peegee_helper.configure_peegee
39
+ 3.times { Factory.create(:user) }
40
+ @users = User.all
41
+ @users_table = Peegee::Table.new(:table_name => 'users')
42
+ @foreign_keys = @users_table.foreign_keys
43
+ @dependent_foreign_keys = @users_table.dependent_foreign_keys
44
+ @primary_key = @users_table.primary_key
45
+ @unique_constraints = @users_table.unique_constraints
46
+ @indexes = @users_table.indexes
47
+ end
48
+
49
+ after :each do
50
+ User.delete_all
51
+ end
52
+
53
+ it 'should maintain all foreign keys on the resulting table' do
54
+ do_cluster
55
+ @users_table.foreign_keys!
56
+ @foreign_keys.each do |fk|
57
+ @users_table.foreign_keys.should include(fk)
58
+ end
59
+ @users_table.foreign_keys.size.should == @foreign_keys.size
60
+ end
61
+
62
+ it 'should maintain all dependent foreign keys on the resulting table' do
63
+ do_cluster
64
+ @users_table.dependent_foreign_keys!
65
+ @dependent_foreign_keys.each do |dpf|
66
+ @users_table.dependent_foreign_keys.should include(dpf)
67
+ end
68
+ @users_table.dependent_foreign_keys.size.should == @dependent_foreign_keys.size
69
+ end
70
+
71
+ it 'should maintain all primary key on the resulting table' do
72
+ do_cluster
73
+ @users_table.primary_key!
74
+ @primary_key.each do |pk|
75
+ @users_table.primary_key.should include(pk)
76
+ end
77
+ @users_table.primary_key.size.should == @primary_key.size
78
+ end
79
+
80
+ it 'should maintain all indexes on the resulting table' do
81
+ do_cluster
82
+ @users_table.indexes!
83
+ @indexes.each do |i|
84
+ @users_table.indexes.should include(i)
85
+ end
86
+ @users_table.indexes.size.should == @indexes.size
87
+ end
88
+
89
+ it 'should maintain all of the data on the resulting table' do
90
+ do_cluster
91
+ @users.should == User.all
92
+ end
93
+
94
+ end
95
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hgimenez-peegee
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harold A. Gimenez
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-04-10 00:00:00 -07:00
12
+ date: 2009-04-13 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -36,15 +36,21 @@ files:
36
36
  - VERSION.yml
37
37
  - lib/peegee.rb
38
38
  - lib/peegee/clustering.rb
39
+ - lib/peegee/configuration.rb
39
40
  - lib/peegee/constraint.rb
40
41
  - lib/peegee/foreign_key.rb
41
42
  - lib/peegee/index.rb
42
43
  - lib/peegee/primary_key.rb
43
44
  - lib/peegee/table.rb
45
+ - lib/peegee/table_does_not_exist_error.rb
44
46
  - lib/peegee/unique_constraint.rb
45
47
  - peegee.gemspec
46
- - spec/peegee_spec.rb
48
+ - spec/factories.rb
49
+ - spec/fixtures/activerecord_models.rb
50
+ - spec/fixtures/structure.sql
51
+ - spec/peegee_helper.rb
47
52
  - spec/spec_helper.rb
53
+ - spec/unit/peegee_table_spec.rb
48
54
  has_rdoc: true
49
55
  homepage: http://github.com/hgimenez/peegee
50
56
  post_install_message:
@@ -72,5 +78,8 @@ signing_key:
72
78
  specification_version: 2
73
79
  summary: A set of utilities for doing PostgreSQL database related stuffs from ruby.
74
80
  test_files:
75
- - spec/peegee_spec.rb
81
+ - spec/factories.rb
82
+ - spec/fixtures/activerecord_models.rb
83
+ - spec/peegee_helper.rb
76
84
  - spec/spec_helper.rb
85
+ - spec/unit/peegee_table_spec.rb
data/spec/peegee_spec.rb DELETED
@@ -1,7 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "Peegee" do
4
- it "fails" do
5
- fail "hey buddy, you should probably rename this file and start specing for real"
6
- end
7
- end