module RailsSqlViews4 module SchemaDumper def self.included(base) base.alias_method_chain :trailer, :views base.alias_method_chain :dump, :views base.alias_method_chain :tables, :views_excluded # A list of views which should not be dumped to the schema. # Acceptable values are strings as well as regexp. # This setting is only used if ActiveRecord::Base.schema_format == :ruby base.cattr_accessor :ignore_views base.ignore_views = [] # Optional: specify the order that in which views are created. # This allows views to depend on and include fields from other views. # It is not necessary to specify all the view names, just the ones that # need to be created first base.cattr_accessor :view_creation_order base.view_creation_order = [] end def trailer_with_views(stream) # do nothing...we'll call this later end # Add views to the end of the dump stream def dump_with_views(stream) dump_without_views(stream) begin if @connection.supports_views? views(stream) end rescue => e if ActiveRecord::Base.logger ActiveRecord::Base.logger.error "Unable to dump views: #{e}" else raise e end end trailer_without_views(stream) stream end # Add views to the stream def views(stream) if view_creation_order.empty? sorted_views = @connection.views.sort else # set union, merge by joining arrays, removing dups # this will float the view name sin view_creation_order to the top # without requiring all the views to be specified sorted_views = view_creation_order | @connection.views end sorted_views.each do |v| next if [ActiveRecord::Migrator.schema_migrations_table_name, ignore_views].flatten.any? do |ignored| case ignored when String then v == ignored when Symbol then v == ignored.to_s when Regexp then v =~ ignored else raise StandardError, 'ActiveRecord::SchemaDumper.ignore_views accepts an array of String and / or Regexp values.' end end view(v, stream) end end # Add the specified view to the stream def view(view, stream) columns = @connection.columns(view).collect { |c| c.name } begin v = StringIO.new v.print " create_view #{view.inspect} " v.print ", #{@connection.view_select_statement(view).dump}" v.print ", :force => true" v.puts " do |v|" columns.each do |column| v.print " v.column :#{column}" v.puts end v.puts " end" v.puts v.rewind stream.print v.read rescue => e stream.puts "# Could not dump view #{view.inspect} because of following #{e.class}" stream.puts "# #{e.message}" stream.puts end stream end def tables_with_views_excluded(stream) @connection.base_tables.sort.each do |tbl| next if [ActiveRecord::Migrator.schema_migrations_table_name, ignore_tables].flatten.any? do |ignored| case ignored when String then tbl == ignored when Regexp then tbl =~ ignored else raise StandardError, 'ActiveRecord::SchemaDumper.ignore_tables accepts an array of String and / or Regexp values.' end end table(tbl, stream) end end end end