bullet_instructure 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +20 -0
  6. data/CHANGELOG.md +75 -0
  7. data/Gemfile +19 -0
  8. data/Gemfile.mongoid +14 -0
  9. data/Gemfile.mongoid-2.4 +19 -0
  10. data/Gemfile.mongoid-2.5 +19 -0
  11. data/Gemfile.mongoid-2.6 +19 -0
  12. data/Gemfile.mongoid-2.7 +19 -0
  13. data/Gemfile.mongoid-2.8 +19 -0
  14. data/Gemfile.mongoid-3.0 +19 -0
  15. data/Gemfile.mongoid-3.1 +19 -0
  16. data/Gemfile.mongoid-4.0 +19 -0
  17. data/Gemfile.rails-3.0 +19 -0
  18. data/Gemfile.rails-3.1 +19 -0
  19. data/Gemfile.rails-3.2 +19 -0
  20. data/Gemfile.rails-4.0 +19 -0
  21. data/Gemfile.rails-4.1 +19 -0
  22. data/Guardfile +8 -0
  23. data/Hacking.md +74 -0
  24. data/MIT-LICENSE +20 -0
  25. data/README.md +428 -0
  26. data/Rakefile +52 -0
  27. data/bullet_instructure.gemspec +27 -0
  28. data/lib/bullet.rb +196 -0
  29. data/lib/bullet/active_record3.rb +148 -0
  30. data/lib/bullet/active_record3x.rb +128 -0
  31. data/lib/bullet/active_record4.rb +128 -0
  32. data/lib/bullet/active_record41.rb +121 -0
  33. data/lib/bullet/dependency.rb +81 -0
  34. data/lib/bullet/detector.rb +9 -0
  35. data/lib/bullet/detector/association.rb +67 -0
  36. data/lib/bullet/detector/base.rb +6 -0
  37. data/lib/bullet/detector/counter_cache.rb +59 -0
  38. data/lib/bullet/detector/n_plus_one_query.rb +89 -0
  39. data/lib/bullet/detector/unused_eager_loading.rb +84 -0
  40. data/lib/bullet/ext/object.rb +9 -0
  41. data/lib/bullet/ext/string.rb +5 -0
  42. data/lib/bullet/mongoid2x.rb +56 -0
  43. data/lib/bullet/mongoid3x.rb +56 -0
  44. data/lib/bullet/mongoid4x.rb +56 -0
  45. data/lib/bullet/notification.rb +10 -0
  46. data/lib/bullet/notification/base.rb +97 -0
  47. data/lib/bullet/notification/counter_cache.rb +13 -0
  48. data/lib/bullet/notification/n_plus_one_query.rb +28 -0
  49. data/lib/bullet/notification/unused_eager_loading.rb +13 -0
  50. data/lib/bullet/notification_collector.rb +24 -0
  51. data/lib/bullet/rack.rb +81 -0
  52. data/lib/bullet/registry.rb +7 -0
  53. data/lib/bullet/registry/association.rb +13 -0
  54. data/lib/bullet/registry/base.rb +40 -0
  55. data/lib/bullet/registry/object.rb +13 -0
  56. data/lib/bullet/version.rb +4 -0
  57. data/perf/benchmark.rb +121 -0
  58. data/rails/init.rb +1 -0
  59. data/spec/bullet/detector/association_spec.rb +26 -0
  60. data/spec/bullet/detector/base_spec.rb +8 -0
  61. data/spec/bullet/detector/counter_cache_spec.rb +56 -0
  62. data/spec/bullet/detector/n_plus_one_query_spec.rb +138 -0
  63. data/spec/bullet/detector/unused_eager_loading_spec.rb +88 -0
  64. data/spec/bullet/ext/object_spec.rb +17 -0
  65. data/spec/bullet/ext/string_spec.rb +13 -0
  66. data/spec/bullet/notification/base_spec.rb +83 -0
  67. data/spec/bullet/notification/counter_cache_spec.rb +12 -0
  68. data/spec/bullet/notification/n_plus_one_query_spec.rb +14 -0
  69. data/spec/bullet/notification/unused_eager_loading_spec.rb +12 -0
  70. data/spec/bullet/notification_collector_spec.rb +32 -0
  71. data/spec/bullet/rack_spec.rb +97 -0
  72. data/spec/bullet/registry/association_spec.rb +26 -0
  73. data/spec/bullet/registry/base_spec.rb +44 -0
  74. data/spec/bullet/registry/object_spec.rb +24 -0
  75. data/spec/bullet_spec.rb +41 -0
  76. data/spec/integration/active_record3/association_spec.rb +651 -0
  77. data/spec/integration/active_record4/association_spec.rb +649 -0
  78. data/spec/integration/counter_cache_spec.rb +63 -0
  79. data/spec/integration/mongoid/association_spec.rb +258 -0
  80. data/spec/models/address.rb +3 -0
  81. data/spec/models/author.rb +3 -0
  82. data/spec/models/base_user.rb +5 -0
  83. data/spec/models/category.rb +7 -0
  84. data/spec/models/city.rb +3 -0
  85. data/spec/models/client.rb +4 -0
  86. data/spec/models/comment.rb +4 -0
  87. data/spec/models/company.rb +3 -0
  88. data/spec/models/country.rb +3 -0
  89. data/spec/models/document.rb +5 -0
  90. data/spec/models/entry.rb +3 -0
  91. data/spec/models/firm.rb +4 -0
  92. data/spec/models/folder.rb +2 -0
  93. data/spec/models/mongoid/address.rb +7 -0
  94. data/spec/models/mongoid/category.rb +8 -0
  95. data/spec/models/mongoid/comment.rb +7 -0
  96. data/spec/models/mongoid/company.rb +7 -0
  97. data/spec/models/mongoid/entry.rb +7 -0
  98. data/spec/models/mongoid/post.rb +12 -0
  99. data/spec/models/mongoid/user.rb +5 -0
  100. data/spec/models/newspaper.rb +3 -0
  101. data/spec/models/page.rb +2 -0
  102. data/spec/models/person.rb +3 -0
  103. data/spec/models/pet.rb +3 -0
  104. data/spec/models/post.rb +10 -0
  105. data/spec/models/relationship.rb +4 -0
  106. data/spec/models/student.rb +3 -0
  107. data/spec/models/submission.rb +4 -0
  108. data/spec/models/teacher.rb +3 -0
  109. data/spec/models/user.rb +4 -0
  110. data/spec/models/writer.rb +2 -0
  111. data/spec/spec_helper.rb +103 -0
  112. data/spec/support/bullet_ext.rb +55 -0
  113. data/spec/support/mongo_seed.rb +65 -0
  114. data/spec/support/rack_double.rb +55 -0
  115. data/spec/support/sqlite_seed.rb +229 -0
  116. data/tasks/bullet_tasks.rake +9 -0
  117. data/test.sh +15 -0
  118. metadata +246 -0
