Add version 2.2.2 of composite_primary_keys.

This commit is contained in:
Tom Hughes 2009-05-08 17:54:49 +00:00
parent 9156448ad6
commit a69f380fa5
147 changed files with 6140 additions and 0 deletions

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,67 @@
= Composite Primary Keys - Testing Readme
== Testing an adapter
There are tests available for the following adapters:
* ibmdb
* mysql
* oracle
* postgresql
* sqlite
To run the tests for on of the adapters, follow these steps (using mysql in the example):
* rake -T | grep mysql
rake mysql:build_databases # Build the MySQL test databases
rake mysql:drop_databases # Drop the MySQL test databases
rake mysql:rebuild_databases # Rebuild the MySQL test databases
rake test_mysql # Run tests for test_mysql
* rake mysql:build_databases
* rake test_mysql
== Testing against different ActiveRecord versions (or Edge Rails)
ActiveRecord is a RubyGem within Rails, and is constantly being improved/changed on
its repository (http://dev.rubyonrails.org). These changes may create errors for the CPK
gem. So, we need a way to test CPK against Edge Rails, as well as officially released RubyGems.
The default test (as above) uses the latest RubyGem in your cache.
You can select an older RubyGem version by running the following:
* rake ar:set VERSION=1.14.4 test_mysql
== Edge Rails
Before you can test CPK against Edge Rails, you must checkout a copy of edge rails somewhere (see http://dev.rubyonrails.org for for examples)
* cd /path/to/gems
* svn co http://svn.rubyonrails.org/rails/trunk rails
Say the rails folder is /path/to/gems/rails
Three ways to run CPK tests for Edge Rails:
i) Run:
EDGE_RAILS_DIR=/path/to/gems/rails rake ar:edge test_mysql
ii) In your .profile, set the environment variable EDGE_RAILS_DIR=/path/to/gems/rails,
and once you reload your profile, run:
rake ar:edge test_mysql
iii) Store the path in local/paths.rb. Run:
cp local/paths.rb.sample local/paths.rb
# Now set ENV['EDGE_RAILS_DIR']=/path/to/gems/rails
rake ar:edge test_mysql
These are all variations of the same theme:
* Set the environment variable EDGE_RAILS_DIR to the path to Rails (which contains the activerecord/lib folder)
* Run: rake ar:edge test_<adapter>

View file

@ -0,0 +1,94 @@
$:.unshift(ENV['AR_LOAD_PATH']) if ENV['AR_LOAD_PATH']
require 'test/unit'
require 'hash_tricks'
require 'rubygems'
require 'active_record'
require 'active_record/fixtures'
begin
require 'connection'
rescue MissingSourceFile => e
adapter = 'postgresql' #'sqlite'
require "#{File.dirname(__FILE__)}/connections/native_#{adapter}/connection"
end
require 'composite_primary_keys'
QUOTED_TYPE = ActiveRecord::Base.connection.quote_column_name('type') unless Object.const_defined?(:QUOTED_TYPE)
class Test::Unit::TestCase #:nodoc:
self.fixture_path = File.dirname(__FILE__) + "/fixtures/"
self.use_instantiated_fixtures = false
self.use_transactional_fixtures = true
def assert_date_from_db(expected, actual, message = nil)
# SQL Server doesn't have a separate column type just for dates,
# so the time is in the string and incorrectly formatted
if current_adapter?(:SQLServerAdapter)
assert_equal expected.strftime("%Y/%m/%d 00:00:00"), actual.strftime("%Y/%m/%d 00:00:00")
elsif current_adapter?(:SybaseAdapter)
assert_equal expected.to_s, actual.to_date.to_s, message
else
assert_equal expected.to_s, actual.to_s, message
end
end
def assert_queries(num = 1)
ActiveRecord::Base.connection.class.class_eval do
self.query_count = 0
alias_method :execute, :execute_with_query_counting
end
yield
ensure
ActiveRecord::Base.connection.class.class_eval do
alias_method :execute, :execute_without_query_counting
end
assert_equal num, ActiveRecord::Base.connection.query_count, "#{ActiveRecord::Base.connection.query_count} instead of #{num} queries were executed."
end
def assert_no_queries(&block)
assert_queries(0, &block)
end
cattr_accessor :classes
protected
def testing_with(&block)
classes.keys.each do |@key_test|
@klass_info = classes[@key_test]
@klass, @primary_keys = @klass_info[:class], @klass_info[:primary_keys]
order = @klass.primary_key.is_a?(String) ? @klass.primary_key : @klass.primary_key.join(',')
@first = @klass.find(:first, :order => order)
yield
end
end
def first_id
ids = (1..@primary_keys.length).map {|num| 1}
composite? ? ids.to_composite_ids : ids.first
end
def first_id_str
composite? ? first_id.join(CompositePrimaryKeys::ID_SEP) : first_id.to_s
end
def composite?
@key_test != :single
end
end
def current_adapter?(type)
ActiveRecord::ConnectionAdapters.const_defined?(type) &&
ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters.const_get(type))
end
ActiveRecord::Base.connection.class.class_eval do
cattr_accessor :query_count
alias_method :execute_without_query_counting, :execute
def execute_with_query_counting(sql, name = nil)
self.query_count += 1
execute_without_query_counting(sql, name)
end
end
#ActiveRecord::Base.logger = Logger.new(STDOUT)
#ActiveRecord::Base.colorize_logging = false

View file

@ -0,0 +1,23 @@
print "Using IBM2 \n"
require 'logger'
gem 'ibm_db'
require 'IBM_DB'
RAILS_CONNECTION_ADAPTERS = %w( mysql postgresql sqlite firebird sqlserver db2 oracle sybase openbase frontbase ibm_db )
ActiveRecord::Base.logger = Logger.new("debug.log")
db1 = 'composite_primary_keys_unittest'
connection_options = {
:adapter => "ibm_db",
:database => "ocdpdev",
:username => "db2inst1",
:password => "password",
:host => '192.168.2.21'
}
ActiveRecord::Base.configurations = { db1 => connection_options }
ActiveRecord::Base.establish_connection(connection_options)

View file

@ -0,0 +1,13 @@
print "Using native MySQL\n"
require 'fileutils'
require 'logger'
require 'adapter_helper/mysql'
log_path = File.expand_path(File.join(File.dirname(__FILE__), %w[.. .. .. log]))
FileUtils.mkdir_p log_path
puts "Logging to #{log_path}/debug.log"
ActiveRecord::Base.logger = Logger.new("#{log_path}/debug.log")
# Adapter config setup in locals/database_connections.rb
connection_options = AdapterHelper::MySQL.load_connection_from_env
ActiveRecord::Base.establish_connection(connection_options)

View file

@ -0,0 +1,14 @@
print "Using native Oracle\n"
require 'fileutils'
require 'logger'
require 'adapter_helper/oracle'
log_path = File.expand_path(File.join(File.dirname(__FILE__), %w[.. .. .. log]))
FileUtils.mkdir_p log_path
puts "Logging to #{log_path}/debug.log"
ActiveRecord::Base.logger = Logger.new("#{log_path}/debug.log")
# Adapter config setup in locals/database_connections.rb
connection_options = AdapterHelper::Oracle.load_connection_from_env
puts connection_options.inspect
ActiveRecord::Base.establish_connection(connection_options)

View file

@ -0,0 +1,9 @@
print "Using native Postgresql\n"
require 'logger'
require 'adapter_helper/postgresql'
ActiveRecord::Base.logger = Logger.new("debug.log")
# Adapter config setup in locals/database_connections.rb
connection_options = AdapterHelper::Postgresql.load_connection_from_env
ActiveRecord::Base.establish_connection(connection_options)

View file

@ -0,0 +1,9 @@
print "Using native Sqlite3\n"
require 'logger'
require 'adapter_helper/sqlite3'
ActiveRecord::Base.logger = Logger.new("debug.log")
# Adapter config setup in locals/database_connections.rb
connection_options = AdapterHelper::Sqlite3.load_connection_from_env
ActiveRecord::Base.establish_connection(connection_options)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,5 @@
class Article < ActiveRecord::Base
has_many :readings
has_many :users, :through => :readings
end

View file

@ -0,0 +1,6 @@
first:
id: 1
name: Article One
second:
id: 2
name: Article Two

View file

@ -0,0 +1,6 @@
class Comment < ActiveRecord::Base
set_primary_keys :id
belongs_to :person, :polymorphic => true
belongs_to :hack
end

View file

@ -0,0 +1,16 @@
comment1:
id: 1
person_id: 1
person_type: Employee
comment2:
id: 2
person_id: 1
person_type: User
hack_id: andrew
comment3:
id: 3
person_id: andrew
person_type: Hack

View file

