diff options
Diffstat (limited to 'activerecord/test/cases/view_test.rb')
-rw-r--r-- | activerecord/test/cases/view_test.rb | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/activerecord/test/cases/view_test.rb b/activerecord/test/cases/view_test.rb new file mode 100644 index 0000000000..36b9df7ba5 --- /dev/null +++ b/activerecord/test/cases/view_test.rb @@ -0,0 +1,222 @@ +# frozen_string_literal: true + +require "cases/helper" +require "models/book" +require "support/schema_dumping_helper" + +module ViewBehavior + include SchemaDumpingHelper + extend ActiveSupport::Concern + + included do + fixtures :books + end + + class Ebook < ActiveRecord::Base + self.table_name = "ebooks'" + self.primary_key = "id" + end + + def setup + super + @connection = ActiveRecord::Base.connection + create_view "ebooks'", <<~SQL + SELECT id, name, status FROM books WHERE format = 'ebook' + SQL + end + + def teardown + super + drop_view "ebooks'" + end + + def test_reading + books = Ebook.all + assert_equal [books(:rfr).id], books.map(&:id) + assert_equal ["Ruby for Rails"], books.map(&:name) + end + + def test_views + assert_equal [Ebook.table_name], @connection.views + end + + def test_view_exists + view_name = Ebook.table_name + assert @connection.view_exists?(view_name), "'#{view_name}' view should exist" + end + + def test_table_exists + view_name = Ebook.table_name + assert_not @connection.table_exists?(view_name), "'#{view_name}' table should not exist" + end + + def test_views_ara_valid_data_sources + view_name = Ebook.table_name + assert @connection.data_source_exists?(view_name), "'#{view_name}' should be a data source" + end + + def test_column_definitions + assert_equal([["id", :integer], + ["name", :string], + ["status", :integer]], Ebook.columns.map { |c| [c.name, c.type] }) + end + + def test_attributes + assert_equal({ "id" => 2, "name" => "Ruby for Rails", "status" => 0 }, + Ebook.first.attributes) + end + + def test_does_not_assume_id_column_as_primary_key + model = Class.new(ActiveRecord::Base) do + self.table_name = "ebooks'" + end + assert_nil model.primary_key + end + + def test_does_not_dump_view_as_table + schema = dump_table_schema "ebooks'" + assert_no_match %r{create_table "ebooks'"}, schema + end + + private + def quote_table_name(name) + @connection.quote_table_name(name) + end +end + +if ActiveRecord::Base.connection.supports_views? + class ViewWithPrimaryKeyTest < ActiveRecord::TestCase + include ViewBehavior + + private + def create_view(name, query) + @connection.execute "CREATE VIEW #{quote_table_name(name)} AS #{query}" + end + + def drop_view(name) + @connection.execute "DROP VIEW #{quote_table_name(name)}" if @connection.view_exists? name + end + end + + class ViewWithoutPrimaryKeyTest < ActiveRecord::TestCase + include SchemaDumpingHelper + fixtures :books + + class Paperback < ActiveRecord::Base; end + + setup do + @connection = ActiveRecord::Base.connection + @connection.execute <<~SQL + CREATE VIEW paperbacks + AS SELECT name, status FROM books WHERE format = 'paperback' + SQL + end + + teardown do + @connection.execute "DROP VIEW paperbacks" if @connection.view_exists? "paperbacks" + end + + def test_reading + books = Paperback.all + assert_equal ["Agile Web Development with Rails"], books.map(&:name) + end + + def test_views + assert_equal [Paperback.table_name], @connection.views + end + + def test_view_exists + view_name = Paperback.table_name + assert @connection.view_exists?(view_name), "'#{view_name}' view should exist" + end + + def test_table_exists + view_name = Paperback.table_name + assert_not @connection.table_exists?(view_name), "'#{view_name}' table should not exist" + end + + def test_column_definitions + assert_equal([["name", :string], + ["status", :integer]], Paperback.columns.map { |c| [c.name, c.type] }) + end + + def test_attributes + assert_equal({ "name" => "Agile Web Development with Rails", "status" => 2 }, + Paperback.first.attributes) + end + + def test_does_not_have_a_primary_key + assert_nil Paperback.primary_key + end + + def test_does_not_dump_view_as_table + schema = dump_table_schema "paperbacks" + assert_no_match %r{create_table "paperbacks"}, schema + end + end + + # sqlite dose not support CREATE, INSERT, and DELETE for VIEW + if current_adapter?(:Mysql2Adapter, :SQLServerAdapter, :PostgreSQLAdapter) + + class UpdateableViewTest < ActiveRecord::TestCase + self.use_transactional_tests = false + fixtures :books + + class PrintedBook < ActiveRecord::Base + self.primary_key = "id" + end + + setup do + @connection = ActiveRecord::Base.connection + @connection.execute <<~SQL + CREATE VIEW printed_books + AS SELECT id, name, status, format FROM books WHERE format = 'paperback' + SQL + end + + teardown do + @connection.execute "DROP VIEW printed_books" if @connection.view_exists? "printed_books" + end + + def test_update_record + book = PrintedBook.first + book.name = "AWDwR" + book.save! + book.reload + assert_equal "AWDwR", book.name + end + + def test_insert_record + PrintedBook.create! name: "Rails in Action", status: 0, format: "paperback" + + new_book = PrintedBook.last + assert_equal "Rails in Action", new_book.name + end + + def test_update_record_to_fail_view_conditions + book = PrintedBook.first + book.format = "ebook" + book.save! + + assert_raises ActiveRecord::RecordNotFound do + book.reload + end + end + end + end # end of `if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter, :SQLServerAdapter)` +end # end of `if ActiveRecord::Base.connection.supports_views?` + +if ActiveRecord::Base.connection.supports_materialized_views? + class MaterializedViewTest < ActiveRecord::PostgreSQLTestCase + include ViewBehavior + + private + def create_view(name, query) + @connection.execute "CREATE MATERIALIZED VIEW #{quote_table_name(name)} AS #{query}" + end + + def drop_view(name) + @connection.execute "DROP MATERIALIZED VIEW #{quote_table_name(name)}" if @connection.view_exists? name + end + end +end |