frolic-redhillonrails_core 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. data/.gitignore +3 -0
  2. data/CHANGELOG +196 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README +177 -0
  5. data/Rakefile +35 -0
  6. data/VERSION +1 -0
  7. data/init.rb +1 -0
  8. data/lib/red_hill_consulting/core/active_record/base.rb +67 -0
  9. data/lib/red_hill_consulting/core/active_record/connection_adapters/abstract_adapter.rb +46 -0
  10. data/lib/red_hill_consulting/core/active_record/connection_adapters/column.rb +21 -0
  11. data/lib/red_hill_consulting/core/active_record/connection_adapters/foreign_key_definition.rb +26 -0
  12. data/lib/red_hill_consulting/core/active_record/connection_adapters/index_definition.rb +11 -0
  13. data/lib/red_hill_consulting/core/active_record/connection_adapters/mysql4_adapter.rb +37 -0
  14. data/lib/red_hill_consulting/core/active_record/connection_adapters/mysql5_adapter.rb +35 -0
  15. data/lib/red_hill_consulting/core/active_record/connection_adapters/mysql_adapter.rb +56 -0
  16. data/lib/red_hill_consulting/core/active_record/connection_adapters/mysql_column.rb +8 -0
  17. data/lib/red_hill_consulting/core/active_record/connection_adapters/postgresql_adapter.rb +131 -0
  18. data/lib/red_hill_consulting/core/active_record/connection_adapters/schema_statements.rb +23 -0
  19. data/lib/red_hill_consulting/core/active_record/connection_adapters/sqlite3_adapter.rb +9 -0
  20. data/lib/red_hill_consulting/core/active_record/connection_adapters/table_definition.rb +27 -0
  21. data/lib/red_hill_consulting/core/active_record/schema.rb +25 -0
  22. data/lib/red_hill_consulting/core/active_record/schema_dumper.rb +58 -0
  23. data/lib/redhillonrails_core.rb +45 -0
  24. data/redhillonrails_core.gemspec +83 -0
  25. data/spec/models/child.rb +2 -0
  26. data/spec/models/top.rb +2 -0
  27. data/spec/redhillonrails_core_spec.rb +106 -0
  28. data/spec/spec_helper.rb +36 -0
  29. data/spec/spec_helper_module.rb +55 -0
  30. data/tasks/db/comments.rake +9 -0
  31. metadata +107 -0
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ .DS_Store
2
+ *.log
3
+ pkg
data/CHANGELOG ADDED
@@ -0,0 +1,196 @@
1
+ add
2
+
3
+ [REVISION 0.0.1]
4
+
5
+ [NEW] redhillonrails_core is now a gem
6
+
7
+ [REVISION 20080701]
8
+
9
+ [FIXED] Looking up schema version fails on Rails 2.1.
10
+
11
+ [REVISION 20080318]
12
+
13
+ [FIXED] Case-insensitive text columns not recognised.
14
+
15
+ [REVISION 20080221]
16
+
17
+ [NEW] PostgreSQL view management via create_view and drop_view.
18
+
19
+ [REVISION 20080209]
20
+
21
+ [FIXED] PostgreSQL columns named the same as database keywords (eg. type, column, user, etc.) caused NoSuchMethod errors during model validation.
22
+
23
+ [REVISION 20080110]
24
+
25
+ [FIXED] Workaround for bug in MySQL that adversely affects INFORMATION schema performance take 3 (Michael Latta).
26
+
27
+ [REVISION 20080103]
28
+
29
+ [FIXED] Workaround for bug in MySQL that adversely affects INFORMATION schema performance take 2 (Michael Latta).
30
+
31
+ [REVISION 20080102]
32
+
33
+ [FIXED] Workaround for bug in MySQL that adversely affects INFORMATION schema performance (Michael Latta).
34
+
35
+ [REVISION 20071128]
36
+
37
+ [FIXED] Workaround to ensure plugin is only ever loaded once.
38
+
39
+ [REVISION 20071013]
40
+
41
+ [NEW] Rake task (db:comments) to show database table comments.
42
+
43
+ [REVISION 20071013]
44
+
45
+ [NEW] New migration script methods: set_table_comment and clear_table_comment. Implemented for MySQL and PostgreSQL. Currently not written to schema.rb.
46
+
47
+ [REVISION 20070905]
48
+
49
+ [NEW] Explicitly ignore add_foreign_key() and remove_foreign_key() when running under SQLite. This solves issues when migrating schema from other databases.
50
+
51
+ [REVISION 20070707]
52
+
53
+ [NEW] Make the table name in table definition accessible.
54
+
55
+ [REVISION 20070529]
56
+
57
+ [FIXED] Undefined constant errors when patching connection adapters. Rails now only loads the connection adapter for the specified database (it used to load them all).
58
+
59
+ [REVISION 20070503]
60
+
61
+ [NEW] Support for SQL92 [NOT] DEFERRABLE on foreign keys.
62
+ [CHANGED] Foreign key names are now assigned by the database unless an explicit name is given (using :name).
63
+
64
+ [REVISION 20070221]
65
+
66
+ [NEW] Where possible, determine if a column is case sensitive (or not) based on the presence of case-insensitive indexes.
67
+
68
+ [REVISION 20070220]
69
+
70
+ [CHANGED] :ignore_case => true option when creating indexes change to :case_sensitive => false in keeping with the new Rails 1.2 option of the same name on validates_uniqueness_of. You may need to re-create your schema.rb (by using rake db:schema:dump) to pickup the new syntax.
71
+
72
+ [FIXED] Multi-column, case-insensitive indexes only selecting one of the columns!
73
+
74
+ [REVISION 20070219]
75
+
76
+ [FIXED] Can't drop table referenced in a foreign-key. All reverse foreign keys are now dropped before dropping the table.
77
+
78
+ [CHANGED] Upgrade to Rails 1.2.2.
79
+
80
+ [REVISION 20070217]
81
+
82
+ [NEW] Support reverse_foreign_keys for MySQL using the (typically bastardised) MySQL flavour of information_schema.
83
+
84
+ [CHANGED] Merged ForiegnKey and ForeignKeyDefinition as they were practically the same.
85
+
86
+ [REVISION 20070214]
87
+
88
+ [NEW] :name option when creating foreign keys.
89
+
90
+ [FIXED] Foreign key names are preserved in schema dumps. This means they will be copied from one database to another rather than leaving it up to the target database to make one up.
91
+
92
+ [NEW] Foreign keys are automatically assigned a name (fkey_<tablename>_col1_and_col2_and_col3) if none is specified.
93
+
94
+ [REVISION 20061206]
95
+
96
+ [NEW] Added :ignore_case option to add_index in PostgreSQL to support case-insensitive indexes. The generated indexes are actually expression indexes of the form: lower(column_name).
97
+
98
+ [REVISION 20061206]
99
+
100
+ [NEW] reverse_foreign_keys methods.
101
+
102
+ [REVISION 20061202]
103
+
104
+ [CHANGED] Use Rails 1.2 alias_method_chain.
105
+
106
+ [CHANGED] Separate modules into individual files.
107
+
108
+ [REVISION 20061129]
109
+
110
+ [FIXED] Foreign-key ON DELETE and ON UPDATE flipped in schema dump.
111
+
112
+ [REVISION 20061121]
113
+
114
+ [FIXED] MySQL doesn't support SQL92 'DROP CONSTRAINT SYNTAX'; use 'DROP FOREIGN KEY' instead.
115
+
116
+ [REVISION 20061116]
117
+
118
+ [FIXED] 'DROP FOREIGN KEY' should be 'DROP CONSTRAINT'.
119
+
120
+ [REVISION 20061114]
121
+
122
+ [CHANGED] Removed Column.required as it didn't handle updates correctly. Instead we now have Column.required_on which returns an appropriate event (nil, :save, :update).
123
+
124
+ [REVISION 20061110]
125
+
126
+ [FIXED] MySQL driver uses single AND double quotes around identifiers.
127
+
128
+ [REVISION 20061028]
129
+
130
+ [FIXED] Syntax error when generating schema under MySQL when a foreign key specifies both ON UPDATE and ON DELETE.
131
+
132
+ [REVISION 20061024]
133
+
134
+ [FIXED] Foreign key associations for key-word table-names are quoted in postgresql.
135
+
136
+ [REVISION 20061011]
137
+
138
+ [NEW] ActiveRecord::Base.base_class? returns true if the class is a base class; false otherwise.
139
+
140
+ [REVISION 20061009]
141
+
142
+ [NEW] ActiveRecord::Base.abstract_class? returns true if class name starts with 'Abstract'; false otherwise.
143
+
144
+ [REVISION 20061001]
145
+
146
+ [NEW] remove_foreign_key for completeness.
147
+
148
+ [FIXED] MySQL barfs when attempting to drop a column that participates in a foreign key constraint.
149
+
150
+ [REVISION 20060921]
151
+
152
+ [FIXED] add_foreign_key doesn't support on_delete or on_update--It doesn't do anything with the options hash.
153
+
154
+ [REVISION 20060919]
155
+
156
+ [CHANGED] Column.unique is now derived based on the presence of Column.unique_scope (which is an empty array for single column unique indexes).
157
+
158
+ [REVISION 20060915]
159
+
160
+ [NEW] Unique columns contain scoping meta-data for multi-column unique indexes. The column to be marked as unique is either the last column not ending in '_id' or simply the last column. This follows the typical composite unique index column ordering where the scoping is specified first but will attempt to find the last non-foreign-key column just-in-case. Eg, both add_index :states, [:country_id, :name] and add_index :states, [:name, :country_id] would result in the name column marked as unique with a scope of [:country_id].
161
+
162
+ [REVISION 20060913]
163
+
164
+ [NEW] Column.required: returns true if a column is marked as not allowing null and has no default.
165
+
166
+ [REVISION 20060911]
167
+
168
+ [NEW] Patch rails MysqlColumn so that empty string defaults are treated as nil when a column is marked as NOT NULL. This primarily affects schema dumps incorrectly assigning a default of 0 to numbers and '' to strings when none was originally specified.
169
+
170
+ [REVISION 20060909]
171
+
172
+ [CHANGED] Renamed from Foreign Key Support.
173
+
174
+ [NEW] ActiveRecord::Base.indexes.
175
+
176
+ [REVISION 20060906]
177
+
178
+ [FIXED] :on_update with :on_delete producing invalid SQL.
179
+
180
+ [REVISION 20060905]
181
+
182
+ [NEW] Schema dumper outputs foreign keys when available.
183
+
184
+ [NEW] Foreign-key meta-data for: PostgreSQL; and MySQL. (Still needs a bit of DRY-ing up but it works which is the first step.)
185
+
186
+ [REVISION 20060901]
187
+
188
+ [FIXED] Incorrect generation of ON UPDATE/ON DELETE clauses.
189
+
190
+ [NEW] Support :restrict in ON UPDATE/ON DELETE clauses.
191
+
192
+ [NEW] Preliminary support for querying foreign-keys in PostgreSQL.
193
+
194
+ [REVISION 20060831]
195
+
196
+ [NEW] Initial version.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006 RedHill Consulting, Pty. Ltd.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,177 @@
1
+ = RedHill on Rails Core
2
+
3
+ RedHill on Rails Core is a plugin that features to support other RedHill on Rails plugins. Those features include:
4
+
5
+ * Creating and dropping views;
6
+ * Creating and removing foreign-keys;
7
+ * Obtaining indexes directly from a model class; and
8
+ * Determining when <code>Schema.define()</code> is running.
9
+
10
+ === View Support
11
+
12
+ The plugin provides a mechanism for creating and dropping views as well as
13
+ preserving views when performing a schema dump:
14
+
15
+ create_view :normal_customers, "SELECT * FROM customers WHERE status = 'normal'"
16
+ drop_view :normal_customers
17
+
18
+ === Foreign Key Support
19
+
20
+ The plugin provides two mechanisms for adding foreign keys as well as
21
+ preserving foreign keys when performing a schema dump. (Using SQL-92 syntax and
22
+ as such should be compatible with most databases that support foreign-key
23
+ constraints.)
24
+
25
+ The first mechanism for creating foreign-keys allows you to add a foreign key
26
+ when defining a table. For example:
27
+
28
+ create_table :orders do |t|
29
+ ...
30
+ t.foreign_key :customer_id, :customers, :id
31
+ end
32
+
33
+ You also have the option of specifying what to do on delete/update using
34
+ <code>:on_delete</code>/<code>:on_update</code>, respectively to one of: <code>:cascade</code>; <code>:restrict</code>; and <code>:set_null</code>:
35
+
36
+ create_table :orders do |t|
37
+ ...
38
+ t.foreign_key :customer_id, :customers, :id, :on_delete => :set_null, :on_update => :cascade
39
+ end
40
+
41
+ The second method allows you to create arbitrary foreign-keys at any time:
42
+
43
+ add_foreign_key(:orders, :customer_id, :customers, :id, :on_delete => :set_null, :on_update => :cascade)
44
+
45
+ In either case, if your database supports deferred foreign keys (for example PostgreSQL) you can specify this as well:
46
+
47
+ t.foreign_key :customer_id, :customers, :id, :deferrable => true
48
+ add_foreign_key(:orders, :customer_id, :customers, :id, :deferrable => true)
49
+
50
+ By default, the foreign key will be assigned a name by the underlying database. However, if this doesn't suit
51
+ your needs, you can override the default assignment using the <code>:name</code> option:
52
+
53
+ add_foreign_key(:orders, :customer_id, :customers, :id, :on_delete => :set_null, :on_update => :cascade, <strong>:name => :orders_customer_id_foreign_key<strong>)
54
+
55
+ You can also query the foreign keys for a model yourself by calling <code>foreign_keys()</code>:
56
+
57
+ Order.foreign_keys
58
+
59
+ Or for an arbitrary table by calling <code>foreign_keys(table_name)</code> on a database adapter.
60
+
61
+ Either method returns an array of the following meta-data:
62
+
63
+ * +name+ - The name of the foreign key constraint;
64
+ * +table_name+ - The table for which the foreign-key was generated;
65
+ * +column_names+ - The column names in the table;
66
+ * +references_table_name+ - The table referenced by the foreign-key; and
67
+ * +references_column_names+ - The columns names in the referenced table.
68
+
69
+ If you need to drop a foreign-key, use:
70
+
71
+ remove_foreign_key :orders, :orders_ordered_by_id_fkey
72
+
73
+ The plugin also ensures that all foreign keys are output when performing a
74
+ schema dump. This happens automatically when running <code>rake migrate</code> or
75
+ <code>rake db:schema:dump</code>. This has particular implications when running
76
+ unit tests that contain fixtures. To ensure the test data is correctly reset after
77
+ each test, you should list your fixtures in order of parent->child. For example:
78
+
79
+ fixtures :customers, :products, :orders, :order_lines
80
+
81
+ Rails will then set-up and tear-down the fixtures in the correct sequence.
82
+
83
+ Some databases (PostgreSQL and MySQL for example) allow you to set a comment for a
84
+ table. You can do this for existing tables by using:
85
+
86
+ set_table_comment :orders, "All pending and processed orders"
87
+
88
+ or even at the time of creation:
89
+
90
+ create_table :orders, :comment => "All pending and processed orders" do |t|
91
+ ...
92
+ end
93
+
94
+ You can clear table comments using:
95
+
96
+ clear_table_comment :orders
97
+
98
+ There is also a rake tasks to show all database tables and their comments:
99
+
100
+ rake db:comments
101
+
102
+ The plugin fully supports and understands the following active-record
103
+ configuration properties:
104
+
105
+ * <code>config.active_record.pluralize_table_names</code>
106
+ * <code>config.active_record.table_name_prefix</code>
107
+ * <code>config.active_record.table_name_suffix</code>
108
+
109
+ === Model Indexes
110
+
111
+ ActiveRecord::Base already provides a method on connection for obtaining the
112
+ indexes for a given table. This plugin now makes it possible to obtain the
113
+ indexes for a given model--<code>ActiveRecord::Base</code>--class. For example:
114
+
115
+ Invoice.indexes
116
+
117
+ Would return all the indexes for the +invoices+ table.
118
+
119
+ === Schema Defining
120
+
121
+ The plugin also adds a method--<code>defining?()</code>--to
122
+ <code>ActiveRecord::Schema</code> to indicate when <code>define()</code> is running. This is necessary
123
+ as some migration plugins must change their behaviour accordingly.
124
+
125
+ === Case-insensitive Indexes
126
+
127
+ For PostgreSQL, you can add an option <code>:case_sensitive => false</code> to <code>add_index</code>
128
+ which will generate an expression index of the form:
129
+
130
+ LOWER(column_name)
131
+
132
+ This means finder queries of the form:
133
+
134
+ WHERE LOWER(column_name) = LOWER(?)
135
+
136
+ are able to use the indexes rather require, in the worst case, full-table scans.
137
+
138
+ Note also that this ties in well with Rails built-in support for case-insensitive searching:
139
+
140
+ validates_uniqueness_of :name, :case_sensitive => false
141
+
142
+ === Testing
143
+
144
+ The plugin is heavily dependent on the database and rspec testing is provided to verify if database supports plugin features.
145
+
146
+ Rspec and rspec-rails plugins are neccessary:
147
+
148
+ script/plugin install git://github.com/dchelimsky/rspec.git
149
+ script/plugin install git://github.com/dchelimsky/rspec-rails.git
150
+ script/generate rspec
151
+
152
+ The plugin test use rails test database so it must be created before the tests are run:
153
+
154
+ rake db:create RAILS_ENV=test
155
+
156
+ And then run the plugin specs with:
157
+
158
+ rake specs:plugins
159
+
160
+ The plugin was tested on:
161
+ * mysql5 - all tests pass
162
+ * sqlite - plugin doesn't support foreign key functionality for sqlite because db doesn't implement foreign key constraints
163
+ * sqlite3 - plugin doesn't support foreign key functionality for sqlite3
164
+ * postgresql - all tests pass
165
+
166
+ Currently only foreign key functionality is tested
167
+ === See Also
168
+
169
+ * Foreign Key Associations (foreign_key_associations)
170
+ * Foreign Key Migrations (foreign_key_migrations)
171
+ * Row Version Migrations (row_version_migrations)
172
+ * Schema Validations (schema_validations)
173
+
174
+ === License
175
+
176
+ This plugin is copyright 2006 by RedHill Consulting, Pty. Ltd. and is released
177
+ under the MIT license.
data/Rakefile ADDED
@@ -0,0 +1,35 @@
1
+ require 'rake'
2
+ require 'spec/rake/spectask'
3
+
4
+ desc 'Run the specs'
5
+ namespace :spec do
6
+ namespace :plugins do
7
+ Spec::Rake::SpecTask.new(:redhillonrails_core) do |t|
8
+ t.spec_opts = ['--colour --format progress --loadby mtime --reverse']
9
+ t.spec_files = FileList['spec/**/*_spec.rb']
10
+ end
11
+ end
12
+ end
13
+
14
+
15
+ begin
16
+ require 'jeweler'
17
+ Jeweler::Tasks.new do |gemspec|
18
+ gemspec.name = "redhillonrails_core"
19
+ gemspec.summary = "A gem version of redhillonrails_core"
20
+ gemspec.description = "RedHill on Rails Core is a plugin that features to support other RedHill on Rails plugins. Those features include:
21
+ * Creating and dropping views;
22
+ * Creating and removing foreign-keys;
23
+ * Obtaining indexes directly from a model class; and
24
+ * Determining when Schema.define() is running.
25
+ "
26
+ gemspec.email = "christian@perpenduum.com"
27
+ gemspec.homepage = "http://github.com/frolic/redhillonrails_core"
28
+ gemspec.authors = ["RedHill Consulting, Pty. Ltd.", "Christian Eager"]
29
+ gemspec.add_dependency('rspec')
30
+ gemspec.add_dependency('activerecord')
31
+ # gemspec.files.exclude
32
+ end
33
+ rescue LoadError
34
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
35
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'redhillonrails_core' unless defined?(RedHillConsulting::Core)
@@ -0,0 +1,67 @@
1
+ module RedHillConsulting
2
+ end
3
+
4
+ module RedHillConsulting::Core
5
+ end
6
+
7
+ module RedHillConsulting::Core::ActiveRecord
8
+ module Base
9
+ def self.included(base)
10
+ base.extend(ClassMethods)
11
+ end
12
+
13
+ module ClassMethods
14
+ def self.extended(base)
15
+ class << base
16
+ alias_method_chain :columns, :redhillonrails_core
17
+ alias_method_chain :reset_column_information, :redhillonrails_core
18
+ alias_method_chain :abstract_class?, :redhillonrails_core
19
+ end
20
+ end
21
+
22
+ def base_class?
23
+ self == base_class
24
+ end
25
+
26
+ def abstract_class_with_redhillonrails_core?
27
+ abstract_class_without_redhillonrails_core? || !(name =~ /^Abstract/).nil?
28
+ end
29
+
30
+ def columns_with_redhillonrails_core
31
+ unless defined?(@columns) && @columns
32
+ columns_without_redhillonrails_core
33
+ cols = columns_hash
34
+ indexes.each do |index|
35
+ column_name = index.columns.reverse.detect { |name| name !~ /_id$/ } || index.columns.last
36
+ column = cols[column_name]
37
+ column.case_sensitive = index.case_sensitive?
38
+ column.unique_scope = index.columns.reject { |name| name == column_name } if index.unique
39
+ end
40
+ end
41
+ @columns
42
+ end
43
+
44
+ def pluralized_table_name(table_name)
45
+ ActiveRecord::Base.pluralize_table_names ? table_name.to_s.pluralize : table_name
46
+ end
47
+
48
+ def indexes
49
+ @indexes ||= connection.indexes(table_name, "#{name} Indexes")
50
+ end
51
+
52
+ def foreign_keys
53
+ connection.foreign_keys(table_name, "#{name} Foreign Keys")
54
+ end
55
+
56
+ def reverse_foreign_keys
57
+ connection.reverse_foreign_keys(table_name, "#{name} Reverse Foreign Keys")
58
+ end
59
+
60
+ def reset_column_information_with_redhillonrails_core
61
+ reset_column_information_without_redhillonrails_core
62
+ @indexes = nil
63
+ end
64
+
65
+ end
66
+ end
67
+ end