@@ -0,0 +1,5 @@
1
+ class Mongoid::User
2
+ include Mongoid::Document
3
+
4
+ field :name
5
+ end
@@ -0,0 +1,3 @@
1
+ class Newspaper < ActiveRecord::Base
2
+ has_many :writers, class_name: "BaseUser"
3
+ end
@@ -0,0 +1,2 @@
1
+ class Page < Document
2
+ end
@@ -0,0 +1,3 @@
1
+ class Person < ActiveRecord::Base
2
+ has_many :pets
3
+ end
@@ -0,0 +1,3 @@
1
+ class Pet < ActiveRecord::Base
2
+ belongs_to :person, counter_cache: true
3
+ end
@@ -0,0 +1,10 @@
1
+ class Post < ActiveRecord::Base
2
+ extend Bullet::Dependency
3
+
4
+ belongs_to :category
5
+ belongs_to :writer
6
+ has_many :comments, inverse_of: :post
7
+
8
+ scope :preload_comments, -> { includes(:comments) }
9
+ scope :in_category_name, ->(name) { where(['categories.name = ?', name]).includes(:category) }
10
+ end
@@ -0,0 +1,4 @@
1
+ class Relationship < ActiveRecord::Base
2
+ belongs_to :firm
3
+ belongs_to :client
4
+ end
@@ -0,0 +1,3 @@
1
+ class Student < ActiveRecord::Base
2
+ has_and_belongs_to_many :teachers
3
+ end
@@ -0,0 +1,4 @@
1
+ class Submission < ActiveRecord::Base
2
+ belongs_to :category
3
+ belongs_to :user
4
+ end
@@ -0,0 +1,3 @@
1
+ class Teacher < ActiveRecord::Base
2
+ has_and_belongs_to_many :students
3
+ end
@@ -0,0 +1,4 @@
1
+ class User < ActiveRecord::Base
2
+ has_one :submission
3
+ belongs_to :category
4
+ end
@@ -0,0 +1,2 @@
1
+ class Writer < BaseUser
2
+ end
@@ -0,0 +1,103 @@
1
+ require 'rspec'
2
+ begin
3
+ require 'active_record'
4
+ rescue LoadError
5
+ end
6
+ begin
7
+ require 'mongoid'
8
+ rescue LoadError
9
+ end
10
+
11
+ module Rails
12
+ class <<self
13
+ def root
14
+ File.expand_path(__FILE__).split('/')[0..-3].join('/')
15
+ end
16
+
17
+ def env
18
+ "test"
19
+ end
20
+ end
21
+ end
22
+
23
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
24
+ require 'bullet'
25
+ extend Bullet::Dependency
26
+ Bullet.enable = true
27
+
28
+ MODELS = File.join(File.dirname(__FILE__), "models")
29
+ $LOAD_PATH.unshift(MODELS)
30
+ SUPPORT = File.join(File.dirname(__FILE__), "support")
31
+ Dir[ File.join(SUPPORT, "*.rb") ].reject { |filename| filename =~ /_seed.rb$/ }.sort.each { |file| require file }
32
+
33
+ require 'coveralls'
34
+ Coveralls.wear!
35
+
36
+ RSpec.configure do |config|
37
+ config.extend Bullet::Dependency
38
+
39
+ config.filter_run :focus => true
40
+ config.run_all_when_everything_filtered = true
41
+ end
42
+
43
+ if active_record?
44
+ ActiveRecord::Migration.verbose = false
45
+
46
+ # Autoload every active_record model for the test suite that sits in spec/models.
47
+ Dir[ File.join(MODELS, "*.rb") ].sort.each do |filename|
48
+ name = File.basename(filename, ".rb")
49
+ autoload name.camelize.to_sym, name
50
+ end
51
+ require File.join(SUPPORT, "sqlite_seed.rb")
52
+
53
+ RSpec.configure do |config|
54
+ config.before(:suite) do
55
+ Support::SqliteSeed.setup_db
56
+ Support::SqliteSeed.seed_db
57
+ end
58
+
59
+ config.before(:each) do
60
+ Bullet.start_request
61
+ end
62
+
63
+ config.after(:each) do
64
+ Bullet.end_request
65
+ end
66
+ end
67
+
68
+ if ENV["LOG"]
69
+ require 'logger'
70
+ ActiveRecord::Base.logger = Logger.new(STDOUT)
71
+ end
72
+ end
73
+
74
+ if mongoid?
75
+ # Autoload every mongoid model for the test suite that sits in spec/models.
76
+ Dir[ File.join(MODELS, "mongoid", "*.rb") ].sort.each { |file| require file }
77
+ require File.join(SUPPORT, "mongo_seed.rb")
78
+
79
+ RSpec.configure do |config|
80
+ config.before(:suite) do
81
+ Support::MongoSeed.setup_db
82
+ Support::MongoSeed.seed_db
83
+ end
84
+
85
+ config.after(:suite) do
86
+ Support::MongoSeed.setup_db
87
+ Support::MongoSeed.teardown_db
88
+ end
89
+
90
+ config.before(:each) do
91
+ Bullet.start_request
92
+ end
93
+
94
+ config.after(:each) do
95
+ Bullet.end_request
96
+ end
97
+ end
98
+
99
+ if ENV["LOG"]
100
+ Mongoid.logger = Logger.new(STDOUT)
101
+ Moped.logger = Logger.new(STDOUT)
102
+ end
103
+ end
@@ -0,0 +1,55 @@
1
+ module Bullet
2
+ def self.collected_notifications_of_class(notification_class)
3
+ Bullet.notification_collector.collection.select do |notification|
4
+ notification.is_a? notification_class
5
+ end
6
+ end
7
+
8
+ def self.collected_counter_cache_notifications
9
+ collected_notifications_of_class Bullet::Notification::CounterCache
10
+ end
11
+
12
+ def self.collected_n_plus_one_query_notifications
13
+ collected_notifications_of_class Bullet::Notification::NPlusOneQuery
14
+ end
15
+
16
+ def self.collected_unused_eager_association_notifications
17
+ collected_notifications_of_class Bullet::Notification::UnusedEagerLoading
18
+ end
19
+ end
20
+
21
+ module Bullet
22
+ module Detector
23
+ class Association
24
+ class <<self
25
+ # returns true if all associations are preloaded
26
+ def completely_preloading_associations?
27
+ Bullet.collected_n_plus_one_query_notifications.empty?
28
+ end
29
+
30
+ def has_unused_preload_associations?
31
+ Bullet.collected_unused_eager_association_notifications.present?
32
+ end
33
+
34
+ # returns true if a given object has a specific association
35
+ def creating_object_association_for?(object, association)
36
+ object_associations[object.bullet_key].present? && object_associations[object.bullet_key].include?(association)
37
+ end
38
+
39
+ # returns true if a given class includes the specific unpreloaded association
40
+ def detecting_unpreloaded_association_for?(klass, association)
41
+ Bullet.collected_n_plus_one_query_notifications.select { |notification|
42
+ notification.base_class == klass.to_s && notification.associations.include?(association)
43
+ }.present?
44
+ end
45
+
46
+ # returns true if the given class includes the specific unused preloaded association
47
+ def unused_preload_associations_for?(klass, association)
48
+ Bullet.collected_unused_eager_association_notifications.select { |notification|
49
+ notification.base_class == klass.to_s && notification.associations.include?(association)
50
+ }.present?
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,65 @@
1
+ module Support
2
+ module MongoSeed
3
+ def seed_db
4
+ category1 = Mongoid::Category.create(:name => 'first')
5
+ category2 = Mongoid::Category.create(:name => 'second')
6
+
7
+ post1 = category1.posts.create(:name => 'first')
8
+ post1a = category1.posts.create(:name => 'like first')
9
+ post2 = category2.posts.create(:name => 'second')
10
+
11
+ post1.users << Mongoid::User.create(:name => 'first')
12
+ post1.users << Mongoid::User.create(:name => 'another')
13
+ post2.users << Mongoid::User.create(:name => 'second')
14
+
15
+ comment1 = post1.comments.create(:name => 'first')
16
+ comment2 = post1.comments.create(:name => 'first2')
17
+ comment3 = post1.comments.create(:name => 'first3')
18
+ comment4 = post1.comments.create(:name => 'second')
19
+ comment8 = post1a.comments.create(:name => "like first 1")
20
+ comment9 = post1a.comments.create(:name => "like first 2")
21
+ comment5 = post2.comments.create(:name => 'third')
22
+ comment6 = post2.comments.create(:name => 'fourth')
23
+ comment7 = post2.comments.create(:name => 'fourth')
24
+
25
+ entry1 = category1.entries.create(:name => 'first')
26
+ entry2 = category1.entries.create(:name => 'second')
27
+
28
+ company1 = Mongoid::Company.create(:name => 'first')
29
+ company2 = Mongoid::Company.create(:name => 'second')
30
+
31
+ Mongoid::Address.create(:name => 'first', :company => company1)
32
+ Mongoid::Address.create(:name => 'second', :company => company2)
33
+ end
34
+
35
+ def setup_db
36
+ if Mongoid::VERSION =~ /\A2\.[4-8]/
37
+ Mongoid.configure do |config|
38
+ config.master = Mongo::Connection.new.db("bullet")
39
+ end
40
+ elsif Mongoid::VERSION =~ /\A3/
41
+ Mongoid.configure do |config|
42
+ config.connect_to("bullet")
43
+ end
44
+ elsif Mongoid::VERSION =~ /\A4/
45
+ Mongoid.configure do |config|
46
+ config.load_configuration(
47
+ sessions: {
48
+ default: {
49
+ database: "bullet",
50
+ hosts: [ "localhost:27017" ]
51
+ }
52
+ }
53
+ )
54
+ end
55
+ end
56
+ end
57
+
58
+ def teardown_db
59
+ Mongoid.purge!
60
+ Mongoid::IdentityMap.clear if Mongoid.const_defined?(:IdentityMap)
61
+ end
62
+
63
+ extend self
64
+ end
65
+ end
@@ -0,0 +1,55 @@
1
+ module Support
2
+ class AppDouble
3
+ def call env
4
+ env = @env
5
+ [ status, headers, response ]
6
+ end
7
+
8
+ def status= status
9
+ @status = status
10
+ end
11
+
12
+ def headers= headers
13
+ @headers = headers
14
+ end
15
+
16
+ def headers
17
+ @headers ||= {"Content-Type" => "text/html"}
18
+ @headers
19
+ end
20
+
21
+ def response= response
22
+ @response = response
23
+ end
24
+
25
+ private
26
+ def status
27
+ @status || 200
28
+ end
29
+
30
+ def response
31
+ @response || ResponseDouble.new
32
+ end
33
+ end
34
+
35
+ class ResponseDouble
36
+ def initialize actual_body = nil
37
+ @actual_body = actual_body
38
+ end
39
+
40
+ def body
41
+ @body ||= "<html><head></head><body></body></html>"
42
+ end
43
+
44
+ def body= body
45
+ @body = body
46
+ end
47
+
48
+ def each
49
+ yield body
50
+ end
51
+
52
+ def close
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,229 @@
1
+ module Support
2
+ module SqliteSeed
3
+ def seed_db
4
+ newspaper1 = Newspaper.create(:name => "First Newspaper")
5
+ newspaper2 = Newspaper.create(:name => "Second Newspaper")
6
+
7
+ writer1 = Writer.create(:name => 'first', :newspaper => newspaper1)
8
+ writer2 = Writer.create(:name => 'second', :newspaper => newspaper2)
9
+ user1 = BaseUser.create(:name => 'third', :newspaper => newspaper1)
10
+ user2 = BaseUser.create(:name => 'fourth', :newspaper => newspaper2)
11
+
12
+
13
+ category1 = Category.create(:name => 'first')
14
+ category2 = Category.create(:name => 'second')
15
+
16
+ post1 = category1.posts.create(:name => 'first', :writer => writer1)
17
+ post1a = category1.posts.create(:name => 'like first', :writer => writer2)
18
+ post2 = category2.posts.create(:name => 'second', :writer => writer2)
19
+
20
+ comment1 = post1.comments.create(:name => 'first', :author => writer1)
21
+ comment2 = post1.comments.create(:name => 'first2', :author => writer1)
22
+ comment3 = post1.comments.create(:name => 'first3', :author => writer1)
23
+ comment4 = post1.comments.create(:name => 'second', :author => writer2)
24
+ comment8 = post1a.comments.create(:name => "like first 1", :author => writer1)
25
+ comment9 = post1a.comments.create(:name => "like first 2", :author => writer2)
26
+ comment5 = post2.comments.create(:name => 'third', :author => user1)
27
+ comment6 = post2.comments.create(:name => 'fourth', :author => user2)
28
+ comment7 = post2.comments.create(:name => 'fourth', :author => writer1)
29
+
30
+ entry1 = category1.entries.create(:name => 'first')
31
+ entry2 = category1.entries.create(:name => 'second')
32
+
33
+ student1 = Student.create(:name => 'first')
34
+ student2 = Student.create(:name => 'second')
35
+ teacher1 = Teacher.create(:name => 'first')
36
+ teacher2 = Teacher.create(:name => 'second')
37
+ student1.teachers = [teacher1, teacher2]
38
+ student2.teachers = [teacher1, teacher2]
39
+ teacher1.students << student1
40
+ teacher2.students << student2
41
+
42
+ firm1 = Firm.create(:name => 'first')
43
+ firm2 = Firm.create(:name => 'second')
44
+ client1 = Client.create(:name => 'first')
45
+ client2 = Client.create(:name => 'second')
46
+ firm1.clients = [client1, client2]
47
+ firm2.clients = [client1, client2]
48
+ client1.firms << firm1
49
+ client2.firms << firm2
50
+
51
+ company1 = Company.create(:name => 'first')
52
+ company2 = Company.create(:name => 'second')
53
+
54
+ Address.create(:name => 'first', :company => company1)
55
+ Address.create(:name => 'second', :company => company2)
56
+
57
+ country1 = Country.create(:name => 'first')
58
+ country2 = Country.create(:name => 'second')
59
+
60
+ country1.cities.create(:name => 'first')
61
+ country1.cities.create(:name => 'second')
62
+ country2.cities.create(:name => 'third')
63
+ country2.cities.create(:name => 'fourth')
64
+
65
+ person1 = Person.create(:name => 'first')
66
+ person2 = Person.create(:name => 'second')
67
+
68
+ person1.pets.create(:name => 'first')
69
+ person1.pets.create(:name => 'second')
70
+ person2.pets.create(:name => 'third')
71
+ person2.pets.create(:name => 'fourth')
72
+
73
+ author1 = Author.create(:name => 'author1')
74
+ author2 = Author.create(:name => 'author2')
75
+ folder1 = Folder.create(:name => 'folder1', :author_id => author1.id)
76
+ folder2 = Folder.create(:name => 'folder2', :author_id => author2.id)
77
+ page1 = Page.create(:name => 'page1', :parent_id => folder1.id, :author_id => author1.id)
78
+ page2 = Page.create(:name => 'page2', :parent_id => folder1.id, :author_id => author1.id)
79
+ page3 = Page.create(:name => 'page3', :parent_id => folder2.id, :author_id => author2.id)
80
+ page4 = Page.create(:name => 'page4', :parent_id => folder2.id, :author_id => author2.id)
81
+
82
+ user1 = User.create(:name => 'user1', :category => category1)
83
+ user2 = User.create(:name => 'user2', :category => category1)
84
+
85
+ submission1 = category1.submissions.create(:name => "submission1", :user => user1)
86
+ submission2 = category1.submissions.create(:name => "submission2", :user => user2)
87
+ submission3 = category2.submissions.create(:name => "submission3", :user => user1)
88
+ submission4 = category2.submissions.create(:name => "submission4", :user => user2)
89
+ end
90
+
91
+ def setup_db
92
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
93
+
94
+ ActiveRecord::Schema.define(:version => 1) do
95
+ create_table :addresses do |t|
96
+ t.column :name, :string
97
+ t.column :company_id, :integer
98
+ end
99
+
100
+ create_table :authors do |t|
101
+ t.string :name
102
+ end
103
+
104
+ create_table :base_users do |t|
105
+ t.column :name, :string
106
+ t.column :type, :string
107
+ t.column :newspaper_id, :integer
108
+ end
109
+
110
+ create_table :categories do |t|
111
+ t.column :name, :string
112
+ end
113
+
114
+ create_table :cities do |t|
115
+ t.string :name
116
+ t.integer :country_id
117
+ end
118
+
119
+ create_table :clients do |t|
120
+ t.column :name, :string
121
+ end
122
+
123
+ create_table :comments do |t|
124
+ t.column :name, :string
125
+ t.column :post_id, :integer
126
+ t.column :author_id, :integer
127
+ end
128
+
129
+ create_table :companies do |t|
130
+ t.column :name, :string
131
+ end
132
+
133
+ create_table :contacts do |t|
134
+ t.column :name, :string
135
+ end
136
+
137
+ create_table :countries do |t|
138
+ t.string :name
139
+ end
140
+
141
+ create_table :deals do |t|
142
+ t.column :name, :string
143
+ t.column :hotel_id, :integer
144
+ end
145
+
146
+ create_table :documents do |t|
147
+ t.string :name
148
+ t.string :type
149
+ t.integer :parent_id
150
+ t.integer :author_id
151
+ end
152
+
153
+ create_table :emails do |t|
154
+ t.column :name, :string
155
+ t.column :contact_id, :integer
156
+ end
157
+
158
+ create_table :entries do |t|
159
+ t.column :name, :string
160
+ t.column :category_id, :integer
161
+ end
162
+
163
+ create_table :firms do |t|
164
+ t.column :name, :string
165
+ end
166
+
167
+ create_table :hotels do |t|
168
+ t.column :name, :string
169
+ t.column :location_id, :integer
170
+ end
171
+
172
+ create_table :locations do |t|
173
+ t.column :name, :string
174
+ end
175
+
176
+ create_table :newspapers do |t|
177
+ t.column :name, :string
178
+ end
179
+
180
+ create_table :people do |t|
181
+ t.string :name
182
+ t.integer :pets_count
183
+ end
184
+
185
+ create_table :pets do |t|
186
+ t.string :name
187
+ t.integer :person_id
188
+ end
189
+
190
+ create_table :posts do |t|
191
+ t.column :name, :string
192
+ t.column :category_id, :integer
193
+ t.column :writer_id, :integer
194
+ end
195
+
196
+ create_table :relationships do |t|
197
+ t.column :firm_id, :integer
198
+ t.column :client_id, :integer
199
+ end
200
+
201
+ create_table :students do |t|
202
+ t.column :name, :string
203
+ end
204
+
205
+ create_table :students_teachers, :id => false do |t|
206
+ t.column :student_id, :integer
207
+ t.column :teacher_id, :integer
208
+ end
209
+
210
+ create_table :teachers do |t|
211
+ t.column :name, :string
212
+ end
213
+
214
+ create_table :submissions do |t|
215
+ t.column :name, :string
216
+ t.column :category_id, :integer
217
+ t.column :user_id, :integer
218
+ end
219
+
220
+ create_table :users do |t|
221
+ t.column :name, :string
222
+ t.column :category_id, :integer
223
+ end
224
+ end
225
+ end
226
+
227
+ extend self
228
+ end
229
+ end