Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow to configure definition path #321

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ class <%= migration_class_name %> < <%= activerecord_migration_class %>
def change
<%- if materialized? -%>
update_view <%= formatted_plural_name %>,
version: <%= version %>,
revert_to_version: <%= previous_version %>,
version: <%= definition.version %>,
revert_to_version: <%= previous_definition.version %>,
materialized: <%= no_data? ? "{ no_data: true }" : true %>
<%- else -%>
update_view <%= formatted_plural_name %>, version: <%= version %>, revert_to_version: <%= previous_version %>
update_view <%= formatted_plural_name %>,
version: <%= definition.version %>,
revert_to_version: <%= previous_definition.version %>
<%- end -%>
end
end
38 changes: 14 additions & 24 deletions lib/generators/scenic/view/view_generator.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
require "rails/generators"
require "rails/generators/active_record"
require "generators/scenic/materializable"
require "scenic/definition"
require "scenic/definitions"

module Scenic
module Generators
Expand All @@ -11,16 +13,16 @@ class ViewGenerator < Rails::Generators::NamedBase
source_root File.expand_path("templates", __dir__)

def create_views_directory
unless views_directory_path.exist?
empty_directory(views_directory_path)
unless Scenic.configuration.definitions_path.exist?
empty_directory(Scenic.configuration.definitions_path)
end
end

def create_view_definition
if creating_new_view?
create_file definition.path
else
copy_file previous_definition.full_path, definition.full_path
copy_file previous_definition.path, definition.path
end
end

Expand All @@ -31,6 +33,7 @@ def create_migration_file
"db/migrate/create_#{plural_file_name}.rb",
)
else
version = definition.version
migration_template(
"db/migrate/update_view.erb",
"db/migrate/update_#{plural_file_name}_to_version_#{version}.rb",
Expand All @@ -43,22 +46,11 @@ def self.next_migration_number(dir)
end

no_tasks do
def previous_version
@previous_version ||=
Dir.entries(views_directory_path)
.map { |name| version_regex.match(name).try(:[], "version").to_i }
.max
end

def version
@version ||= destroying? ? previous_version : previous_version.next
end

def migration_class_name
if creating_new_view?
"Create#{class_name.tr('.', '').pluralize}"
else
"Update#{class_name.pluralize}ToVersion#{version}"
"Update#{class_name.pluralize}ToVersion#{definition.version}"
end
end

Expand All @@ -79,24 +71,22 @@ def file_name
super.tr(".", "_")
end

def views_directory_path
@views_directory_path ||= Rails.root.join("db", "views")
end

def version_regex
/\A#{plural_file_name}_v(?<version>\d+)\.sql\z/
def definitions
@definitions ||= Scenic::Definitions.new(plural_file_name)
end

def creating_new_view?
previous_version.zero?
definitions.none?
end

def definition
previous_version = previous_definition.version
version = destroying? ? previous_version : previous_version.next
Scenic::Definition.new(plural_file_name, version)
end

def previous_definition
Scenic::Definition.new(plural_file_name, previous_version)
definitions.max || Scenic::Definition.new(plural_file_name, 0)
end

def destroying?
Expand All @@ -120,7 +110,7 @@ def create_view_options
end

def destroying_initial_view?
destroying? && version == 1
destroying? && definition.version == 1
end
end
end
Expand Down
1 change: 0 additions & 1 deletion lib/scenic.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
require "scenic/configuration"
require "scenic/adapters/postgres"
require "scenic/command_recorder"
require "scenic/definition"
require "scenic/railtie"
require "scenic/schema_dumper"
require "scenic/statements"
Expand Down
11 changes: 10 additions & 1 deletion lib/scenic/configuration.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require_relative "adapters/postgres"

module Scenic
class Configuration
# The Scenic database adapter instance to use when executing SQL.
Expand All @@ -6,8 +8,15 @@ class Configuration
# @return Scenic adapter
attr_accessor :database

# The full path where is stored views definition sql files.
#
# Defaults to `Rails.root.join("db", "views")` an instance of {Pathname}
# @return the path
attr_accessor :definitions_path

def initialize
@database = Scenic::Adapters::Postgres.new
self.database = Scenic::Adapters::Postgres.new
self.definitions_path = Rails.root.join("db", "views")
end
end

Expand Down
18 changes: 9 additions & 9 deletions lib/scenic/definition.rb
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
module Scenic
# @api private
class Definition
include Comparable

attr_reader :name, :version

def initialize(name, version)
@name = name
@version = version.to_i
end

def to_sql
File.read(full_path).tap do |content|
File.read(path).tap do |content|
if content.empty?
raise "Define view query in #{path} before migrating."
end
end
end

def full_path
Rails.root.join(path)
end

def path
File.join("db", "views", filename)
Scenic.configuration.definitions_path.join(filename)
end

def version
@version.to_s.rjust(2, "0")
def <=>(other)
version <=> other.version
end

private

def filename
"#{@name.to_s.tr('.', '_')}_v#{version}.sql"
"#{name.to_s.tr('.', '_')}_v#{version.to_s.rjust(2, '0')}.sql"
end
end
end
34 changes: 34 additions & 0 deletions lib/scenic/definitions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
require_relative "definition"

module Scenic
# @api private
class Definitions
include Enumerable

attr_reader :name, :views_directory_path

def initialize(name)
@name = name
end

def each
versions.each do |version|
yield Scenic::Definition.new(name, version)
end
end

def versions
@versions ||= Dir.entries(Scenic.configuration.definitions_path)
.map { |filename| /\A#{name}_v(?<version>\d+)\.sql\z/.match(filename) }
.compact
.map { |match| match["version"].to_i }
.sort
end

private

def version_regex
/\A#{name}_v(?<version>\d+)\.sql\z/
end
end
end
1 change: 1 addition & 0 deletions lib/scenic/statements.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require_relative "definition"
module Scenic
# Methods that are made available in migrations for managing Scenic views.
module Statements
Expand Down
1 change: 1 addition & 0 deletions spec/generators/scenic/view/view_generator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
allow(Dir).to receive(:entries).and_return(["aired_episodes_v01.sql"])

run_generator ["aired_episode", "--materialized"]

migration = migration_file(
"db/migrate/update_aired_episodes_to_version_2.rb",
)
Expand Down
17 changes: 5 additions & 12 deletions spec/scenic/definition_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ module Scenic

describe "path" do
it "returns a sql file in db/views with padded version and view name" do
expected = "db/views/searches_v01.sql"
expected = Rails.root.join("db/views/searches_v01.sql")

definition = Definition.new("searches", 1)

Expand All @@ -32,30 +32,23 @@ module Scenic

it "handles schema qualified view names" do
definition = Definition.new("non_public.searches", 1)
expected = Rails.root.join("db/views/non_public_searches_v01.sql")

expect(definition.path).to eq "db/views/non_public_searches_v01.sql"
end
end

describe "full_path" do
it "joins the path with Rails.root" do
definition = Definition.new("searches", 15)

expect(definition.full_path).to eq Rails.root.join(definition.path)
expect(definition.path).to eq expected
end
end

describe "version" do
it "pads the version number with 0" do
definition = Definition.new(:_, 1)

expect(definition.version).to eq "01"
expect(definition.version).to eq 1
end

it "doesn't pad more than 2 characters" do
definition = Definition.new(:_, 15)

expect(definition.version).to eq "15"
expect(definition.version).to eq 15
end
end
end
Expand Down
18 changes: 15 additions & 3 deletions spec/support/generator_spec_setup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,23 @@
require "ammeter/init"

RSpec.configure do |config|
rails_root = Rails.root
fake_rails_root = Pathname.new(File.expand_path("../../tmp", __dir__))

config.before(:example, :generator) do
fake_rails_root = File.expand_path("../../tmp", __dir__)
allow(Rails).to receive(:root).and_return(Pathname.new(fake_rails_root))
allow(Rails).to receive(:root).and_return(fake_rails_root)

destination fake_rails_root
destination fake_rails_root.to_s
prepare_destination

Scenic.configure do |configuration|
configuration.definitions_path = fake_rails_root.join("db", "views")
end
end

config.after(:example, :generator) do
Scenic.configure do |configuration|
configuration.definitions_path = rails_root.join("db", "views")
end
end
end
6 changes: 3 additions & 3 deletions spec/support/view_definition_helpers.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
module ViewDefinitionHelpers
def with_view_definition(name, version, schema)
definition = Scenic::Definition.new(name, version)
FileUtils.mkdir_p(File.dirname(definition.full_path))
File.open(definition.full_path, "w") { |f| f.write(schema) }
FileUtils.mkdir_p(File.dirname(definition.path))
File.open(definition.path, "w") { |f| f.write(schema) }
yield
ensure
FileUtils.rm_f(definition.full_path)
FileUtils.rm_f(definition.path)
end
end