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

Support multiple db/views paths #237

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

smdern
Copy link

@smdern smdern commented Feb 14, 2018

I needed to use this in a rails engine and didn't want to have to copy db_views over for every rails app.

This makes it so the the definition is searched for in multiple paths when trying to call to_sql. Generator paths aren't affected. I leveraged Rails' config.paths for configuring additional db/views paths. I could change it so that the paths are apart of Scenic::Configuration, I just thought putting it in Rails.config.paths['db/views'] would pair nicely with Rails.config.paths['db/migrations'] works.

I'm able to make this work with a rails engine by using the following in engine.rb

    initializer :append_migrations do |app|
      app.config.paths["db/views"] << root.join("db/views")

      unless app.root.to_s.match? root.to_s
        config.paths["db/migrate"].expanded.each do |expanded_path|
          app.config.paths["db/migrate"] << expanded_path
        end
      end
    end

This follows a similar pattern to how migrations are found. It enables Rails
engines to define their own db/views. It finds the first entry found in the
Rails.application.config.paths["db/views"]. It still assumes Rails.root/db/views
when generating a migration.
spec/scenic/definition_spec.rb Outdated Show resolved Hide resolved
spec/scenic/definition_spec.rb Outdated Show resolved Hide resolved
spec/scenic/definition_spec.rb Outdated Show resolved Hide resolved
@smdern smdern changed the title Support multiple views paths Support multiple db/views paths Feb 14, 2018
@coding-chimp
Copy link

coding-chimp commented Apr 25, 2018

I pretty much have the same use-case. Would love to see this get merged! 👍

@MarcReniu
Copy link

Hello!! Anyone know when this PR will be merged? Thanks

Copy link
Contributor

@derekprior derekprior left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not familiar with config.paths and there's zero public docs on it. Do you have something you can point me to for this?

Further, are there methods on Definition that we no longer need? (path, full_path)?

lib/scenic/definition.rb Outdated Show resolved Hide resolved
lib/scenic/definition.rb Outdated Show resolved Hide resolved
spec/scenic/definition_spec.rb Outdated Show resolved Hide resolved
lib/scenic/definition.rb Outdated Show resolved Hide resolved
lib/scenic/definition.rb Outdated Show resolved Hide resolved
lib/scenic/definition.rb Outdated Show resolved Hide resolved
def find_definition
definition = views_paths.flat_map do |directory|
Dir.glob("#{directory}/**/#{filename}")
end.first
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
end.first
end

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be a find, but then it would only return the directory that the view exists under. This actually resolves the first matching file that is found under each view_path directory. Plus it could be possibly be nested.

Dir.glob("#{directory}/**/#{filename}")
end.first

unless definition
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be more consistent like this:

Suggested change
unless definition
if definition.empty?

@@ -0,0 +1 @@
SELECT text 'Hi' as greeting
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
SELECT text 'Hi' as greeting
SELECT text 'Hi' as greeting

spec/scenic/definition_spec.rb Outdated Show resolved Hide resolved
Rails.application.config.paths["db/views"] << fixtures_path
yield
ensure
Rails.application.config.paths["db/views"] = original
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.

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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.


def with_views_fixtures
original = Rails.application.config.paths["db/views"].to_a
fixtures_path = File.expand_path("../../fixtures/db_views", __FILE__)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/ExpandPathArguments: Use expand_path('../fixtures/db_views', dir) instead of expand_path('../../fixtures/db_views', FILE).
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.

@@ -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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.

end

it "raises an error if the file is empty" do
allow(File).to receive(:read).and_return("")
definition = Definition.new("empty_view", 1)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.

@@ -2,22 +2,51 @@

module Scenic
describe Definition do
describe "defintion_path" do
it "raises an error if file cant be found" do
definition = Definition.new("not_valid", 1)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.

@@ -2,22 +2,51 @@

module Scenic
describe Definition do
describe "defintion_path" do
it "raises an error if file cant be found" do
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.

@@ -2,22 +2,51 @@

