mysql_view_support 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ class SqlViewMigrationGenerator < Rails::Generator::NamedBase
2
+ def manifest
3
+ record do |m|
4
+ m.migration_template 'migration.rb', 'db/views'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ class Create<%= class_name.underscore.camelize %>Migration < ActiveRecord::Migration
2
+ def self.up
3
+ update_view :<%= class_name.underscore.pluralize %> do
4
+ select_statement = ""
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,55 @@
1
+ require_dependency 'active_record/connection_adapters/mysql_adapter'
2
+
3
+ module ActiveRecord
4
+ class Base
5
+ class << self
6
+ def mysql_with_views_connection(config) # :nodoc:
7
+ ConnectionAdapters::MysqlWithViewsAdapter.new(config)
8
+ end
9
+ end
10
+ end
11
+
12
+ class ConnectionAdapters::MysqlWithViewsAdapter < DelegateClass(ActiveRecord::ConnectionAdapters::MysqlAdapter)
13
+ attr_reader :view_options
14
+ def initialize(config)
15
+ super ActiveRecord::Base.mysql_connection(config)
16
+ @view_options = (config.symbolize_keys[:view_options] || {}).symbolize_keys.freeze
17
+ end
18
+
19
+ def create_view(name, column_names = nil, options = {})
20
+ raise ArgumentError, "You must provide the SQL statement that defines the view." unless block_given?
21
+ select_statement = yield
22
+ command = ["CREATE"]
23
+ command << "OR REPLACE" if options[:force]
24
+ command << "VIEW #{quote_table_name(name)}"
25
+ command << "(" + [column_names].flatten.join(", ") + ")" if column_names
26
+ command << "AS #{select_statement}"
27
+ execute command.join(" ")
28
+ end
29
+
30
+ def update_view(name, column_names = nil, options = {}, &block)
31
+ create_view name, column_names, options.merge(:force => true), &block
32
+ end
33
+
34
+ def drop_view(name)
35
+ execute "DROP VIEW #{quote_table_name(name)}"
36
+ end
37
+
38
+ def views(name = nil) #:nodoc:
39
+ tables = []
40
+ result = execute("SHOW FULL TABLES", name)
41
+ result.each { |field| tables << field[0] if field[1] == 'VIEW' }
42
+ result.free
43
+ tables
44
+ end
45
+
46
+ def pk_and_sequence_for(table)
47
+ if table_key = super(table)
48
+ table_key
49
+ elsif views.include?( table.to_s ) and columns(table).any?{|col| col.name == 'id'}
50
+ view_key = ['id', nil]
51
+ end
52
+ end
53
+
54
+ end
55
+ end
data/tasks/views.rake ADDED
@@ -0,0 +1,62 @@
1
+ unless defined? remove_task
2
+ Rake::TaskManager.class_eval do
3
+ def remove_task(task_name)
4
+ @tasks.delete(task_name.to_s)
5
+ end
6
+ end
7
+
8
+ def remove_task(task_name)
9
+ Rake.application.remove_task(task_name)
10
+ end
11
+ end
12
+
13
+ alias drop_database_without_view_support drop_database
14
+ def drop_database(config)
15
+ drop_database_without_view_support(config.merge('adapter' => config['adapter'].gsub(/_with_views/, "")))
16
+ end
17
+
18
+ alias create_database_without_view_support create_database
19
+ def create_database(config)
20
+ create_database_without_view_support(config.merge('adapter' => config['adapter'].gsub(/_with_views/, "")))
21
+ end
22
+
23
+ namespace :db do
24
+ namespace :views do
25
+ desc "Run views migration from db/views"
26
+ task :update => :environment do
27
+ view_migration_classes = Dir.glob(File.join(Rails.root, "db", "views", "*.rb")).map{|view_migration|
28
+ if File.basename(view_migration) =~ /[0-9]+_([^.]+).rb/
29
+ require view_migration
30
+ view_migration_class = "create_#{$1}_migration".camelize.constantize
31
+ end
32
+ }
33
+
34
+ view_migration_classes.each{|mc|
35
+ mc.migrate(:up)
36
+ }
37
+ end
38
+ end
39
+ namespace :test do
40
+ original_purge_task = Rake::Task["db:test:purge"]
41
+ remove_task "db:test:purge"
42
+
43
+ desc "Empty the test database"
44
+ task :purge => :environment do
45
+ abcs = ActiveRecord::Base.configurations
46
+ if abcs["test"]["adapter"] == "mysql_with_views"
47
+ ActiveRecord::Base.establish_connection(:test)
48
+ ActiveRecord::Base.connection.recreate_database(abcs["test"]["database"], abcs["test"])
49
+ else
50
+ original_purge_task.invoke
51
+ end
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ # We need to invoke the db:views:update task IMIDIATELY after the db:migrate task.
58
+ # Failure to do so will cause broken schema dumps to happen.
59
+ Rake::Task["db:migrate"].actions.unshift lambda{Rake::Task["db:views:update"].invoke}
60
+
61
+
62
+
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mysql_view_support
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Tom Lea
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-08 00:00:00 +00:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: contrib@tomlea.co.uk
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - tasks/views.rake
26
+ - generators/sql_view_migration/sql_view_migration_generator.rb
27
+ - generators/sql_view_migration/templates/migration.rb
28
+ - lib/active_record/connection_adapters/mysql_with_views_adapter.rb
29
+ has_rdoc: true
30
+ homepage: http://labs.reevoo.com
31
+ licenses: []
32
+
33
+ post_install_message:
34
+ rdoc_options: []
35
+
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: "0"
43
+ version:
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ requirements: []
51
+
52
+ rubyforge_project:
53
+ rubygems_version: 1.3.5
54
+ signing_key:
55
+ specification_version: 3
56
+ summary: Provides view support to rails.
57
+ test_files: []
58
+