@ -0,0 +1,113 @@
CREATE TABLE reference_types (
reference_type_id integer NOT NULL generated by default as identity (start with 100, increment by 1, no cache),
type_label varchar(50) default NULL,
abbreviation varchar(50) default NULL,
description varchar(50) default NULL,
PRIMARY KEY (reference_type_id)
);
CREATE TABLE reference_codes (
reference_type_id integer,
reference_code integer NOT NULL,
code_label varchar(50) default NULL,
abbreviation varchar(50) default NULL,
description varchar(50) default NULL,
PRIMARY KEY (reference_type_id,reference_code)
);
CREATE TABLE products (
id integer NOT NULL,
name varchar(50) default NULL,
PRIMARY KEY (id)
);
CREATE TABLE tariffs (
tariff_id integer NOT NULL,
start_date date NOT NULL,
amount integer default NULL,
PRIMARY KEY (tariff_id,start_date)
);
CREATE TABLE product_tariffs (
product_id integer NOT NULL,
tariff_id integer NOT NULL,
tariff_start_date date NOT NULL,
PRIMARY KEY (product_id,tariff_id,tariff_start_date)
);
CREATE TABLE suburbs (
city_id integer NOT NULL,
suburb_id integer NOT NULL,
name varchar(50) NOT NULL,
PRIMARY KEY (city_id,suburb_id)
);
CREATE TABLE streets (
id integer NOT NULL ,
city_id integer NOT NULL,
suburb_id integer NOT NULL,
name varchar(50) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE users (
id integer NOT NULL ,
name varchar(50) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE articles (
id integer NOT NULL ,
name varchar(50) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE readings (
id integer NOT NULL ,
user_id integer NOT NULL,
article_id integer NOT NULL,
rating integer NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE groups (
id integer NOT NULL ,
name varchar(50) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE memberships (
user_id integer NOT NULL,
group_id integer NOT NULL,
PRIMARY KEY (user_id,group_id)
);
CREATE TABLE membership_statuses (
id integer NOT NULL ,
user_id integer NOT NULL,
group_id integer NOT NULL,
status varchar(50) NOT NULL,
PRIMARY KEY (id)
);
create table kitchen_sinks (
id_1 integer not null,
id_2 integer not null,
a_date date,
a_string varchar(100),
primary key (id_1, id_2)
);
create table restaurants (
franchise_id integer not null,
store_id integer not null,
name varchar(100),
primary key (franchise_id, store_id)
);
create table restaurants_suburbs (
franchise_id integer not null,
store_id integer not null,
city_id integer not null,
suburb_id integer not null
);

View file

@ -0,0 +1,16 @@
drop table MEMBERSHIPS;
drop table REFERENCE_CODES;
drop table TARIFFS;
drop table ARTICLES;
drop table GROUPS;
drop table MEMBERSHIP_STATUSES;
drop table READINGS;
drop table REFERENCE_TYPES;
drop table STREETS;
drop table PRODUCTS;
drop table USERS;
drop table SUBURBS;
drop table PRODUCT_TARIFFS;
drop table KITCHEN_SINK;
drop table RESTAURANTS;
drop table RESTAURANTS_SUBURBS;

View file

@ -0,0 +1,174 @@
create table reference_types (
reference_type_id int(11) not null auto_increment,
type_label varchar(50) default null,
abbreviation varchar(50) default null,
description varchar(50) default null,
primary key (reference_type_id)
) type=InnoDB;
create table reference_codes (
reference_type_id int(11),
reference_code int(11) not null,
code_label varchar(50) default null,
abbreviation varchar(50) default null,
description varchar(50) default null,
primary key (reference_type_id, reference_code)
) type=InnoDB;
create table products (
id int(11) not null auto_increment,
name varchar(50) default null,
primary key (id)
) type=InnoDB;
create table tariffs (
tariff_id int(11) not null,
start_date date not null,
amount integer(11) default null,
primary key (tariff_id, start_date)
) type=InnoDB;
create table product_tariffs (
product_id int(11) not null,
tariff_id int(11) not null,
tariff_start_date date not null,
primary key (product_id, tariff_id, tariff_start_date)
) type=InnoDB;
create table suburbs (
city_id int(11) not null,
suburb_id int(11) not null,
name varchar(50) not null,
primary key (city_id, suburb_id)
) type=InnoDB;
create table streets (
id int(11) not null auto_increment,
city_id int(11) not null,
suburb_id int(11) not null,
name varchar(50) not null,
primary key (id)
) type=InnoDB;
create table users (
id int(11) not null auto_increment,
name varchar(50) not null,
primary key (id)
) type=InnoDB;
create table articles (
id int(11) not null auto_increment,
name varchar(50) not null,
primary key (id)
) type=InnoDB;
create table readings (
id int(11) not null auto_increment,
user_id int(11) not null,
article_id int(11) not null,
rating int(11) not null,
primary key (id)
) type=InnoDB;
create table groups (
id int(11) not null auto_increment,
name varchar(50) not null,
primary key (id)
) type=InnoDB;
create table memberships (
user_id int(11) not null,
group_id int(11) not null,
primary key (user_id,group_id)
) type=InnoDB;
create table membership_statuses (
id int(11) not null auto_increment,
user_id int(11) not null,
group_id int(11) not null,
status varchar(50) not null,
primary key (id)
) type=InnoDB;
create table departments (
department_id int(11) not null,
location_id int(11) not null,
primary key (department_id, location_id)
) type=InnoDB;
create table employees (
id int(11) not null auto_increment,
department_id int(11) default null,
location_id int(11) default null,
primary key (id)
) type=InnoDB;
create table comments (
id int(11) not null auto_increment,
person_id varchar(100) default null,
person_type varchar(100) default null,
hack_id varchar(100) default null,
primary key (id)
) type=InnoDB;
create table hacks (
name varchar(50) not null,
primary key (name)
) type=InnoDB;
create table kitchen_sinks (
id_1 int(11) not null,
id_2 int(11) not null,
a_date date,
a_string varchar(100),
primary key (id_1, id_2)
) type=InnoDB;
create table restaurants (
franchise_id int(11) not null,
store_id int(11) not null,
name varchar(100),
primary key (franchise_id, store_id)
) type=InnoDB;
create table restaurants_suburbs (
franchise_id int(11) not null,
store_id int(11) not null,
city_id int(11) not null,
suburb_id int(11) not null
) type=InnoDB;
create table dorms (
id int(11) not null auto_increment,
primary key(id)
) type=InnoDB;
create table rooms (
dorm_id int(11) not null,
room_id int(11) not null,
primary key (dorm_id, room_id)
) type=InnoDB;
create table room_attributes (
id int(11) not null auto_increment,
name varchar(50),
primary key(id)
) type=InnoDB;
create table room_attribute_assignments (
dorm_id int(11) not null,
room_id int(11) not null,
room_attribute_id int(11) not null
) type=InnoDB;
create table students (
id int(11) not null auto_increment,
primary key(id)
) type=InnoDB;
create table room_assignments (
student_id int(11) not null,
dorm_id int(11) not null,
room_id int(11) not null
) type=InnoDB;

View file

@ -0,0 +1,39 @@
drop table reference_types;
drop sequence reference_types_seq;
drop table reference_codes;
drop table products;
drop sequence products_seq;
drop table tariffs;
drop table product_tariffs;
drop table suburbs;
drop table streets;
drop sequence streets_seq;
drop table users;
drop sequence users_seq;
drop table articles;
drop sequence articles_seq;
drop table readings;
drop sequence readings_seq;
drop table groups;
drop sequence groups_seq;
drop table memberships;
drop table membership_statuses;
drop sequence membership_statuses_seq;
drop table departments;
drop table employees;
drop sequence employees_seq;
drop table comments;
drop sequence comments_seq;
drop table hacks;
drop table kitchen_sinks;
drop table restaurants;
drop table restaurants_suburbs;
drop table dorms;
drop sequence dorms_seq;
drop table rooms;
drop table room_attributes;
drop sequence room_attributes_seq;
drop table room_attribute_assignments;
drop table room_assignments;
drop table students;
drop sequence students_seq;

View file

@ -0,0 +1,188 @@
create sequence reference_types_seq start with 1000;
create table reference_types (
reference_type_id number(11) primary key,
type_label varchar2(50) default null,
abbreviation varchar2(50) default null,
description varchar2(50) default null
);
create table reference_codes (
reference_type_id number(11),
reference_code number(11),
code_label varchar2(50) default null,
abbreviation varchar2(50) default null,
description varchar2(50) default null
);
create sequence products_seq start with 1000;
create table products (
id number(11) primary key,
name varchar2(50) default null
);
create table tariffs (
tariff_id number(11),
start_date date,
amount number(11) default null,
constraint tariffs_pk primary key (tariff_id, start_date)
);
create table product_tariffs (
product_id number(11),
tariff_id number(11),
tariff_start_date date,
constraint product_tariffs_pk primary key (product_id, tariff_id, tariff_start_date)
);
create table suburbs (
city_id number(11),
suburb_id number(11),
name varchar2(50) not null,
constraint suburbs_pk primary key (city_id, suburb_id)
);
create sequence streets_seq start with 1000;
create table streets (
id number(11) primary key,
city_id number(11) not null,
suburb_id number(11) not null,
name varchar2(50) not null
);
create sequence users_seq start with 1000;
create table users (
id number(11) primary key,
name varchar2(50) not null
);
create sequence articles_seq start with 1000;
create table articles (
id number(11) primary key,
name varchar2(50) not null
);
create sequence readings_seq start with 1000;
create table readings (
id number(11) primary key,
user_id number(11) not null,
article_id number(11) not null,
rating number(11) not null
);
create sequence groups_seq start with 1000;
create table groups (
id number(11) primary key,
name varchar2(50) not null
);
create table memberships (
user_id number(11) not null,
group_id number(11) not null,
constraint memberships_pk primary key (user_id, group_id)
);
create sequence membership_statuses_seq start with 1000;
create table membership_statuses (
id number(11) primary key,
user_id number(11) not null,
group_id number(11) not null,
status varchar2(50) not null
);
create table departments (
department_id number(11) not null,
location_id number(11) not null,
constraint departments_pk primary key (department_id, location_id)
);
create sequence employees_seq start with 1000;
create table employees (
id number(11) not null primary key,
department_id number(11) default null,
location_id number(11) default null
);
create sequence comments_seq start with 1000;
create table comments (
id number(11) not null primary key,
person_id varchar(100) default null,
person_type varchar(100) default null,
hack_id varchar(100) default null
);
create table hacks (
name varchar(50) not null primary key
);
create table kitchen_sinks (
id_1 number(11) not null,
id_2 number(11) not null,
a_date date,
a_string varchar(100),
constraint kitchen_sinks_pk primary key (id_1, id_2)
);
create table restaurants (
franchise_id number(11) not null,
store_id number(11) not null,
name varchar(100),
constraint restaurants_pk primary key (franchise_id, store_id)
);
create table restaurants_suburbs (
franchise_id number(11) not null,
store_id number(11) not null,
city_id number(11) not null,
suburb_id number(11) not null
);
create sequence dorms_seq start with 1000;
create table dorms (
id number(11) not null,
constraint dorms_pk primary key (id)
);
create table rooms (
dorm_id number(11) not null,
room_id number(11) not null,
constraint rooms_pk primary key (dorm_id, room_id)
);
create sequence room_attributes_seq start with 1000;
create table room_attributes (
id number(11) not null,
name varchar(50),
constraint room_attributes_pk primary key (id)
);
create table room_attribute_assignments (
dorm_id number(11) not null,
room_id number(11) not null,
room_attribute_id number(11) not null
);
create sequence students_seq start with 1000;
create table students (
id number(11) not null,
constraint students_pk primary key (id)
);
create table room_assignments (
student_id number(11) not null,
dorm_id number(11) not null,
room_id number(11) not null
);

View file

@ -0,0 +1,199 @@
create sequence public.reference_types_seq start 1000;
create table reference_types (
reference_type_id int default nextval('public.reference_types_seq'),
type_label varchar(50) default null,
abbreviation varchar(50) default null,
description varchar(50) default null,
primary key (reference_type_id)
);
create table reference_codes (
reference_type_id int,
reference_code int not null,
code_label varchar(50) default null,
abbreviation varchar(50) default null,
description varchar(50) default null
);
create sequence public.products_seq start 1000;
create table products (
id int not null default nextval('public.products_seq'),
name varchar(50) default null,
primary key (id)
);
create table tariffs (
tariff_id int not null,
start_date date not null,
amount int default null,
primary key (tariff_id, start_date)
);
create table product_tariffs (
product_id int not null,
tariff_id int not null,
tariff_start_date date not null,
primary key (product_id, tariff_id, tariff_start_date)
);
create table suburbs (
city_id int not null,
suburb_id int not null,
name varchar(50) not null,
primary key (city_id, suburb_id)
);
create sequence public.streets_seq start 1000;
create table streets (
id int not null default nextval('public.streets_seq'),
city_id int not null,
suburb_id int not null,
name varchar(50) not null,
primary key (id)
);
create sequence public.users_seq start 1000;
create table users (
id int not null default nextval('public.users_seq'),
name varchar(50) not null,
primary key (id)
);
create sequence public.articles_seq start 1000;
create table articles (
id int not null default nextval('public.articles_seq'),
name varchar(50) not null,
primary key (id)
);
create sequence public.readings_seq start 1000;
create table readings (
id int not null default nextval('public.readings_seq'),
user_id int not null,
article_id int not null,
rating int not null,
primary key (id)
);
create sequence public.groups_seq start 1000;
create table groups (
id int not null default nextval('public.groups_seq'),
name varchar(50) not null,
primary key (id)
);
create table memberships (
user_id int not null,
group_id int not null,
primary key (user_id, group_id)
);
create sequence public.membership_statuses_seq start 1000;
create table membership_statuses (
id int not null default nextval('public.membership_statuses_seq'),
user_id int not null,
group_id int not null,
status varchar(50) not null,
primary key (id)
);
create table departments (
department_id int not null,
location_id int not null,
primary key (department_id, location_id)
);
create sequence public.employees_seq start 1000;
create table employees (
id int not null default nextval('public.employees_seq'),
department_id int default null,
location_id int default null,
primary key (id)
);
create sequence public.comments_seq start 1000;
create table comments (
id int not null default nextval('public.comments_seq'),
person_id varchar(100) default null,
person_type varchar(100) default null,
hack_id varchar(100) default null,
primary key (id)
);
create table hacks (
name varchar(50) not null,
primary key (name)
);
create table kitchen_sinks (
id_1 int not null,
id_2 int not null,
a_date date,
a_string varchar(100),
primary key (id_1, id_2)
);
create table restaurants (
franchise_id int not null,
store_id int not null,
name varchar(100),
primary key (franchise_id, store_id)
);
create table restaurants_suburbs (
franchise_id int not null,
store_id int not null,
city_id int not null,
suburb_id int not null
);
create sequence public.dorms_seq start 1000;
create table dorms (
id int not null default nextval('public.dorms_seq'),
primary key (id)
);
create table rooms (
dorm_id int not null,
room_id int not null,
primary key (dorm_id, room_id)
);
create sequence public.room_attributes_seq start 1000;
create table room_attributes (
id int not null default nextval('public.room_attributes_seq'),
name varchar(50),
primary key (id)
);
create table room_attribute_assignments (
dorm_id int not null,
room_id int not null,
room_attribute_id int not null
);
create sequence public.students_seq start 1000;
create table students (
id int not null default nextval('public.students_seq'),
primary key (id)
);
create table room_assignments (
student_id int not null,
dorm_id int not null,
room_id int not null
);

View file

@ -0,0 +1,160 @@
create table reference_types (
reference_type_id integer primary key,
type_label varchar(50) default null,
abbreviation varchar(50) default null,
description varchar(50) default null
);
create table reference_codes (
reference_type_id int(11),
reference_code int(11) not null,
code_label varchar(50) default null,
abbreviation varchar(50) default null,
description varchar(50) default null,
primary key (reference_type_id, reference_code)
);
create table products (
id int(11) not null primary key,
name varchar(50) default null
);
create table tariffs (
tariff_id int(11) not null,
start_date date not null,
amount integer(11) default null,
primary key (tariff_id, start_date)
);
create table product_tariffs (
product_id int(11) not null,
tariff_id int(11) not null,
tariff_start_date date not null,
primary key (product_id, tariff_id, tariff_start_date)
);
create table suburbs (
city_id int(11) not null,
suburb_id int(11) not null,
name varchar(50) not null,
primary key (city_id, suburb_id)
);
create table streets (
id integer not null primary key autoincrement,
city_id int(11) not null,
suburb_id int(11) not null,
name varchar(50) not null
);
create table users (
id integer not null primary key autoincrement,
name varchar(50) not null
);
create table articles (
id integer not null primary key autoincrement,
name varchar(50) not null
);
create table readings (
id integer not null primary key autoincrement,
user_id int(11) not null,
article_id int(11) not null,
rating int(11) not null
);
create table groups (
id integer not null primary key autoincrement,
name varchar(50) not null
);
create table memberships (
user_id int not null,
group_id int not null,
primary key (user_id, group_id)
);
create table membership_statuses (
id integer not null primary key autoincrement,
user_id int not null,
group_id int not null,
status varchar(50) not null
);
create table departments (
department_id integer not null,
location_id integer not null,
primary key (department_id, location_id)
);
create table employees (
id integer not null primary key autoincrement,
department_id integer null,
location_id integer null
);
create table comments (
id integer not null primary key autoincrement,
person_id varchar(100) null,
person_type varchar(100) null,
hack_id varchar(100) null
);
create table hacks (
name varchar(50) not null primary key
);
create table kitchen_sinks (
id_1 integer not null,
id_2 integer not null,
a_date date,
a_string varchar(100),
primary key (id_1, id_2)
);
create table restaurants (
franchise_id integer not null,
store_id integer not null,
name varchar(100),
primary key (franchise_id, store_id)
);
create table restaurants_suburbs (
franchise_id integer not null,
store_id integer not null,
city_id integer not null,
suburb_id integer not null
);
create table dorms (
id integer not null primary key autoincrement
);
create table rooms (
dorm_id integer not null,
room_id integer not null,
primary key (dorm_id, room_id)
);
create table room_attributes (
id integer not null primary key autoincrement,
name varchar(50)
);
create table room_attribute_assignments (
dorm_id integer not null,
room_id integer not null,
room_attribute_id integer not null
);
create table students (
id integer not null primary key autoincrement
);
create table room_assignments (
student_id integer not null,
dorm_id integer not null,
room_id integer not null
);

View file

@ -0,0 +1,5 @@
class Department < ActiveRecord::Base
# set_primary_keys *keys - turns on composite key functionality
set_primary_keys :department_id, :location_id
has_many :employees, :foreign_key => [:department_id, :location_id]
end

View file

@ -0,0 +1,3 @@
department1-cpk:
department_id: 1
location_id: 1

View file

@ -0,0 +1,4 @@
class Employee < ActiveRecord::Base
belongs_to :department, :foreign_key => [:department_id, :location_id]
has_many :comments, :as => :person
end

View file

@ -0,0 +1,9 @@
employee1:
id: 1
department_id: 1
location_id: 1
employee2:
id: 2
department_id: 1
location_id: 1

View file

@ -0,0 +1,3 @@
class Group < ActiveRecord::Base
has_many :memberships
end

View file

@ -0,0 +1,3 @@
cpk:
id: 1
name: Composite Primary Keys

View file

@ -0,0 +1,6 @@
class Hack < ActiveRecord::Base
set_primary_keys :name
has_many :comments, :as => :person
has_one :first_comment, :as => :person, :class_name => "Comment"
end

View file

@ -0,0 +1,2 @@
andrew:
name: andrew

View file

@ -0,0 +1,7 @@
class Membership < ActiveRecord::Base
# set_primary_keys *keys - turns on composite key functionality
set_primary_keys :user_id, :group_id
belongs_to :user
belongs_to :group
has_many :statuses, :class_name => 'MembershipStatus', :foreign_key => [:user_id, :group_id]
end

View file

@ -0,0 +1,3 @@
class MembershipStatus < ActiveRecord::Base
belongs_to :membership, :foreign_key => [:user_id, :group_id]
end

View file

@ -0,0 +1,10 @@
santiago-cpk:
id: 1
user_id: 1
group_id: 1
status: Active
drnic-cpk:
id: 2
user_id: 2
group_id: 1
status: Owner

View file

@ -0,0 +1,6 @@
santiago-cpk:
user_id: 1
group_id: 1
drnic-cpk:
user_id: 2
group_id: 1

View file

@ -0,0 +1,7 @@
class Product < ActiveRecord::Base
set_primary_keys :id # redundant
has_many :product_tariffs, :foreign_key => :product_id
has_one :product_tariff, :foreign_key => :product_id
has_many :tariffs, :through => :product_tariffs, :foreign_key => [:tariff_id, :tariff_start_date]
end

View file

@ -0,0 +1,5 @@
class ProductTariff < ActiveRecord::Base
set_primary_keys :product_id, :tariff_id, :tariff_start_date
belongs_to :product, :foreign_key => :product_id
belongs_to :tariff, :foreign_key => [:tariff_id, :tariff_start_date]
end

View file

@ -0,0 +1,12 @@
first_flat:
product_id: 1
tariff_id: 1
tariff_start_date: <%= Date.today.to_s(:db) %>
first_free:
product_id: 1
tariff_id: 2
tariff_start_date: <%= Date.today.to_s(:db) %>
second_free:
product_id: 2
tariff_id: 2
tariff_start_date: <%= Date.today.to_s(:db) %>

View file

@ -0,0 +1,6 @@
first_product:
id: 1
name: Product One
second_product:
id: 2
name: Product Two

View file

@ -0,0 +1,4 @@
class Reading < ActiveRecord::Base
belongs_to :article
belongs_to :user
end

View file

@ -0,0 +1,10 @@
santiago_first:
id: 1
user_id: 1
article_id: 1
rating: 4
santiago_second:
id: 2
user_id: 1
article_id: 2
rating: 5

View file

@ -0,0 +1,7 @@
class ReferenceCode < ActiveRecord::Base
set_primary_keys :reference_type_id, :reference_code
belongs_to :reference_type, :foreign_key => "reference_type_id"
validates_presence_of :reference_code, :code_label, :abbreviation
end

View file

@ -0,0 +1,28 @@
name_prefix_mr:
reference_type_id: 1
reference_code: 1
code_label: MR
abbreviation: Mr
name_prefix_mrs:
reference_type_id: 1
reference_code: 2
code_label: MRS
abbreviation: Mrs
name_prefix_ms:
reference_type_id: 1
reference_code: 3
code_label: MS
abbreviation: Ms
gender_male:
reference_type_id: 2
reference_code: 1
code_label: MALE
abbreviation: Male
gender_female:
reference_type_id: 2
reference_code: 2
code_label: FEMALE
abbreviation: Female

View file

@ -0,0 +1,7 @@
class ReferenceType < ActiveRecord::Base
set_primary_key :reference_type_id
has_many :reference_codes, :foreign_key => "reference_type_id"
validates_presence_of :type_label, :abbreviation
validates_uniqueness_of :type_label
end

View file

@ -0,0 +1,9 @@
name_prefix:
reference_type_id: 1
type_label: NAME_PREFIX
abbreviation: Name Prefix
gender:
reference_type_id: 2
type_label: GENDER
abbreviation: Gender

View file

@ -0,0 +1,3 @@
class Street < ActiveRecord::Base
belongs_to :suburb, :foreign_key => [:city_id, :suburb_id]
end

View file

@ -0,0 +1,15 @@
first:
id: 1
city_id: 1
suburb_id: 1
name: First Street
second1:
id: 2
city_id: 2
suburb_id: 1
name: First Street
second2:
id: 3
city_id: 2
suburb_id: 1
name: Second Street

View file

@ -0,0 +1,6 @@
class Suburb < ActiveRecord::Base
set_primary_keys :city_id, :suburb_id
has_many :streets, :foreign_key => [:city_id, :suburb_id]
has_many :first_streets, :foreign_key => [:city_id, :suburb_id],
:class_name => 'Street', :conditions => "streets.name = 'First Street'"
end

View file

@ -0,0 +1,9 @@
first:
city_id: 1
suburb_id: 1
name: First Suburb
second:
city_id: 2
suburb_id: 1
name: Second Suburb

View file

@ -0,0 +1,6 @@
class Tariff < ActiveRecord::Base
set_primary_keys [:tariff_id, :start_date]
has_many :product_tariffs, :foreign_key => [:tariff_id, :tariff_start_date]
has_one :product_tariff, :foreign_key => [:tariff_id, :tariff_start_date]
has_many :products, :through => :product_tariffs, :foreign_key => [:tariff_id, :tariff_start_date]
end

View file

@ -0,0 +1,13 @@
flat:
tariff_id: 1
start_date: <%= Date.today.to_s(:db) %>
amount: 50
free:
tariff_id: 2
start_date: <%= Date.today.to_s(:db) %>
amount: 0
flat_future:
tariff_id: 1
start_date: <%= Date.today.next.to_s(:db) %>
amount: 100

View file

@ -0,0 +1,10 @@
class User < ActiveRecord::Base
has_many :readings
has_many :articles, :through => :readings
has_many :comments, :as => :person
has_many :hacks, :through => :comments, :source => :hack
def find_custom_articles
articles.find(:all, :conditions => ["name = ?", "Article One"])
end
end

View file

@ -0,0 +1,6 @@
santiago:
id: 1
name: Santiago
drnic:
id: 2
name: Dr Nic

View file

@ -0,0 +1,34 @@
# From:
# http://www.bigbold.com/snippets/posts/show/2178
# http://blog.caboo.se/articles/2006/06/11/stupid-hash-tricks
#
# An example utilisation of these methods in a controller is:
# def some_action
# # some script kiddie also passed in :bee, which we don't want tampered with _here_.
# @model = Model.create(params.pass(:foo, :bar))
# end
class Hash
# lets through the keys in the argument
# >> {:one => 1, :two => 2, :three => 3}.pass(:one)
# => {:one=>1}
def pass(*keys)
keys = keys.first if keys.first.is_a?(Array)
tmp = self.clone
tmp.delete_if {|k,v| ! keys.include?(k.to_sym) }
tmp.delete_if {|k,v| ! keys.include?(k.to_s) }
tmp
end
# blocks the keys in the arguments
# >> {:one => 1, :two => 2, :three => 3}.block(:one)
# => {:two=>2, :three=>3}
def block(*keys)
keys = keys.first if keys.first.is_a?(Array)
tmp = self.clone
tmp.delete_if {|k,v| keys.include?(k.to_sym) }
tmp.delete_if {|k,v| keys.include?(k.to_s) }
tmp
end
end

View file

@ -0,0 +1,405 @@
module ActionController
# === Action Pack pagination for Active Record collections
#
# The Pagination module aids in the process of paging large collections of
# Active Record objects. It offers macro-style automatic fetching of your
# model for multiple views, or explicit fetching for single actions. And if
# the magic isn't flexible enough for your needs, you can create your own
# paginators with a minimal amount of code.
#
# The Pagination module can handle as much or as little as you wish. In the
# controller, have it automatically query your model for pagination; or,
# if you prefer, create Paginator objects yourself.
#
# Pagination is included automatically for all controllers.
#
# For help rendering pagination links, see
# ActionView::Helpers::PaginationHelper.
#
# ==== Automatic pagination for every action in a controller
#
# class PersonController < ApplicationController
# model :person
#
# paginate :people, :order => 'last_name, first_name',
# :per_page => 20
#
# # ...
# end
#
# Each action in this controller now has access to a <tt>@people</tt>
# instance variable, which is an ordered collection of model objects for the
# current page (at most 20, sorted by last name and first name), and a
# <tt>@person_pages</tt> Paginator instance. The current page is determined
# by the <tt>params[:page]</tt> variable.
#
# ==== Pagination for a single action
#
# def list
# @person_pages, @people =
# paginate :people, :order => 'last_name, first_name'
# end
#
# Like the previous example, but explicitly creates <tt>@person_pages</tt>
# and <tt>@people</tt> for a single action, and uses the default of 10 items
# per page.
#
# ==== Custom/"classic" pagination
#
# def list
# @person_pages = Paginator.new self, Person.count, 10, params[:page]
# @people = Person.find :all, :order => 'last_name, first_name',
# :limit => @person_pages.items_per_page,
# :offset => @person_pages.current.offset
# end
#
# Explicitly creates the paginator from the previous example and uses
# Paginator#to_sql to retrieve <tt>@people</tt> from the model.
#
module Pagination
unless const_defined?(:OPTIONS)
# A hash holding options for controllers using macro-style pagination
OPTIONS = Hash.new
# The default options for pagination
DEFAULT_OPTIONS = {
:class_name => nil,
:singular_name => nil,
:per_page => 10,
:conditions => nil,
:order_by => nil,
:order => nil,
:join => nil,
:joins => nil,
:count => nil,
:include => nil,
:select => nil,
:group => nil,
:parameter => 'page'
}
else
DEFAULT_OPTIONS[:group] = nil
end
def self.included(base) #:nodoc:
super
base.extend(ClassMethods)
end
def self.validate_options!(collection_id, options, in_action) #:nodoc:
options.merge!(DEFAULT_OPTIONS) {|key, old, new| old}
valid_options = DEFAULT_OPTIONS.keys
valid_options << :actions unless in_action
unknown_option_keys = options.keys - valid_options
raise ActionController::ActionControllerError,
"Unknown options: #{unknown_option_keys.join(', ')}" unless
unknown_option_keys.empty?
options[:singular_name] ||= ActiveSupport::Inflector.singularize(collection_id.to_s)
options[:class_name] ||= ActiveSupport::Inflector.camelize(options[:singular_name])
end
# Returns a paginator and a collection of Active Record model instances
# for the paginator's current page. This is designed to be used in a
# single action; to automatically paginate multiple actions, consider
# ClassMethods#paginate.
#
# +options+ are:
# <tt>:singular_name</tt>:: the singular name to use, if it can't be inferred by singularizing the collection name
# <tt>:class_name</tt>:: the class name to use, if it can't be inferred by
# camelizing the singular name
# <tt>:per_page</tt>:: the maximum number of items to include in a
# single page. Defaults to 10
# <tt>:conditions</tt>:: optional conditions passed to Model.find(:all, *params) and
# Model.count
# <tt>:order</tt>:: optional order parameter passed to Model.find(:all, *params)
# <tt>:order_by</tt>:: (deprecated, used :order) optional order parameter passed to Model.find(:all, *params)
# <tt>:joins</tt>:: optional joins parameter passed to Model.find(:all, *params)
# and Model.count
# <tt>:join</tt>:: (deprecated, used :joins or :include) optional join parameter passed to Model.find(:all, *params)
# and Model.count
# <tt>:include</tt>:: optional eager loading parameter passed to Model.find(:all, *params)
# and Model.count
# <tt>:select</tt>:: :select parameter passed to Model.find(:all, *params)
#
# <tt>:count</tt>:: parameter passed as :select option to Model.count(*params)
#
# <tt>:group</tt>:: :group parameter passed to Model.find(:all, *params). It forces the use of DISTINCT instead of plain COUNT to come up with the total number of records
#
def paginate(collection_id, options={})
Pagination.validate_options!(collection_id, options, true)
paginator_and_collection_for(collection_id, options)
end
# These methods become class methods on any controller
module ClassMethods
# Creates a +before_filter+ which automatically paginates an Active
# Record model for all actions in a controller (or certain actions if
# specified with the <tt>:actions</tt> option).
#
# +options+ are the same as PaginationHelper#paginate, with the addition
# of:
# <tt>:actions</tt>:: an array of actions for which the pagination is
# active. Defaults to +nil+ (i.e., every action)
def paginate(collection_id, options={})
Pagination.validate_options!(collection_id, options, false)
module_eval do
before_filter :create_paginators_and_retrieve_collections
OPTIONS[self] ||= Hash.new
OPTIONS[self][collection_id] = options
end
end
end
def create_paginators_and_retrieve_collections #:nodoc:
Pagination::OPTIONS[self.class].each do |collection_id, options|
next unless options[:actions].include? action_name if
options[:actions]
paginator, collection =
paginator_and_collection_for(collection_id, options)
paginator_name = "@#{options[:singular_name]}_pages"
self.instance_variable_set(paginator_name, paginator)
collection_name = "@#{collection_id.to_s}"
self.instance_variable_set(collection_name, collection)
end
end
# Returns the total number of items in the collection to be paginated for
# the +model+ and given +conditions+. Override this method to implement a
# custom counter.
def count_collection_for_pagination(model, options)
model.count(:conditions => options[:conditions],
:joins => options[:join] || options[:joins],
:include => options[:include],
:select => (options[:group] ? "DISTINCT #{options[:group]}" : options[:count]))
end
# Returns a collection of items for the given +model+ and +options[conditions]+,
# ordered by +options[order]+, for the current page in the given +paginator+.
# Override this method to implement a custom finder.
def find_collection_for_pagination(model, options, paginator)
model.find(:all, :conditions => options[:conditions],
:order => options[:order_by] || options[:order],
:joins => options[:join] || options[:joins], :include => options[:include],
:select => options[:select], :limit => options[:per_page],
:group => options[:group], :offset => paginator.current.offset)
end
protected :create_paginators_and_retrieve_collections,
:count_collection_for_pagination,
:find_collection_for_pagination
def paginator_and_collection_for(collection_id, options) #:nodoc:
klass = options[:class_name].constantize
page = params[options[:parameter]]
count = count_collection_for_pagination(klass, options)
paginator = Paginator.new(self, count, options[:per_page], page)
collection = find_collection_for_pagination(klass, options, paginator)
return paginator, collection
end
private :paginator_and_collection_for
# A class representing a paginator for an Active Record collection.
class Paginator
include Enumerable
# Creates a new Paginator on the given +controller+ for a set of items
# of size +item_count+ and having +items_per_page+ items per page.
# Raises ArgumentError if items_per_page is out of bounds (i.e., less
# than or equal to zero). The page CGI parameter for links defaults to
# "page" and can be overridden with +page_parameter+.
def initialize(controller, item_count, items_per_page, current_page=1)
raise ArgumentError, 'must have at least one item per page' if
items_per_page <= 0
@controller = controller
@item_count = item_count || 0
@items_per_page = items_per_page
@pages = {}
self.current_page = current_page
end
attr_reader :controller, :item_count, :items_per_page
# Sets the current page number of this paginator. If +page+ is a Page
# object, its +number+ attribute is used as the value; if the page does
# not belong to this Paginator, an ArgumentError is raised.
def current_page=(page)
if page.is_a? Page
raise ArgumentError, 'Page/Paginator mismatch' unless
page.paginator == self
end
page = page.to_i
@current_page_number = has_page_number?(page) ? page : 1
end
# Returns a Page object representing this paginator's current page.
def current_page
@current_page ||= self[@current_page_number]
end
alias current :current_page
# Returns a new Page representing the first page in this paginator.
def first_page
@first_page ||= self[1]
end
alias first :first_page
# Returns a new Page representing the last page in this paginator.
def last_page
@last_page ||= self[page_count]
end
alias last :last_page
# Returns the number of pages in this paginator.
def page_count
@page_count ||= @item_count.zero? ? 1 :
(q,r=@item_count.divmod(@items_per_page); r==0? q : q+1)
end
alias length :page_count
# Returns true if this paginator contains the page of index +number+.
def has_page_number?(number)
number >= 1 and number <= page_count
end
# Returns a new Page representing the page with the given index
# +number+.
def [](number)
@pages[number] ||= Page.new(self, number)
end
# Successively yields all the paginator's pages to the given block.
def each(&block)
page_count.times do |n|
yield self[n+1]
end
end
# A class representing a single page in a paginator.
class Page
include Comparable
# Creates a new Page for the given +paginator+ with the index
# +number+. If +number+ is not in the range of valid page numbers or
# is not a number at all, it defaults to 1.
def initialize(paginator, number)
@paginator = paginator
@number = number.to_i
@number = 1 unless @paginator.has_page_number? @number
end
attr_reader :paginator, :number
alias to_i :number
# Compares two Page objects and returns true when they represent the
# same page (i.e., their paginators are the same and they have the
# same page number).
def ==(page)
return false if page.nil?
@paginator == page.paginator and
@number == page.number
end
# Compares two Page objects and returns -1 if the left-hand page comes
# before the right-hand page, 0 if the pages are equal, and 1 if the
# left-hand page comes after the right-hand page. Raises ArgumentError
# if the pages do not belong to the same Paginator object.
def <=>(page)
raise ArgumentError unless @paginator == page.paginator
@number <=> page.number
end
# Returns the item offset for the first item in this page.
def offset
@paginator.items_per_page * (@number - 1)
end
# Returns the number of the first item displayed.
def first_item
offset + 1
end
# Returns the number of the last item displayed.
def last_item
[@paginator.items_per_page * @number, @paginator.item_count].min
end
# Returns true if this page is the first page in the paginator.
def first?
self == @paginator.first
end
# Returns true if this page is the last page in the paginator.
def last?
self == @paginator.last
end
# Returns a new Page object representing the page just before this
# page, or nil if this is the first page.
def previous
if first? then nil else @paginator[@number - 1] end
end
# Returns a new Page object representing the page just after this
# page, or nil if this is the last page.
def next
if last? then nil else @paginator[@number + 1] end
end
# Returns a new Window object for this page with the specified
# +padding+.
def window(padding=2)
Window.new(self, padding)
end
# Returns the limit/offset array for this page.
def to_sql
[@paginator.items_per_page, offset]
end
def to_param #:nodoc:
@number.to_s
end
end
# A class for representing ranges around a given page.
class Window
# Creates a new Window object for the given +page+ with the specified
# +padding+.
def initialize(page, padding=2)
@paginator = page.paginator
@page = page
self.padding = padding
end
attr_reader :paginator, :page
# Sets the window's padding (the number of pages on either side of the
# window page).
def padding=(padding)
@padding = padding < 0 ? 0 : padding
# Find the beginning and end pages of the window
@first = @paginator.has_page_number?(@page.number - @padding) ?
@paginator[@page.number - @padding] : @paginator.first
@last = @paginator.has_page_number?(@page.number + @padding) ?
@paginator[@page.number + @padding] : @paginator.last
end
attr_reader :padding, :first, :last
# Returns an array of Page objects in the current window.
def pages
(@first.number..@last.number).to_a.collect! {|n| @paginator[n]}
end
alias to_a :pages
end
end
end
end

View file

@ -0,0 +1,135 @@
module ActionView
module Helpers
# Provides methods for linking to ActionController::Pagination objects using a simple generator API. You can optionally
# also build your links manually using ActionView::Helpers::AssetHelper#link_to like so:
#
# <%= link_to "Previous page", { :page => paginator.current.previous } if paginator.current.previous %>
# <%= link_to "Next page", { :page => paginator.current.next } if paginator.current.next %>
module PaginationHelper
unless const_defined?(:DEFAULT_OPTIONS)
DEFAULT_OPTIONS = {
:name => :page,
:window_size => 2,
:always_show_anchors => true,
:link_to_current_page => false,
:params => {}
}
end
# Creates a basic HTML link bar for the given +paginator+. Links will be created
# for the next and/or previous page and for a number of other pages around the current
# pages position. The +html_options+ hash is passed to +link_to+ when the links are created.
#
# ==== Options
# <tt>:name</tt>:: the routing name for this paginator
# (defaults to +page+)
# <tt>:prefix</tt>:: prefix for pagination links
# (i.e. Older Pages: 1 2 3 4)
# <tt>:suffix</tt>:: suffix for pagination links
# (i.e. 1 2 3 4 <- Older Pages)
# <tt>:window_size</tt>:: the number of pages to show around
# the current page (defaults to <tt>2</tt>)
# <tt>:always_show_anchors</tt>:: whether or not the first and last
# pages should always be shown
# (defaults to +true+)
# <tt>:link_to_current_page</tt>:: whether or not the current page
# should be linked to (defaults to
# +false+)
# <tt>:params</tt>:: any additional routing parameters
# for page URLs
#
# ==== Examples
# # We'll assume we have a paginator setup in @person_pages...
#
# pagination_links(@person_pages)
# # => 1 <a href="/?page=2/">2</a> <a href="/?page=3/">3</a> ... <a href="/?page=10/">10</a>
#
# pagination_links(@person_pages, :link_to_current_page => true)
# # => <a href="/?page=1/">1</a> <a href="/?page=2/">2</a> <a href="/?page=3/">3</a> ... <a href="/?page=10/">10</a>
#
# pagination_links(@person_pages, :always_show_anchors => false)
# # => 1 <a href="/?page=2/">2</a> <a href="/?page=3/">3</a>
#
# pagination_links(@person_pages, :window_size => 1)
# # => 1 <a href="/?page=2/">2</a> ... <a href="/?page=10/">10</a>
#
# pagination_links(@person_pages, :params => { :viewer => "flash" })
# # => 1 <a href="/?page=2&amp;viewer=flash/">2</a> <a href="/?page=3&amp;viewer=flash/">3</a> ...
# # <a href="/?page=10&amp;viewer=flash/">10</a>
def pagination_links(paginator, options={}, html_options={})
name = options[:name] || DEFAULT_OPTIONS[:name]
params = (options[:params] || DEFAULT_OPTIONS[:params]).clone
prefix = options[:prefix] || ''
suffix = options[:suffix] || ''
pagination_links_each(paginator, options, prefix, suffix) do |n|
params[name] = n
link_to(n.to_s, params, html_options)
end
end
# Iterate through the pages of a given +paginator+, invoking a
# block for each page number that needs to be rendered as a link.
#
# ==== Options
# <tt>:window_size</tt>:: the number of pages to show around
# the current page (defaults to +2+)
# <tt>:always_show_anchors</tt>:: whether or not the first and last
# pages should always be shown
# (defaults to +true+)
# <tt>:link_to_current_page</tt>:: whether or not the current page
# should be linked to (defaults to
# +false+)
#
# ==== Example
# # Turn paginated links into an Ajax call
# pagination_links_each(paginator, page_options) do |link|
# options = { :url => {:action => 'list'}, :update => 'results' }
# html_options = { :href => url_for(:action => 'list') }
#
# link_to_remote(link.to_s, options, html_options)
# end
def pagination_links_each(paginator, options, prefix = nil, suffix = nil)
options = DEFAULT_OPTIONS.merge(options)
link_to_current_page = options[:link_to_current_page]
always_show_anchors = options[:always_show_anchors]
current_page = paginator.current_page
window_pages = current_page.window(options[:window_size]).pages
return if window_pages.length <= 1 unless link_to_current_page
first, last = paginator.first, paginator.last
html = ''
html << prefix if prefix
if always_show_anchors and not (wp_first = window_pages[0]).first?
html << yield(first.number)
html << ' ... ' if wp_first.number - first.number > 1
html << ' '
end
window_pages.each do |page|
if current_page == page && !link_to_current_page
html << page.number.to_s
else
html << yield(page.number)
end
html << ' '
end
if always_show_anchors and not (wp_last = window_pages[-1]).last?
html << ' ... ' if last.number - wp_last.number > 1
html << yield(last.number)
end
html << suffix if suffix
html
end
end # PaginationHelper
end # Helpers
end # ActionView

View file

@ -0,0 +1,160 @@
require 'abstract_unit'
require 'fixtures/article'
require 'fixtures/product'
require 'fixtures/tariff'
require 'fixtures/product_tariff'
require 'fixtures/suburb'
require 'fixtures/street'
require 'fixtures/restaurant'
require 'fixtures/dorm'
require 'fixtures/room'
require 'fixtures/room_attribute'
require 'fixtures/room_attribute_assignment'
require 'fixtures/student'
require 'fixtures/room_assignment'
require 'fixtures/user'
require 'fixtures/reading'
class TestAssociations < Test::Unit::TestCase
fixtures :articles, :products, :tariffs, :product_tariffs, :suburbs, :streets, :restaurants, :restaurants_suburbs,
:dorms, :rooms, :room_attributes, :room_attribute_assignments, :students, :room_assignments, :users, :readings
def test_has_many_through_with_conditions_when_through_association_is_not_composite
user = User.find(:first)
assert_equal 1, user.articles.find(:all, :conditions => ["articles.name = ?", "Article One"]).size
end
def test_has_many_through_with_conditions_when_through_association_is_composite
room = Room.find(:first)
assert_equal 0, room.room_attributes.find(:all, :conditions => ["room_attributes.name != ?", "keg"]).size
end
def test_has_many_through_on_custom_finder_when_through_association_is_composite_finder_when_through_association_is_not_composite
user = User.find(:first)
assert_equal 1, user.find_custom_articles.size
end
def test_has_many_through_on_custom_finder_when_through_association_is_composite
room = Room.find(:first)
assert_equal 0, room.find_custom_room_attributes.size
end
def test_count
assert_equal 2, Product.count(:include => :product_tariffs)
assert_equal 3, Tariff.count(:include => :product_tariffs)
assert_equal 2, Tariff.count(:group => :start_date).size
end
def test_products
assert_not_nil products(:first_product).product_tariffs
assert_equal 2, products(:first_product).product_tariffs.length
assert_not_nil products(:first_product).tariffs
assert_equal 2, products(:first_product).tariffs.length
assert_not_nil products(:first_product).product_tariff
end
def test_product_tariffs
assert_not_nil product_tariffs(:first_flat).product
assert_not_nil product_tariffs(:first_flat).tariff
assert_equal Product, product_tariffs(:first_flat).product.class
assert_equal Tariff, product_tariffs(:first_flat).tariff.class
end
def test_tariffs
assert_not_nil tariffs(:flat).product_tariffs
assert_equal 1, tariffs(:flat).product_tariffs.length
assert_not_nil tariffs(:flat).products
assert_equal 1, tariffs(:flat).products.length
assert_not_nil tariffs(:flat).product_tariff
end
# Its not generating the instances of associated classes from the rows
def test_find_includes_products
assert @products = Product.find(:all, :include => :product_tariffs)
assert_equal 2, @products.length
assert_not_nil @products.first.instance_variable_get('@product_tariffs'), '@product_tariffs not set; should be array'
assert_equal 3, @products.inject(0) {|sum, tariff| sum + tariff.instance_variable_get('@product_tariffs').length},
"Incorrect number of product_tariffs returned"
end
def test_find_includes_tariffs
assert @tariffs = Tariff.find(:all, :include => :product_tariffs)
assert_equal 3, @tariffs.length
assert_not_nil @tariffs.first.instance_variable_get('@product_tariffs'), '@product_tariffs not set; should be array'
assert_equal 3, @tariffs.inject(0) {|sum, tariff| sum + tariff.instance_variable_get('@product_tariffs').length},
"Incorrect number of product_tariffs returnedturned"
end
def test_find_includes_product
assert @product_tariffs = ProductTariff.find(:all, :include => :product)
assert_equal 3, @product_tariffs.length
assert_not_nil @product_tariffs.first.instance_variable_get('@product'), '@product not set'
end
def test_find_includes_comp_belongs_to_tariff
assert @product_tariffs = ProductTariff.find(:all, :include => :tariff)
assert_equal 3, @product_tariffs.length
assert_not_nil @product_tariffs.first.instance_variable_get('@tariff'), '@tariff not set'
end
def test_find_includes_extended
assert @products = Product.find(:all, :include => {:product_tariffs => :tariff})
assert_equal 3, @products.inject(0) {|sum, product| sum + product.instance_variable_get('@product_tariffs').length},
"Incorrect number of product_tariffs returned"
assert @tariffs = Tariff.find(:all, :include => {:product_tariffs => :product})
assert_equal 3, @tariffs.inject(0) {|sum, tariff| sum + tariff.instance_variable_get('@product_tariffs').length},
"Incorrect number of product_tariffs returned"
end
def test_join_where_clause
@product = Product.find(:first, :include => :product_tariffs)
where_clause = @product.product_tariffs.composite_where_clause(
['foo','bar'], [1,2]
)
assert_equal('(foo=1 AND bar=2)', where_clause)
end
def test_has_many_through
@products = Product.find(:all, :include => :tariffs)
assert_equal 3, @products.inject(0) {|sum, product| sum + product.instance_variable_get('@tariffs').length},
"Incorrect number of tariffs returned"
end
def test_has_many_through_when_not_pre_loaded
student = Student.find(:first)
rooms = student.rooms
assert_equal 1, rooms.size
assert_equal 1, rooms.first.dorm_id
assert_equal 1, rooms.first.room_id
end
def test_has_many_through_when_through_association_is_composite
dorm = Dorm.find(:first)
assert_equal 1, dorm.rooms.length
assert_equal 1, dorm.rooms.first.room_attributes.length
assert_equal 'keg', dorm.rooms.first.room_attributes.first.name
end
def test_associations_with_conditions
@suburb = Suburb.find([2, 1])
assert_equal 2, @suburb.streets.size
@suburb = Suburb.find([2, 1])
assert_equal 1, @suburb.first_streets.size
@suburb = Suburb.find([2, 1], :include => :streets)
assert_equal 2, @suburb.streets.size
@suburb = Suburb.find([2, 1], :include => :first_streets)
assert_equal 1, @suburb.first_streets.size
end
def test_has_and_belongs_to_many
@restaurant = Restaurant.find([1,1])
assert_equal 2, @restaurant.suburbs.size
@restaurant = Restaurant.find([1,1], :include => :suburbs)
assert_equal 2, @restaurant.suburbs.size
end
end

View file

@ -0,0 +1,22 @@
require 'abstract_unit'
require 'fixtures/kitchen_sink'
require 'fixtures/reference_type'
class TestAttributeMethods < Test::Unit::TestCase
fixtures :kitchen_sinks, :reference_types
def test_read_attribute_with_single_key
rt = ReferenceType.find(1)
assert_equal(1, rt.reference_type_id)
assert_equal('NAME_PREFIX', rt.type_label)
assert_equal('Name Prefix', rt.abbreviation)
end
def test_read_attribute_with_composite_keys
sink = KitchenSink.find(1,2)
assert_equal(1, sink.id_1)
assert_equal(2, sink.id_2)
assert_equal(Date.today, sink.a_date.to_date)
assert_equal('string', sink.a_string)
end
end

View file

@ -0,0 +1,84 @@
require 'abstract_unit'
require 'fixtures/reference_type'
require 'fixtures/reference_code'
require 'fixtures/product'
require 'fixtures/tariff'
require 'fixtures/product_tariff'
class TestAttributes < Test::Unit::TestCase
fixtures :reference_types, :reference_codes, :products, :tariffs, :product_tariffs
CLASSES = {
:single => {
:class => ReferenceType,
:primary_keys => :reference_type_id,
},
:dual => {
:class => ReferenceCode,
:primary_keys => [:reference_type_id, :reference_code],
},
}
def setup
self.class.classes = CLASSES
end
def test_brackets
testing_with do
@first.attributes.each_pair do |attr_name, value|
assert_equal value, @first[attr_name]
end
end
end
def test_brackets_primary_key
testing_with do
assert_equal @first.id, @first[@primary_keys], "[] failing for #{@klass}"
assert_equal @first.id, @first[@first.class.primary_key]
end
end
def test_brackets_assignment
testing_with do
@first.attributes.each_pair do |attr_name, value|
@first[attr_name]= !value.nil? ? value * 2 : '1'
assert_equal !value.nil? ? value * 2 : '1', @first[attr_name]
end
end
end
def test_brackets_foreign_key_assignment
@flat = Tariff.find(1, Date.today.to_s(:db))
@second_free = ProductTariff.find(2,2,Date.today.to_s(:db))
@second_free_fk = [:tariff_id, :tariff_start_date]
@second_free[key = @second_free_fk] = @flat.id
compare_indexes('@flat', @flat.class.primary_key, '@second_free', @second_free_fk)
assert_equal @flat.id, @second_free[key]
@second_free[key = @second_free_fk.to_composite_ids] = @flat.id
assert_equal @flat.id, @second_free[key]
compare_indexes('@flat', @flat.class.primary_key, '@second_free', @second_free_fk)
@second_free[key = @second_free_fk.to_composite_ids] = @flat.id.to_s
assert_equal @flat.id, @second_free[key]
compare_indexes('@flat', @flat.class.primary_key, '@second_free', @second_free_fk)
@second_free[key = @second_free_fk.to_composite_ids] = @flat.id.to_s
assert_equal @flat.id, @second_free[key]
compare_indexes('@flat', @flat.class.primary_key, '@second_free', @second_free_fk)
@second_free[key = @second_free_fk.to_composite_ids.to_s] = @flat.id
assert_equal @flat.id, @second_free[key]
compare_indexes('@flat', @flat.class.primary_key, '@second_free', @second_free_fk)
@second_free[key = @second_free_fk.to_composite_ids.to_s] = @flat.id.to_s
assert_equal @flat.id, @second_free[key]
compare_indexes('@flat', @flat.class.primary_key, '@second_free', @second_free_fk)
end
private
def compare_indexes(obj_name1, indexes1, obj_name2, indexes2)
obj1, obj2 = eval "[#{obj_name1}, #{obj_name2}]"
indexes1.length.times do |key_index|
assert_equal obj1[indexes1[key_index].to_s],
obj2[indexes2[key_index].to_s],
"#{obj_name1}[#{indexes1[key_index]}]=#{obj1[indexes1[key_index].to_s].inspect} != " +
"#{obj_name2}[#{indexes2[key_index]}]=#{obj2[indexes2[key_index].to_s].inspect}; " +
"#{obj_name2} = #{obj2.inspect}"
end
end
end

View file

@ -0,0 +1,34 @@
require 'abstract_unit'
require 'fixtures/reference_type'
require 'fixtures/reference_code'
class TestClone < Test::Unit::TestCase
fixtures :reference_types, :reference_codes
CLASSES = {
:single => {
:class => ReferenceType,
:primary_keys => :reference_type_id,
},
:dual => {
:class => ReferenceCode,
:primary_keys => [:reference_type_id, :reference_code],
},
}
def setup
self.class.classes = CLASSES
end
def test_truth
testing_with do
clone = @first.clone
assert_equal @first.attributes.block(@klass.primary_key), clone.attributes
if composite?
@klass.primary_key.each {|key| assert_nil clone[key], "Primary key '#{key}' should be nil"}
else
assert_nil clone[@klass.primary_key], "Sole primary key should be nil"
end
end
end
end

View file

@ -0,0 +1,51 @@
require 'abstract_unit'
require 'fixtures/reference_type'
require 'fixtures/reference_code'
class CompositeArraysTest < Test::Unit::TestCase
def test_new_primary_keys
keys = CompositePrimaryKeys::CompositeKeys.new
assert_not_nil keys
assert_equal '', keys.to_s
assert_equal '', "#{keys}"
end
def test_initialize_primary_keys
keys = CompositePrimaryKeys::CompositeKeys.new([1,2,3])
assert_not_nil keys
assert_equal '1,2,3', keys.to_s
assert_equal '1,2,3', "#{keys}"
end
def test_to_composite_keys
keys = [1,2,3].to_composite_keys
assert_equal CompositePrimaryKeys::CompositeKeys, keys.class
assert_equal '1,2,3', keys.to_s
end
def test_new_ids
keys = CompositePrimaryKeys::CompositeIds.new
assert_not_nil keys
assert_equal '', keys.to_s
assert_equal '', "#{keys}"
end
def test_initialize_ids
keys = CompositePrimaryKeys::CompositeIds.new([1,2,3])
assert_not_nil keys
assert_equal '1,2,3', keys.to_s
assert_equal '1,2,3', "#{keys}"
end
def test_to_composite_ids
keys = [1,2,3].to_composite_ids
assert_equal CompositePrimaryKeys::CompositeIds, keys.class
assert_equal '1,2,3', keys.to_s
end
def test_flatten
keys = [CompositePrimaryKeys::CompositeIds.new([1,2,3]), CompositePrimaryKeys::CompositeIds.new([4,5,6])]
assert_equal 6, keys.flatten.size
end
end

View file

@ -0,0 +1,68 @@
require 'abstract_unit'
require 'fixtures/reference_type'
require 'fixtures/reference_code'
require 'fixtures/street'
require 'fixtures/suburb'
class TestCreate < Test::Unit::TestCase
fixtures :reference_types, :reference_codes, :streets, :suburbs
CLASSES = {
:single => {
:class => ReferenceType,
:primary_keys => :reference_type_id,
:create => {:reference_type_id => 10, :type_label => 'NEW_TYPE', :abbreviation => 'New Type'}
},
:dual => {
:class => ReferenceCode,
:primary_keys => [:reference_type_id, :reference_code],
:create => {:reference_type_id => 1, :reference_code => 20, :code_label => 'NEW_CODE', :abbreviation => 'New Code'}
},
}
def setup
self.class.classes = CLASSES
end
def test_setup
testing_with do
assert_not_nil @klass_info[:create]
end
end
def test_create
testing_with do
assert new_obj = @klass.create(@klass_info[:create])
assert !new_obj.new_record?
end
end
def test_create_no_id
testing_with do
begin
@obj = @klass.create(@klass_info[:create].block(@klass.primary_key))
@successful = !composite?
rescue CompositePrimaryKeys::ActiveRecord::CompositeKeyError
@successful = false
rescue
flunk "Incorrect exception raised: #{$!}, #{$!.class}"
end
assert_equal composite?, !@successful, "Create should have failed for composites; #{@obj.inspect}"
end
end
def test_create_on_association
suburb = Suburb.find(:first)
suburb.streets.create(:name => "my street")
street = Street.find_by_name('my street')
assert_equal(suburb.city_id, street.city_id)
assert_equal(suburb.suburb_id, street.suburb_id)
end
def test_create_on_association_when_belongs_to_is_single_key
rt = ReferenceType.find(:first)
rt.reference_codes.create(:reference_code => 4321, :code_label => 'foo', :abbreviation => 'bar')
rc = ReferenceCode.find_by_reference_code(4321)
assert_equal(rc.reference_type_id, rt.reference_type_id)
end
end

View file

@ -0,0 +1,96 @@
require 'abstract_unit'
require 'fixtures/reference_type'
require 'fixtures/reference_code'
require 'fixtures/department'
require 'fixtures/employee'
class TestDelete < Test::Unit::TestCase
fixtures :reference_types, :reference_codes, :departments, :employees
CLASSES = {
:single => {
:class => ReferenceType,
:primary_keys => :reference_type_id,
},
:dual => {
:class => ReferenceCode,
:primary_keys => [:reference_type_id, :reference_code],
},
}
def setup
self.class.classes = CLASSES
end
def test_destroy_one
testing_with do
#assert @first.destroy
assert true
end
end
def test_destroy_one_via_class
testing_with do
assert @klass.destroy(*@first.id)
end
end
def test_destroy_one_alone_via_class
testing_with do
assert @klass.destroy(@first.id)
end
end
def test_delete_one
testing_with do
assert @klass.delete(*@first.id) if composite?
end
end
def test_delete_one_alone
testing_with do
assert @klass.delete(@first.id)
end
end
def test_delete_many
testing_with do
to_delete = @klass.find(:all)[0..1]
assert_equal 2, to_delete.length
end
end
def test_delete_all
testing_with do
@klass.delete_all
end
end
def test_clear_association
department = Department.find(1,1)
assert_equal 2, department.employees.size, "Before clear employee count should be 2."
department.employees.clear
assert_equal 0, department.employees.size, "After clear employee count should be 0."
department.reload
assert_equal 0, department.employees.size, "After clear and a reload from DB employee count should be 0."
end
def test_delete_association
department = Department.find(1,1)
assert_equal 2, department.employees.size , "Before delete employee count should be 2."
first_employee = department.employees[0]
department.employees.delete(first_employee)
assert_equal 1, department.employees.size, "After delete employee count should be 1."
department.reload
assert_equal 1, department.employees.size, "After delete and a reload from DB employee count should be 1."
end
def test_delete_records_for_has_many_association_with_composite_primary_key
reference_type = ReferenceType.find(1)
codes_to_delete = reference_type.reference_codes[0..1]
assert_equal 3, reference_type.reference_codes.size, "Before deleting records reference_code count should be 3."
reference_type.reference_codes.delete_records(codes_to_delete)
reference_type.reload
assert_equal 1, reference_type.reference_codes.size, "After deleting 2 records and a reload from DB reference_code count should be 1."
end
end

View file

@ -0,0 +1,28 @@
require 'abstract_unit'
require 'fixtures/reference_type'
require 'fixtures/reference_code'
class TestDummy < Test::Unit::TestCase
fixtures :reference_types, :reference_codes
classes = {
:single => {
:class => ReferenceType,
:primary_keys => :reference_type_id,
},
:dual => {
:class => ReferenceCode,
:primary_keys => [:reference_type_id, :reference_code],
},
}
def setup
self.class.classes = classes
end
def test_truth
testing_with do
assert true
end
end
end

View file

@ -0,0 +1,29 @@
require 'abstract_unit'
require 'fixtures/article'
require 'fixtures/department'
class TestExists < Test::Unit::TestCase
fixtures :articles, :departments
def test_single_key_exists_giving_id
assert Article.exists?(1)
end
def test_single_key_exists_giving_condition
assert Article.exists?(['name = ?', 'Article One'])
end
def test_composite_key_exists_giving_ids_as_string
assert Department.exists?('1,1,')
end
def test_composite_key_exists_giving_ids_as_array
assert Department.exists?([1,1])
assert_equal(false, Department.exists?([1111,1111]))
end
def test_composite_key_exists_giving_ids_as_condition
assert Department.exists?(['department_id = ? and location_id = ?', 1, 1])
assert_equal(false, Department.exists?(['department_id = ? and location_id = ?', 11111, 11111]))
end
end

View file

@ -0,0 +1,73 @@
require 'abstract_unit'
require 'fixtures/reference_type'
require 'fixtures/reference_code'
# Testing the find action on composite ActiveRecords with two primary keys
class TestFind < Test::Unit::TestCase
fixtures :reference_types, :reference_codes
CLASSES = {
:single => {
:class => ReferenceType,
:primary_keys => [:reference_type_id],
},
:dual => {
:class => ReferenceCode,
:primary_keys => [:reference_type_id, :reference_code],
},
:dual_strs => {
:class => ReferenceCode,
:primary_keys => ['reference_type_id', 'reference_code'],
},
}
def setup
self.class.classes = CLASSES
end
def test_find_first
testing_with do
obj = @klass.find(:first)
assert obj
assert_equal @klass, obj.class
end
end
def test_find
testing_with do
found = @klass.find(*first_id) # e.g. find(1,1) or find 1,1
assert found
assert_equal @klass, found.class
assert_equal found, @klass.find(found.id)
assert_equal found, @klass.find(found.to_param)
end
end
def test_find_composite_ids
testing_with do
found = @klass.find(first_id) # e.g. find([1,1].to_composite_ids)
assert found
assert_equal @klass, found.class
assert_equal found, @klass.find(found.id)
assert_equal found, @klass.find(found.to_param)
end
end
def test_to_param
testing_with do
assert_equal first_id_str, @first.to_param.to_s
end
end
def things_to_look_at
testing_with do
assert_equal found, @klass.find(found.id.to_s) # fails for 2+ keys
end
end
def test_not_found
assert_raise(::ActiveRecord::RecordNotFound) do
ReferenceCode.send :find, '999,999'
end
end
end

View file

@ -0,0 +1,97 @@
require 'abstract_unit'
require 'fixtures/reference_type'
require 'fixtures/reference_code'
class TestIds < Test::Unit::TestCase
fixtures :reference_types, :reference_codes
CLASSES = {
:single => {
:class => ReferenceType,
:primary_keys => [:reference_type_id],
},
:dual => {
:class => ReferenceCode,
:primary_keys => [:reference_type_id, :reference_code],
},
:dual_strs => {
:class => ReferenceCode,
:primary_keys => ['reference_type_id', 'reference_code'],
},
}
def setup
self.class.classes = CLASSES
end
def test_id
testing_with do
assert_equal @first.id, @first.ids if composite?
end
end
def test_id_to_s
testing_with do
assert_equal first_id_str, @first.id.to_s
assert_equal first_id_str, "#{@first.id}"
end
end
def test_ids_to_s
testing_with do
order = @klass.primary_key.is_a?(String) ? @klass.primary_key : @klass.primary_key.join(',')
to_test = @klass.find(:all, :order => order)[0..1].map(&:id)
assert_equal '(1,1),(1,2)', @klass.ids_to_s(to_test) if @key_test == :dual
assert_equal '1,1;1,2', @klass.ids_to_s(to_test, ',', ';', '', '') if @key_test == :dual
end
end
def test_composite_where_clause
testing_with do
where = 'reference_codes.reference_type_id=1 AND reference_codes.reference_code=2) OR (reference_codes.reference_type_id=2 AND reference_codes.reference_code=2'
assert_equal(where, @klass.composite_where_clause([[1, 2], [2, 2]])) if @key_test == :dual
end
end
def test_set_ids_string
testing_with do
array = @primary_keys.collect {|key| 5}
expected = composite? ? array.to_composite_keys : array.first
@first.id = expected.to_s
assert_equal expected, @first.id
end
end
def test_set_ids_array
testing_with do
array = @primary_keys.collect {|key| 5}
expected = composite? ? array.to_composite_keys : array.first
@first.id = expected
assert_equal expected, @first.id
end
end
def test_set_ids_comp
testing_with do
array = @primary_keys.collect {|key| 5}
expected = composite? ? array.to_composite_keys : array.first
@first.id = expected
assert_equal expected, @first.id
end
end
def test_primary_keys
testing_with do
if composite?
assert_not_nil @klass.primary_keys
assert_equal @primary_keys.map {|key| key.to_sym}, @klass.primary_keys
assert_equal @klass.primary_keys, @klass.primary_key
else
assert_not_nil @klass.primary_key
assert_equal @primary_keys, [@klass.primary_key.to_sym]
end
assert_equal @primary_keys.join(','), @klass.primary_key.to_s
# Need a :primary_keys should be Array with to_s overridden
end
end
end

View file

@ -0,0 +1,39 @@
require 'abstract_unit'
require 'fixtures/reference_type'
require 'fixtures/reference_code'
class TestMiscellaneous < Test::Unit::TestCase
fixtures :reference_types, :reference_codes, :products
CLASSES = {
:single => {
:class => ReferenceType,
:primary_keys => :reference_type_id,
},
:dual => {
:class => ReferenceCode,
:primary_keys => [:reference_type_id, :reference_code],
},
}
def setup
self.class.classes = CLASSES
end
def test_composite_class
testing_with do
assert_equal composite?, @klass.composite?
end
end
def test_composite_instance
testing_with do
assert_equal composite?, @first.composite?
end
end
def test_count
assert_equal 2, Product.count
end
end

View file

@ -0,0 +1,38 @@
require 'abstract_unit'
require 'fixtures/reference_type'
require 'fixtures/reference_code'
require 'plugins/pagination'
class TestPagination < Test::Unit::TestCase
fixtures :reference_types, :reference_codes
include ActionController::Pagination
DEFAULT_PAGE_SIZE = 2
attr_accessor :params
CLASSES = {
:single => {
:class => ReferenceType,
:primary_keys => :reference_type_id,
:table => :reference_types,
},
:dual => {
:class => ReferenceCode,
:primary_keys => [:reference_type_id, :reference_code],
:table => :reference_codes,
},
}
def setup
self.class.classes = CLASSES
@params = {}
end
def test_paginate_all
testing_with do
@object_pages, @objects = paginate @klass_info[:table], :per_page => DEFAULT_PAGE_SIZE
assert_equal 2, @objects.length, "Each page should have #{DEFAULT_PAGE_SIZE} items"
end
end
end

View file

@ -0,0 +1,31 @@
require 'abstract_unit'
require 'fixtures/comment'
require 'fixtures/user'
require 'fixtures/employee'
require 'fixtures/hack'
class TestPolymorphic < Test::Unit::TestCase
fixtures :users, :employees, :comments, :hacks
def test_polymorphic_has_many
comments = Hack.find('andrew').comments
assert_equal 'andrew', comments[0].person_id
end
def test_polymorphic_has_one
first_comment = Hack.find('andrew').first_comment
assert_equal 'andrew', first_comment.person_id
end
def test_has_many_through
user = users(:santiago)
article_names = user.articles.collect { |a| a.name }.sort
assert_equal ['Article One', 'Article Two'], article_names
end
def test_polymorphic_has_many_through
user = users(:santiago)
assert_equal ['andrew'], user.hacks.collect { |a| a.name }.sort
end
end

View file

@ -0,0 +1,27 @@
# Test cases devised by Santiago that broke the Composite Primary Keys
# code at one point in time. But no more!!!
require 'abstract_unit'
require 'fixtures/user'
require 'fixtures/article'
require 'fixtures/reading'
class TestSantiago < Test::Unit::TestCase
fixtures :suburbs, :streets, :users, :articles, :readings
def test_normal_and_composite_associations
assert_not_nil @suburb = Suburb.find(1,1)
assert_equal 1, @suburb.streets.length
assert_not_nil @street = Street.find(1)
assert_not_nil @street.suburb
end
def test_single_keys
@santiago = User.find(1)
assert_not_nil @santiago.articles
assert_equal 2, @santiago.articles.length
assert_not_nil @santiago.readings
assert_equal 2, @santiago.readings.length
end
end

View file

@ -0,0 +1,26 @@
require 'abstract_unit'
require 'fixtures/user'
require 'fixtures/group'
require 'fixtures/membership_status'
require 'fixtures/membership'
class TestTutorialExample < Test::Unit::TestCase
fixtures :users, :groups, :memberships, :membership_statuses
def test_membership
assert(membership = Membership.find(1,1), "Cannot find a membership")
assert(membership.user)
assert(membership.group)
end
def test_status
assert(membership = Membership.find(1,1), "Cannot find a membership")
assert(statuses = membership.statuses, "No has_many association to status")
assert_equal(membership, statuses.first.membership)
end
def test_count
assert(membership = Membership.find(1,1), "Cannot find a membership")
assert_equal(1, membership.statuses.count)
end
end

View file

@ -0,0 +1,40 @@
require 'abstract_unit'
require 'fixtures/reference_type'
require 'fixtures/reference_code'
class TestUpdate < Test::Unit::TestCase
fixtures :reference_types, :reference_codes
CLASSES = {
:single => {
:class => ReferenceType,
:primary_keys => :reference_type_id,
:update => { :description => 'RT Desc' },
},
:dual => {
:class => ReferenceCode,
:primary_keys => [:reference_type_id, :reference_code],
:update => { :description => 'RT Desc' },
},
}
def setup
self.class.classes = CLASSES
end
def test_setup
testing_with do
assert_not_nil @klass_info[:update]
end
end
def test_update_attributes
testing_with do
assert @first.update_attributes(@klass_info[:update])
assert @first.reload
@klass_info[:update].each_pair do |attr_name, new_value|
assert_equal new_value, @first[attr_name], "Attribute #{attr_name} is incorrect"
end
end
end
end