module Scenic
describe Definition do
describe "defintion_path" do
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.

@@ -7,6 +7,8 @@ module Scenic
# @see Scenic.load
class Railtie < Rails::Railtie
initializer "scenic.load" do
Rails.application.config.paths.add("db/views")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.

@@ -28,6 +40,10 @@ def version

private

def views_paths
Rails.application.config.paths["db/views"].expanded
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.

Dir.glob("#{directory}/**/#{filename}")
end.first

unless definition
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/IfUnlessModifier: Favor modifier unless usage when having a single-line body. Another good alternative is the usage of control flow &&/||.

@smdern
Copy link
Author

smdern commented Dec 6, 2018

I'm not familiar with config.paths and there's zero public docs on it. Do you have something you can point me to for this?

https://apidock.com/rails/Rails/Engine/Configuration/paths

@smdern
Copy link
Author

smdern commented Dec 6, 2018

Further, are there methods on Definition that we no longer need? (path, full_path)?

These could probably go away. Currently they're being used in a helper for creating new views using the generator, so maybe they could instead be changed to target_path or something. It looks like path could at least go away since it's just being used by full_path

expect do
connection.update_view(
:views,
version: 1,
sql_definition: "a defintion")
sql_definition: "a definition")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
Layout/MultilineMethodCallBraceLayout: Closing method call brace must be on the line after the last argument when opening brace is on a separate line from the first argument.

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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.

@@ -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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.

@@ -108,7 +108,7 @@ module Scenic
end

it "updates a view from a text definition" do
sql_definition = "a defintion"
sql_definition = "a definition"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.

expect do
connection.create_view :foo, version: 1, sql_definition: "a defintion"
connection.create_view :foo, version: 1, sql_definition: "a definition"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
Metrics/LineLength: Line is too long. [81/80]

@@ -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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.


connection.create_view(:views, sql_definition: sql_definition)

expect(Scenic.database).to have_received(:create_view)
.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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
Metrics/LineLength: Line is too long. [94/80]

@@ -22,15 +22,15 @@ module Scenic
end

it "creates a view from a text definition" do
sql_definition = "a defintion"
sql_definition = "a definition"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.

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}")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Metrics/LineLength: Line is too long. [83/80]

@smdern smdern force-pushed the support-multiple-views-paths branch from a7817a3 to ff5382a Compare December 6, 2018 17:07
@vladimirtemnikov
Copy link

Hi, really waiting for this 👍

@tomasc
Copy link

tomasc commented Jul 18, 2019

Hi, would be great to have this merged! Just ran into this when trying to use scenic from engines.

@derekprior
Copy link
Contributor

Rails 6 adds native support for multiple databases. At this point, I’m inclined to see how we would be able to work with that.

@tomasc
Copy link

tomasc commented Jul 18, 2019

@derekprior an alternative approach would be to make the full_path used in definition.rb configurable – by way of being able to pass root_path in the configuration:

Scenic.configure do |config|
  config.root_path = MyEngine.root
end

In any case, the current setup prevents the gem from being used from within Rails engines as it looks up the db/views under the engine's test app. This is not related to multi-database support in Rails 6 I believe.

Would you be interested in a PR implementing the above?

@huarmenta
Copy link

I agree with @tomasc , it would be nice to have a configuration called root_path like the one that @tomasc propose or views_path to be more specific to set the views path, i thinks this is a better approach than the one on this PR because it is more flexible than overriding a definition.

@derekprior Any provisional solution on how to use scenic inside an engine without copying files?

@derekprior derekprior changed the base branch from master to main June 18, 2020 15:03
@tomasc tomasc mentioned this pull request Sep 16, 2020
@derekprior
Copy link
Contributor

Long time no review on this PR. We've had a number of PRs for this feature (see view-paths ) so I think it merits further consideration. I think this is the closest to something we could accept as it supports multiple search paths. I hope to look at this closer in the next couple of weeks.

@calebhearth calebhearth added this to the 2.0 milestone Jan 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants