diff --git a/lib/scenic/definition.rb b/lib/scenic/definition.rb index d5f313c3..525c5cba 100644 --- a/lib/scenic/definition.rb +++ b/lib/scenic/definition.rb @@ -7,13 +7,17 @@ def initialize(name, version) end def to_sql - File.read(full_path).tap do |content| + File.read(definition_path).tap do |content| if content.empty? raise "Define view query in #{path} before migrating." end end end + def definition_path + resolve_definition || raise("Unable to locate #{filename} in #{views_paths}") + end + def full_path Rails.root.join(path) end @@ -28,6 +32,16 @@ def version private + def resolve_definition + views_paths.flat_map do |directory| + Dir.glob("#{directory}/**/#{filename}") + end.first + end + + def views_paths + Rails.application.config.paths["db/views"].expanded + end + def filename "#{@name}_v#{version}.sql" end diff --git a/lib/scenic/railtie.rb b/lib/scenic/railtie.rb index 8f659583..84ed2aea 100644 --- a/lib/scenic/railtie.rb +++ b/lib/scenic/railtie.rb @@ -7,6 +7,8 @@ module Scenic # @see Scenic.load class Railtie < Rails::Railtie initializer "scenic.load" do + Rails.application.config.paths.add("db/views") + ActiveSupport.on_load :active_record do Scenic.load end diff --git a/spec/fixtures/db_views/empty_view_v01.sql b/spec/fixtures/db_views/empty_view_v01.sql new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/db_views/searches_v01.sql b/spec/fixtures/db_views/searches_v01.sql new file mode 100644 index 00000000..63c22a6f --- /dev/null +++ b/spec/fixtures/db_views/searches_v01.sql @@ -0,0 +1 @@ +SELECT text 'Hi' as greeting \ No newline at end of file diff --git a/spec/scenic/definition_spec.rb b/spec/scenic/definition_spec.rb index ac39f517..872de57d 100644 --- a/spec/scenic/definition_spec.rb +++ b/spec/scenic/definition_spec.rb @@ -2,22 +2,51 @@ module Scenic describe Definition do + describe "definition_path" do + it "raises an error if file cant be found" do + definition = Definition.new("not_valid", 1) + + expect do + definition.definition_path + end.to raise_error RuntimeError, /Unable to locate not_valid_v01.sql/ + end + + it "looks inside Rails.root db/views" do + definition = Definition.new("not_valid", 1) + + expect do + definition.definition_path + end.to raise_error RuntimeError, /spec\/dummy\/db\/views/ + end + + it "looks inside configured additional paths" do + with_views_fixtures do + definition = Definition.new("empty_view", 1) + + expect(definition.definition_path).to be + end + end + end + describe "to_sql" do it "returns the content of a view definition" do sql_definition = "SELECT text 'Hi' as greeting" - allow(File).to receive(:read).and_return(sql_definition) - definition = Definition.new("searches", 1) + with_views_fixtures do + definition = Definition.new("searches", 1) - expect(definition.to_sql).to eq sql_definition + expect(definition.to_sql).to eq sql_definition + end end it "raises an error if the file is empty" do - allow(File).to receive(:read).and_return("") + definition = Definition.new("empty_view", 1) - expect do - Definition.new("searches", 1).to_sql - end.to raise_error RuntimeError + with_views_fixtures do + expect do + definition.to_sql + end.to raise_error RuntimeError + end end end @@ -52,5 +81,14 @@ module Scenic expect(definition.version).to eq "15" end end + + def with_views_fixtures + original = Rails.application.config.paths["db/views"].to_a + fixtures_path = File.expand_path("../../fixtures/db_views", __FILE__) + Rails.application.config.paths["db/views"] << fixtures_path + yield + ensure + Rails.application.config.paths["db/views"] = original + end end end diff --git a/spec/scenic/statements_spec.rb b/spec/scenic/statements_spec.rb index 487232a9..3b2cd241 100644 --- a/spec/scenic/statements_spec.rb +++ b/spec/scenic/statements_spec.rb @@ -22,7 +22,7 @@ module Scenic end it "creates a view from a text definition" do - sql_definition = "a defintion" + sql_definition = "a definition" connection.create_view(:views, sql_definition: sql_definition) @@ -30,7 +30,7 @@ module Scenic .with(:views, sql_definition) end - it "creates version 1 of the view if neither version nor sql_defintion are provided" do + it "creates version 1 of the view if neither version nor sql_definition are provided" do version = 1 definition_stub = instance_double("Definition", to_sql: "foo") allow(Definition).to receive(:new). @@ -43,9 +43,9 @@ module Scenic with(:views, definition_stub.to_sql) end - it "raises an error if both version and sql_defintion are provided" do + it "raises an error if both version and sql_definition are provided" do expect do - connection.create_view :foo, version: 1, sql_definition: "a defintion" + connection.create_view :foo, version: 1, sql_definition: "a definition" end.to raise_error ArgumentError end end @@ -108,7 +108,7 @@ module Scenic end it "updates a view from a text definition" do - sql_definition = "a defintion" + sql_definition = "a definition" connection.update_view(:name, sql_definition: sql_definition) @@ -144,18 +144,18 @@ module Scenic with(:name, definition.to_sql, no_data: true) end - it "raises an error if not supplied a version or sql_defintion" do + it "raises an error if not supplied a version or sql_definition" do expect { connection.update_view :views }.to raise_error( ArgumentError, /sql_definition or version must be specified/) end - it "raises an error if both version and sql_defintion are provided" do + it "raises an error if both version and sql_definition are provided" do expect do connection.update_view( :views, version: 1, - sql_definition: "a defintion") + sql_definition: "a definition") end.to raise_error ArgumentError, /cannot both be set/ end end