ensured_schema 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/Gemfile.lock +23 -0
- data/Rakefile +19 -0
- data/ensured_schema.gemspec +4 -0
- data/lib/ensured_schema/column.rb +9 -0
- data/lib/ensured_schema/ensured_table.rb +53 -0
- data/lib/ensured_schema/mysql_column.rb +17 -0
- data/lib/ensured_schema/schema.rb +7 -0
- data/lib/ensured_schema/schema_statements.rb +69 -0
- data/lib/ensured_schema/version.rb +1 -1
- data/lib/ensured_schema.rb +5 -155
- data/test/cases/ensured_schema_test.rb +206 -0
- data/test/cases/helper.rb +70 -0
- data/test/cases/migration_test.rb +1523 -0
- data/test/cases/repair_helper.rb +50 -0
- data/test/config.rb +5 -0
- data/test/connections/native_mysql/connection.rb +25 -0
- data/test/migrations/broken/100_migration_that_raises_exception.rb +10 -0
- data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -0
- data/test/migrations/duplicate/1_people_have_last_names.rb +9 -0
- data/test/migrations/duplicate/2_we_need_reminders.rb +12 -0
- data/test/migrations/duplicate/3_foo.rb +7 -0
- data/test/migrations/duplicate/3_innocent_jointable.rb +12 -0
- data/test/migrations/duplicate_names/20080507052938_chunky.rb +7 -0
- data/test/migrations/duplicate_names/20080507053028_chunky.rb +7 -0
- data/test/migrations/interleaved/pass_1/3_innocent_jointable.rb +12 -0
- data/test/migrations/interleaved/pass_2/1_people_have_last_names.rb +9 -0
- data/test/migrations/interleaved/pass_2/3_innocent_jointable.rb +12 -0
- data/test/migrations/interleaved/pass_3/1_people_have_last_names.rb +9 -0
- data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +8 -0
- data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +12 -0
- data/test/migrations/missing/1000_people_have_middle_names.rb +9 -0
- data/test/migrations/missing/1_people_have_last_names.rb +9 -0
- data/test/migrations/missing/3_we_need_reminders.rb +12 -0
- data/test/migrations/missing/4_innocent_jointable.rb +12 -0
- data/test/migrations/valid/1_people_have_last_names.rb +9 -0
- data/test/migrations/valid/2_we_need_reminders.rb +12 -0
- data/test/migrations/valid/3_innocent_jointable.rb +12 -0
- data/test/models/author.rb +146 -0
- data/test/models/auto_id.rb +4 -0
- data/test/models/binary.rb +2 -0
- data/test/models/bird.rb +3 -0
- data/test/models/book.rb +4 -0
- data/test/models/categorization.rb +5 -0
- data/test/models/category.rb +34 -0
- data/test/models/citation.rb +6 -0
- data/test/models/club.rb +13 -0
- data/test/models/column_name.rb +3 -0
- data/test/models/comment.rb +29 -0
- data/test/models/company.rb +171 -0
- data/test/models/company_in_module.rb +61 -0
- data/test/models/computer.rb +3 -0
- data/test/models/contact.rb +16 -0
- data/test/models/contract.rb +5 -0
- data/test/models/course.rb +3 -0
- data/test/models/customer.rb +73 -0
- data/test/models/default.rb +2 -0
- data/test/models/developer.rb +101 -0
- data/test/models/edge.rb +5 -0
- data/test/models/entrant.rb +3 -0
- data/test/models/essay.rb +3 -0
- data/test/models/event.rb +3 -0
- data/test/models/guid.rb +2 -0
- data/test/models/item.rb +7 -0
- data/test/models/job.rb +5 -0
- data/test/models/joke.rb +3 -0
- data/test/models/keyboard.rb +3 -0
- data/test/models/legacy_thing.rb +3 -0
- data/test/models/matey.rb +4 -0
- data/test/models/member.rb +12 -0
- data/test/models/member_detail.rb +5 -0
- data/test/models/member_type.rb +3 -0
- data/test/models/membership.rb +9 -0
- data/test/models/minimalistic.rb +2 -0
- data/test/models/mixed_case_monkey.rb +3 -0
- data/test/models/movie.rb +5 -0
- data/test/models/order.rb +4 -0
- data/test/models/organization.rb +6 -0
- data/test/models/owner.rb +5 -0
- data/test/models/parrot.rb +16 -0
- data/test/models/person.rb +16 -0
- data/test/models/pet.rb +5 -0
- data/test/models/pirate.rb +70 -0
- data/test/models/post.rb +100 -0
- data/test/models/price_estimate.rb +3 -0
- data/test/models/project.rb +30 -0
- data/test/models/reader.rb +4 -0
- data/test/models/reference.rb +4 -0
- data/test/models/reply.rb +46 -0
- data/test/models/ship.rb +10 -0
- data/test/models/ship_part.rb +5 -0
- data/test/models/sponsor.rb +4 -0
- data/test/models/subject.rb +4 -0
- data/test/models/subscriber.rb +8 -0
- data/test/models/subscription.rb +4 -0
- data/test/models/tag.rb +7 -0
- data/test/models/tagging.rb +10 -0
- data/test/models/task.rb +3 -0
- data/test/models/topic.rb +80 -0
- data/test/models/toy.rb +6 -0
- data/test/models/treasure.rb +8 -0
- data/test/models/vertex.rb +9 -0
- data/test/models/warehouse_thing.rb +5 -0
- data/test/schema/mysql_specific_schema.rb +24 -0
- data/test/schema/postgresql_specific_schema.rb +114 -0
- data/test/schema/schema.rb +493 -0
- data/test/schema/schema2.rb +6 -0
- data/test/schema/sqlite_specific_schema.rb +25 -0
- metadata +237 -7
@@ -0,0 +1,70 @@
|
|
1
|
+
class Pirate < ActiveRecord::Base
|
2
|
+
belongs_to :parrot, :validate => true
|
3
|
+
belongs_to :non_validated_parrot, :class_name => 'Parrot'
|
4
|
+
has_and_belongs_to_many :parrots, :validate => true
|
5
|
+
has_and_belongs_to_many :non_validated_parrots, :class_name => 'Parrot'
|
6
|
+
has_and_belongs_to_many :parrots_with_method_callbacks, :class_name => "Parrot",
|
7
|
+
:before_add => :log_before_add,
|
8
|
+
:after_add => :log_after_add,
|
9
|
+
:before_remove => :log_before_remove,
|
10
|
+
:after_remove => :log_after_remove
|
11
|
+
has_and_belongs_to_many :parrots_with_proc_callbacks, :class_name => "Parrot",
|
12
|
+
:before_add => proc {|p,pa| p.ship_log << "before_adding_proc_parrot_#{pa.id || '<new>'}"},
|
13
|
+
:after_add => proc {|p,pa| p.ship_log << "after_adding_proc_parrot_#{pa.id || '<new>'}"},
|
14
|
+
:before_remove => proc {|p,pa| p.ship_log << "before_removing_proc_parrot_#{pa.id}"},
|
15
|
+
:after_remove => proc {|p,pa| p.ship_log << "after_removing_proc_parrot_#{pa.id}"}
|
16
|
+
|
17
|
+
has_many :treasures, :as => :looter
|
18
|
+
has_many :treasure_estimates, :through => :treasures, :source => :price_estimates
|
19
|
+
|
20
|
+
# These both have :autosave enabled because accepts_nested_attributes_for is used on them.
|
21
|
+
has_one :ship
|
22
|
+
has_one :non_validated_ship, :class_name => 'Ship'
|
23
|
+
has_many :birds
|
24
|
+
has_many :birds_with_method_callbacks, :class_name => "Bird",
|
25
|
+
:before_add => :log_before_add,
|
26
|
+
:after_add => :log_after_add,
|
27
|
+
:before_remove => :log_before_remove,
|
28
|
+
:after_remove => :log_after_remove
|
29
|
+
has_many :birds_with_proc_callbacks, :class_name => "Bird",
|
30
|
+
:before_add => proc {|p,b| p.ship_log << "before_adding_proc_bird_#{b.id || '<new>'}"},
|
31
|
+
:after_add => proc {|p,b| p.ship_log << "after_adding_proc_bird_#{b.id || '<new>'}"},
|
32
|
+
:before_remove => proc {|p,b| p.ship_log << "before_removing_proc_bird_#{b.id}"},
|
33
|
+
:after_remove => proc {|p,b| p.ship_log << "after_removing_proc_bird_#{b.id}"}
|
34
|
+
|
35
|
+
accepts_nested_attributes_for :parrots, :birds, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
|
36
|
+
accepts_nested_attributes_for :ship, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
|
37
|
+
accepts_nested_attributes_for :parrots_with_method_callbacks, :parrots_with_proc_callbacks,
|
38
|
+
:birds_with_method_callbacks, :birds_with_proc_callbacks, :allow_destroy => true
|
39
|
+
|
40
|
+
validates_presence_of :catchphrase
|
41
|
+
|
42
|
+
def ship_log
|
43
|
+
@ship_log ||= []
|
44
|
+
end
|
45
|
+
|
46
|
+
def reject_empty_ships_on_create(attributes)
|
47
|
+
attributes.delete('_reject_me_if_new').present? && new_record?
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
def log_before_add(record)
|
52
|
+
log(record, "before_adding_method")
|
53
|
+
end
|
54
|
+
|
55
|
+
def log_after_add(record)
|
56
|
+
log(record, "after_adding_method")
|
57
|
+
end
|
58
|
+
|
59
|
+
def log_before_remove(record)
|
60
|
+
log(record, "before_removing_method")
|
61
|
+
end
|
62
|
+
|
63
|
+
def log_after_remove(record)
|
64
|
+
log(record, "after_removing_method")
|
65
|
+
end
|
66
|
+
|
67
|
+
def log(record, callback)
|
68
|
+
ship_log << "#{callback}_#{record.class.name.downcase}_#{record.id || '<new>'}"
|
69
|
+
end
|
70
|
+
end
|
data/test/models/post.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
class Post < ActiveRecord::Base
|
2
|
+
named_scope :containing_the_letter_a, :conditions => "body LIKE '%a%'"
|
3
|
+
named_scope :ranked_by_comments, :order => "comments_count DESC"
|
4
|
+
named_scope :limit, lambda {|limit| {:limit => limit} }
|
5
|
+
named_scope :with_authors_at_address, lambda { |address| {
|
6
|
+
:conditions => [ 'authors.author_address_id = ?', address.id ],
|
7
|
+
:joins => 'JOIN authors ON authors.id = posts.author_id'
|
8
|
+
}
|
9
|
+
}
|
10
|
+
|
11
|
+
belongs_to :author do
|
12
|
+
def greeting
|
13
|
+
"hello"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
belongs_to :author_with_posts, :class_name => "Author", :foreign_key => :author_id, :include => :posts
|
18
|
+
belongs_to :author_with_address, :class_name => "Author", :foreign_key => :author_id, :include => :author_address
|
19
|
+
|
20
|
+
has_one :last_comment, :class_name => 'Comment', :order => 'id desc'
|
21
|
+
|
22
|
+
named_scope :with_special_comments, :joins => :comments, :conditions => {:comments => {:type => 'SpecialComment'} }
|
23
|
+
named_scope :with_very_special_comments, :joins => :comments, :conditions => {:comments => {:type => 'VerySpecialComment'} }
|
24
|
+
named_scope :with_post, lambda {|post_id|
|
25
|
+
{ :joins => :comments, :conditions => {:comments => {:post_id => post_id} } }
|
26
|
+
}
|
27
|
+
|
28
|
+
has_many :comments, :order => "body" do
|
29
|
+
def find_most_recent
|
30
|
+
find(:first, :order => "id DESC")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
has_many :author_favorites, :through => :author
|
35
|
+
|
36
|
+
has_many :comments_with_interpolated_conditions, :class_name => 'Comment',
|
37
|
+
:conditions => ['#{"#{aliased_table_name}." rescue ""}body = ?', 'Thank you for the welcome']
|
38
|
+
|
39
|
+
has_one :very_special_comment
|
40
|
+
has_one :very_special_comment_with_post, :class_name => "VerySpecialComment", :include => :post
|
41
|
+
has_many :special_comments
|
42
|
+
has_many :nonexistant_comments, :class_name => 'Comment', :conditions => 'comments.id < 0'
|
43
|
+
|
44
|
+
has_and_belongs_to_many :categories
|
45
|
+
has_and_belongs_to_many :special_categories, :join_table => "categories_posts", :association_foreign_key => 'category_id'
|
46
|
+
|
47
|
+
has_many :taggings, :as => :taggable
|
48
|
+
has_many :tags, :through => :taggings do
|
49
|
+
def add_joins_and_select
|
50
|
+
find :all, :select => 'tags.*, authors.id as author_id', :include => false,
|
51
|
+
:joins => 'left outer join posts on taggings.taggable_id = posts.id left outer join authors on posts.author_id = authors.id'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
has_many :funky_tags, :through => :taggings, :source => :tag
|
56
|
+
has_many :super_tags, :through => :taggings
|
57
|
+
has_one :tagging, :as => :taggable
|
58
|
+
|
59
|
+
has_many :invalid_taggings, :as => :taggable, :class_name => "Tagging", :conditions => 'taggings.id < 0'
|
60
|
+
has_many :invalid_tags, :through => :invalid_taggings, :source => :tag
|
61
|
+
|
62
|
+
has_many :categorizations, :foreign_key => :category_id
|
63
|
+
has_many :authors, :through => :categorizations
|
64
|
+
|
65
|
+
has_many :readers
|
66
|
+
has_many :people, :through => :readers
|
67
|
+
has_many :people_with_callbacks, :source=>:person, :through => :readers,
|
68
|
+
:before_add => lambda {|owner, reader| log(:added, :before, reader.first_name) },
|
69
|
+
:after_add => lambda {|owner, reader| log(:added, :after, reader.first_name) },
|
70
|
+
:before_remove => lambda {|owner, reader| log(:removed, :before, reader.first_name) },
|
71
|
+
:after_remove => lambda {|owner, reader| log(:removed, :after, reader.first_name) }
|
72
|
+
|
73
|
+
def self.top(limit)
|
74
|
+
ranked_by_comments.limit(limit)
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.reset_log
|
78
|
+
@log = []
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.log(message=nil, side=nil, new_record=nil)
|
82
|
+
return @log if message.nil?
|
83
|
+
@log << [message, side, new_record]
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.what_are_you
|
87
|
+
'a post...'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class SpecialPost < Post; end
|
92
|
+
|
93
|
+
class StiPost < Post
|
94
|
+
self.abstract_class = true
|
95
|
+
has_one :special_comment, :class_name => "SpecialComment"
|
96
|
+
end
|
97
|
+
|
98
|
+
class SubStiPost < StiPost
|
99
|
+
self.table_name = Post.table_name
|
100
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Project < ActiveRecord::Base
|
2
|
+
has_and_belongs_to_many :developers, :uniq => true, :order => 'developers.name desc, developers.id desc'
|
3
|
+
has_and_belongs_to_many :readonly_developers, :class_name => "Developer", :readonly => true
|
4
|
+
has_and_belongs_to_many :selected_developers, :class_name => "Developer", :select => "developers.*", :uniq => true
|
5
|
+
has_and_belongs_to_many :non_unique_developers, :order => 'developers.name desc, developers.id desc', :class_name => 'Developer'
|
6
|
+
has_and_belongs_to_many :limited_developers, :class_name => "Developer", :limit => 1
|
7
|
+
has_and_belongs_to_many :developers_named_david, :class_name => "Developer", :conditions => "name = 'David'", :uniq => true
|
8
|
+
has_and_belongs_to_many :developers_named_david_with_hash_conditions, :class_name => "Developer", :conditions => { :name => 'David' }, :uniq => true
|
9
|
+
has_and_belongs_to_many :salaried_developers, :class_name => "Developer", :conditions => "salary > 0"
|
10
|
+
has_and_belongs_to_many :developers_with_finder_sql, :class_name => "Developer", :finder_sql => 'SELECT t.*, j.* FROM developers_projects j, developers t WHERE t.id = j.developer_id AND j.project_id = #{id} ORDER BY t.id'
|
11
|
+
has_and_belongs_to_many :developers_by_sql, :class_name => "Developer", :delete_sql => "DELETE FROM developers_projects WHERE project_id = \#{id} AND developer_id = \#{record.id}"
|
12
|
+
has_and_belongs_to_many :developers_with_callbacks, :class_name => "Developer", :before_add => Proc.new {|o, r| o.developers_log << "before_adding#{r.id || '<new>'}"},
|
13
|
+
:after_add => Proc.new {|o, r| o.developers_log << "after_adding#{r.id || '<new>'}"},
|
14
|
+
:before_remove => Proc.new {|o, r| o.developers_log << "before_removing#{r.id}"},
|
15
|
+
:after_remove => Proc.new {|o, r| o.developers_log << "after_removing#{r.id}"}
|
16
|
+
has_and_belongs_to_many :well_payed_salary_groups, :class_name => "Developer", :group => "developers.salary", :having => "SUM(salary) > 10000", :select => "SUM(salary) as salary"
|
17
|
+
|
18
|
+
attr_accessor :developers_log
|
19
|
+
|
20
|
+
def after_initialize
|
21
|
+
@developers_log = []
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
class SpecialProject < Project
|
27
|
+
def hello_world
|
28
|
+
"hello there!"
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'models/topic'
|
2
|
+
|
3
|
+
class Reply < Topic
|
4
|
+
named_scope :base
|
5
|
+
|
6
|
+
belongs_to :topic, :foreign_key => "parent_id", :counter_cache => true
|
7
|
+
belongs_to :topic_with_primary_key, :class_name => "Topic", :primary_key => "title", :foreign_key => "parent_title", :counter_cache => "replies_count"
|
8
|
+
has_many :replies, :class_name => "SillyReply", :dependent => :destroy, :foreign_key => "parent_id"
|
9
|
+
|
10
|
+
validate :errors_on_empty_content
|
11
|
+
validate_on_create :title_is_wrong_create
|
12
|
+
|
13
|
+
attr_accessible :title, :author_name, :author_email_address, :written_on, :content, :last_read, :parent_title
|
14
|
+
|
15
|
+
def validate
|
16
|
+
errors.add("title", "Empty") unless attribute_present? "title"
|
17
|
+
end
|
18
|
+
|
19
|
+
def errors_on_empty_content
|
20
|
+
errors.add("content", "Empty") unless attribute_present? "content"
|
21
|
+
end
|
22
|
+
|
23
|
+
def validate_on_create
|
24
|
+
if attribute_present?("title") && attribute_present?("content") && content == "Mismatch"
|
25
|
+
errors.add("title", "is Content Mismatch")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def title_is_wrong_create
|
30
|
+
errors.add("title", "is Wrong Create") if attribute_present?("title") && title == "Wrong Create"
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate_on_update
|
34
|
+
errors.add("title", "is Wrong Update") if attribute_present?("title") && title == "Wrong Update"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class SillyReply < Reply
|
39
|
+
belongs_to :reply, :foreign_key => "parent_id", :counter_cache => :replies_count
|
40
|
+
end
|
41
|
+
|
42
|
+
module Web
|
43
|
+
class Reply < Web::Topic
|
44
|
+
belongs_to :topic, :foreign_key => "parent_id", :counter_cache => true, :class_name => 'Web::Topic'
|
45
|
+
end
|
46
|
+
end
|
data/test/models/ship.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
class Ship < ActiveRecord::Base
|
2
|
+
self.record_timestamps = false
|
3
|
+
|
4
|
+
belongs_to :pirate
|
5
|
+
has_many :parts, :class_name => 'ShipPart', :autosave => true
|
6
|
+
|
7
|
+
accepts_nested_attributes_for :pirate, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
|
8
|
+
|
9
|
+
validates_presence_of :name
|
10
|
+
end
|
data/test/models/tag.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# test that attr_readonly isn't called on the :taggable polymorphic association
|
2
|
+
module Taggable
|
3
|
+
end
|
4
|
+
|
5
|
+
class Tagging < ActiveRecord::Base
|
6
|
+
belongs_to :tag, :include => :tagging
|
7
|
+
belongs_to :super_tag, :class_name => 'Tag', :foreign_key => 'super_tag_id'
|
8
|
+
belongs_to :invalid_tag, :class_name => 'Tag', :foreign_key => 'tag_id'
|
9
|
+
belongs_to :taggable, :polymorphic => true, :counter_cache => true
|
10
|
+
end
|
data/test/models/task.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
class Topic < ActiveRecord::Base
|
2
|
+
named_scope :base
|
3
|
+
named_scope :written_before, lambda { |time|
|
4
|
+
if time
|
5
|
+
{ :conditions => ['written_on < ?', time] }
|
6
|
+
end
|
7
|
+
}
|
8
|
+
named_scope :approved, :conditions => {:approved => true}
|
9
|
+
named_scope :rejected, :conditions => {:approved => false}
|
10
|
+
|
11
|
+
named_scope :by_lifo, :conditions => {:author_name => 'lifo'}
|
12
|
+
|
13
|
+
named_scope :approved_as_hash_condition, :conditions => {:topics => {:approved => true}}
|
14
|
+
named_scope 'approved_as_string', :conditions => {:approved => true}
|
15
|
+
named_scope :replied, :conditions => ['replies_count > 0']
|
16
|
+
named_scope :anonymous_extension do
|
17
|
+
def one
|
18
|
+
1
|
19
|
+
end
|
20
|
+
end
|
21
|
+
module NamedExtension
|
22
|
+
def two
|
23
|
+
2
|
24
|
+
end
|
25
|
+
end
|
26
|
+
module MultipleExtensionOne
|
27
|
+
def extension_one
|
28
|
+
1
|
29
|
+
end
|
30
|
+
end
|
31
|
+
module MultipleExtensionTwo
|
32
|
+
def extension_two
|
33
|
+
2
|
34
|
+
end
|
35
|
+
end
|
36
|
+
named_scope :named_extension, :extend => NamedExtension
|
37
|
+
named_scope :multiple_extensions, :extend => [MultipleExtensionTwo, MultipleExtensionOne]
|
38
|
+
|
39
|
+
has_many :replies, :dependent => :destroy, :foreign_key => "parent_id"
|
40
|
+
has_many :replies_with_primary_key, :class_name => "Reply", :dependent => :destroy, :primary_key => "title", :foreign_key => "parent_title"
|
41
|
+
serialize :content
|
42
|
+
|
43
|
+
before_create :default_written_on
|
44
|
+
before_destroy :destroy_children
|
45
|
+
|
46
|
+
def parent
|
47
|
+
Topic.find(parent_id)
|
48
|
+
end
|
49
|
+
|
50
|
+
# trivial method for testing Array#to_xml with :methods
|
51
|
+
def topic_id
|
52
|
+
id
|
53
|
+
end
|
54
|
+
|
55
|
+
protected
|
56
|
+
def approved=(val)
|
57
|
+
@custom_approved = val
|
58
|
+
write_attribute(:approved, val)
|
59
|
+
end
|
60
|
+
|
61
|
+
def default_written_on
|
62
|
+
self.written_on = Time.now unless attribute_present?("written_on")
|
63
|
+
end
|
64
|
+
|
65
|
+
def destroy_children
|
66
|
+
self.class.delete_all "parent_id = #{id}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def after_initialize
|
70
|
+
if self.new_record?
|
71
|
+
self.author_email_address = 'test@test.com'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
module Web
|
77
|
+
class Topic < ActiveRecord::Base
|
78
|
+
has_many :replies, :dependent => :destroy, :foreign_key => "parent_id", :class_name => 'Web::Reply'
|
79
|
+
end
|
80
|
+
end
|
data/test/models/toy.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# This class models a vertex in a directed graph.
|
2
|
+
class Vertex < ActiveRecord::Base
|
3
|
+
has_many :sink_edges, :class_name => 'Edge', :foreign_key => 'source_id'
|
4
|
+
has_many :sinks, :through => :sink_edges
|
5
|
+
|
6
|
+
has_and_belongs_to_many :sources,
|
7
|
+
:class_name => 'Vertex', :join_table => 'edges',
|
8
|
+
:foreign_key => 'sink_id', :association_foreign_key => 'source_id'
|
9
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
ActiveRecord::Schema.define do
|
2
|
+
create_table :binary_fields, :force => true, :options => 'CHARACTER SET latin1' do |t|
|
3
|
+
t.binary :tiny_blob, :limit => 255
|
4
|
+
t.binary :normal_blob, :limit => 65535
|
5
|
+
t.binary :medium_blob, :limit => 16777215
|
6
|
+
t.binary :long_blob, :limit => 2147483647
|
7
|
+
t.text :tiny_text, :limit => 255
|
8
|
+
t.text :normal_text, :limit => 65535
|
9
|
+
t.text :medium_text, :limit => 16777215
|
10
|
+
t.text :long_text, :limit => 2147483647
|
11
|
+
end
|
12
|
+
|
13
|
+
ActiveRecord::Base.connection.execute <<-SQL
|
14
|
+
DROP PROCEDURE IF EXISTS ten;
|
15
|
+
SQL
|
16
|
+
|
17
|
+
ActiveRecord::Base.connection.execute <<-SQL
|
18
|
+
CREATE PROCEDURE ten() SQL SECURITY INVOKER
|
19
|
+
BEGIN
|
20
|
+
select 10;
|
21
|
+
END
|
22
|
+
SQL
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
ActiveRecord::Schema.define do
|
2
|
+
|
3
|
+
%w(postgresql_arrays postgresql_moneys postgresql_numbers postgresql_times postgresql_network_addresses postgresql_bit_strings
|
4
|
+
postgresql_oids postgresql_xml_data_type defaults geometrics).each do |table_name|
|
5
|
+
execute "DROP TABLE IF EXISTS #{quote_table_name table_name}"
|
6
|
+
end
|
7
|
+
|
8
|
+
execute 'DROP SEQUENCE IF EXISTS companies_nonstd_seq CASCADE'
|
9
|
+
execute 'CREATE SEQUENCE companies_nonstd_seq START 101 OWNED BY companies.id'
|
10
|
+
execute "ALTER TABLE companies ALTER COLUMN id SET DEFAULT nextval('companies_nonstd_seq')"
|
11
|
+
execute 'DROP SEQUENCE IF EXISTS companies_id_seq'
|
12
|
+
|
13
|
+
%w(accounts_id_seq developers_id_seq projects_id_seq topics_id_seq customers_id_seq orders_id_seq).each do |seq_name|
|
14
|
+
execute "SELECT setval('#{seq_name}', 100)"
|
15
|
+
end
|
16
|
+
|
17
|
+
execute <<_SQL
|
18
|
+
CREATE TABLE defaults (
|
19
|
+
id serial primary key,
|
20
|
+
modified_date date default CURRENT_DATE,
|
21
|
+
modified_date_function date default now(),
|
22
|
+
fixed_date date default '2004-01-01',
|
23
|
+
modified_time timestamp default CURRENT_TIMESTAMP,
|
24
|
+
modified_time_function timestamp default now(),
|
25
|
+
fixed_time timestamp default '2004-01-01 00:00:00.000000-00',
|
26
|
+
char1 char(1) default 'Y',
|
27
|
+
char2 character varying(50) default 'a varchar field',
|
28
|
+
char3 text default 'a text field',
|
29
|
+
positive_integer integer default 1,
|
30
|
+
negative_integer integer default -1,
|
31
|
+
decimal_number decimal(3,2) default 2.78,
|
32
|
+
multiline_default text DEFAULT '--- []
|
33
|
+
|
34
|
+
'::text
|
35
|
+
);
|
36
|
+
_SQL
|
37
|
+
|
38
|
+
execute <<_SQL
|
39
|
+
CREATE TABLE geometrics (
|
40
|
+
id serial primary key,
|
41
|
+
a_point point,
|
42
|
+
-- a_line line, (the line type is currently not implemented in postgresql)
|
43
|
+
a_line_segment lseg,
|
44
|
+
a_box box,
|
45
|
+
a_path path,
|
46
|
+
a_polygon polygon,
|
47
|
+
a_circle circle
|
48
|
+
);
|
49
|
+
_SQL
|
50
|
+
|
51
|
+
execute <<_SQL
|
52
|
+
CREATE TABLE postgresql_arrays (
|
53
|
+
id SERIAL PRIMARY KEY,
|
54
|
+
commission_by_quarter INTEGER[],
|
55
|
+
nicknames TEXT[]
|
56
|
+
);
|
57
|
+
_SQL
|
58
|
+
execute <<_SQL
|
59
|
+
CREATE TABLE postgresql_moneys (
|
60
|
+
id SERIAL PRIMARY KEY,
|
61
|
+
wealth MONEY
|
62
|
+
);
|
63
|
+
_SQL
|
64
|
+
|
65
|
+
execute <<_SQL
|
66
|
+
CREATE TABLE postgresql_numbers (
|
67
|
+
id SERIAL PRIMARY KEY,
|
68
|
+
single REAL,
|
69
|
+
double DOUBLE PRECISION
|
70
|
+
);
|
71
|
+
_SQL
|
72
|
+
|
73
|
+
execute <<_SQL
|
74
|
+
CREATE TABLE postgresql_times (
|
75
|
+
id SERIAL PRIMARY KEY,
|
76
|
+
time_interval INTERVAL
|
77
|
+
);
|
78
|
+
_SQL
|
79
|
+
|
80
|
+
execute <<_SQL
|
81
|
+
CREATE TABLE postgresql_network_addresses (
|
82
|
+
id SERIAL PRIMARY KEY,
|
83
|
+
cidr_address CIDR,
|
84
|
+
inet_address INET,
|
85
|
+
mac_address MACADDR
|
86
|
+
);
|
87
|
+
_SQL
|
88
|
+
|
89
|
+
execute <<_SQL
|
90
|
+
CREATE TABLE postgresql_bit_strings (
|
91
|
+
id SERIAL PRIMARY KEY,
|
92
|
+
bit_string BIT(8),
|
93
|
+
bit_string_varying BIT VARYING(8)
|
94
|
+
);
|
95
|
+
_SQL
|
96
|
+
|
97
|
+
execute <<_SQL
|
98
|
+
CREATE TABLE postgresql_oids (
|
99
|
+
id SERIAL PRIMARY KEY,
|
100
|
+
obj_id OID
|
101
|
+
);
|
102
|
+
_SQL
|
103
|
+
|
104
|
+
begin
|
105
|
+
execute <<_SQL
|
106
|
+
CREATE TABLE postgresql_xml_data_type (
|
107
|
+
id SERIAL PRIMARY KEY,
|
108
|
+
data xml
|
109
|
+
);
|
110
|
+
_SQL
|
111
|
+
rescue #This version of PostgreSQL either has no XML support or is was not compiled with XML support: skipping table
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|