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

Adds environment boolean checks #302

Merged
merged 1 commit into from Oct 13, 2017
Merged

Conversation

eliasjpr
Copy link
Contributor

@eliasjpr eliasjpr commented Oct 12, 2017

Amber currently ships with 3 different environments: development, test
and production.

As a developer I would like to sometimes run code conditionally
depending on the environment that the application is.

if Amber.env.development?
  # ... code here ...
end

This PR addresses the issue by creating a Amber::Env module that
contains 3 module methods:

Amber.env.development?
Amber.env.test?
Amber.env.production?
Amber.env.integration?
Amber.env.staging?
Amber.env.sandbox?

Amber.env.in? %w(development test)
Amber.env.in? %i(development test)

Amber.env.is? "test"
Amber.env.is? :test

With the changes in this PR a developer should be able to call the
appropriate method to check for the desired environment.

@elorest
Copy link
Member

elorest commented Oct 12, 2017

Could we add it directly to Amber like it is in Rails. So Amber.env Amber.development? etc.

@eliasjpr
Copy link
Contributor Author

eliasjpr commented Oct 12, 2017

I considered Amber.development? and do like the aesthetics of this, but then I thought that if we move the check all the way, would people expect all the settings to live in this scope? So I opted to be safe by introducing the Amber::Env I consider the module approach to be more appropriate Amber::Env since it allow us to extend the module we can more methods and stuff pertinent to the Env here if we wish to in the future.

@elorest
Copy link
Member

elorest commented Oct 12, 2017

I agree we shouldn't mimic or copy rails in a lot of things, but in this case I do like the way rails does it. Rails.env automatically calls to_s. This is the same for every instance in crystal and ruby.
https://carc.in/#/r/2w6a

You might be right though. If you prefer it this way I'll approve it.

@veelenga
Copy link
Contributor

veelenga commented Oct 12, 2017

@eliasjpr looks nice 👍

What about user-defined environments? staging, integration, sandbox, beta etc. often can be seen in web apps. I understand it is not possible to dynamically generate .staging? method, but it could be good to have some kind of fallback for this, for example, Amber::Env.is? "staging" or Amber::Env["staging"]? or something more friendly...

@migeorge
Copy link

@eliasjpr The implementation looks good 👍. FYI there is a test failing though.

@drujensen
Copy link
Member

@veelenga really like the Amber::Env.is? :staging idea.

@veelenga
Copy link
Contributor

veelenga commented Oct 12, 2017

Another use case might be to check for the inclusion in a list of environments.

Amber::Env.in? %w(development test) or
Amber::Env.in? %i(development test)

which is more or less consistent with Amber::Env.is?. WDYT?

@eliasjpr
Copy link
Contributor Author

eliasjpr commented Oct 12, 2017

I have added the in? and is? methods as suggested @veelenga Thanks, this is a great addition

It would be nice to populate the ENVIRONMENTS constant at precompile time appending the contents of the ./config/environments files present. This way the ENVIRONMENTS will contain the all the environments defined.

I attempted to approach the problem with method_missing and converting the Env to a class, so the call would look something like Amber::Env.new.development?. method_missing will not work in modules, the macro is invoked when a method call on an instance fails, modules cannot be instantiated. What do you guys think about Amber::Env.new.development? it works nice for all environments and there is no need for the ENVIRONMENTS constant, but the aesthetics of the call is too verbose in my opinion.

I'm going to look at the failing specs.

@eliasjpr eliasjpr force-pushed the ep/evironment-check-methods branch 4 times, most recently from b482070 to 10ba651 Compare October 12, 2017 19:38
Copy link
Member

@elorest elorest left a comment

Choose a reason for hiding this comment

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

My only concerns here are that Amber::Env.is?("development") doesn't seem like much of an improvement over ENV["AMBER_ENV"] == "development" which already works. It might seem cleaner this way, but could we just create methods which return the existing VAR instead of storing the value multiple times?

@@ -0,0 +1,27 @@
module Amber
module Env
ENVIRONMENTS = %w(development test production)
Copy link
Member

Choose a reason for hiding this comment

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

These could be dynamically defined at compile time by looking at file names in ./config/environments

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you have an example on how to do this? I got stuck...

Copy link
Member

Choose a reason for hiding this comment

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

Yeah. Give me a second.

Copy link
Member

Choose a reason for hiding this comment

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

There are 2 ways to do this.

Eval

This way requires less files but isn't quite as fast for compile time.

ENVIRONMENTS = {{ system("crystal eval \'puts Dir.glob(\"./config/environments/**\").map(&.split(/[\\/\\.]/)[-2]?)\'") }}

New File using Macro Run

This way is a bit faster as the compile can cache the compiled environment_names.cr

# environment_names.cr
puts Dir.glob("./config/environments/**").map(&.split(/[\/\.]/)[-2]?)

Then call ENVIRONMENTS = {{run("./path/to/environment_names.cr")}} in env.cr.

end

def self.current
Settings.env.not_nil!.downcase
Copy link
Member

Choose a reason for hiding this comment

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

Store env here is just duplicating values already stored in ENV["AMBER_ENV"]. Is this necessary? I would rather current just wrap ENV["AMBER_ENV"] and return it's values.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I would trust the Settings.env more than the ENV["AMBER_ENV"] since the latter can be modified outside of the APP after it has been started. What do you think?

Copy link
Member

@elorest elorest Oct 12, 2017

Choose a reason for hiding this comment

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

ENV["AMBER_ENV"] is defined by the env var at runtime and can't be changed outside of the app afterwards. Since the env var is where this value originates I forsee some possible issues where they could get out of sync and cause confusion if they're not pointing the same value.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We should be fine using Settings.env since its pointing to ENV["AMBER_ENV"]. See https://github.com/amberframework/amber/pull/302/files#diff-b8648cef4f24d74b1b3b0cee94f1c9deR15

Copy link
Member

Choose a reason for hiding this comment

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

Ok. I'm ok with that then.

@eliasjpr
Copy link
Contributor Author

Updates.

@elorest was right by using the Rails way it turned out to be very clean and feature rich

kudos @elorest 🎉

This now supports the following.

Amber.env.development?
Amber.env.test?
Amber.env.production?
Amber.env.integration?
Amber.env.staging?
Amber.env.sandbox?

Amber.env.in? %w(development test)
Amber.env.in? %i(development test)

Amber.env.is? "test"
Amber.env.is? :test

@@ -0,0 +1,47 @@
require "../../../spec_helper"

describe Amber::Server do
Copy link
Member

Choose a reason for hiding this comment

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

I like the idea of moving this under scripts. Would it be possible to move it and maintain git file history though instead of adding a new file?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can undo the commit, and you can go ahead and move it in a separate PR. WDYT?

@eliasjpr eliasjpr force-pushed the ep/evironment-check-methods branch 2 times, most recently from 2b2ca30 to 9d502a4 Compare October 13, 2017 00:40
Amber currently ships with 3 different environments: development, test
and production.

As a developer I would like to sometimes run code conditionally
depending on the environment that the application is.

```crystal
if Amber.env.development?
  # ... code here ...
end

```

This PR addresses the issue by creating a Amber::Env module that
contains 3 module methods:

```crystal
Amber.env.development?
Amber.env.test?
Amber.env.production?
Amber.env.integration?
Amber.env.staging?
Amber.env.sandbox?

Amber.env.in? %w(development test)
Amber.env.in? %i(development test)

Amber.env.is? "test"
Amber.env.is? :test
```

With the changes in this PR a developer should be able to call the
appropriate method to check for the desired environment.

Adds Additional Module methods

`in?` and `is?` methods to check for inclusion of the environments

Uses rails style for Amber environment checks
@eliasjpr eliasjpr merged commit 14f56cf into master Oct 13, 2017
@eliasjpr eliasjpr deleted the ep/evironment-check-methods branch October 13, 2017 01:21
marksiemers pushed a commit to marksiemers/amber that referenced this pull request Oct 28, 2017
Amber currently ships with 3 different environments: development, test
and production.

As a developer I would like to sometimes run code conditionally
depending on the environment that the application is.

```crystal
if Amber.env.development?
  # ... code here ...
end

```

This PR addresses the issue by creating a Amber::Env module that
contains 3 module methods:

```crystal
Amber.env.development?
Amber.env.test?
Amber.env.production?
Amber.env.integration?
Amber.env.staging?
Amber.env.sandbox?

Amber.env.in? %w(development test)
Amber.env.in? %i(development test)

Amber.env.is? "test"
Amber.env.is? :test
```

With the changes in this PR a developer should be able to call the
appropriate method to check for the desired environment.

Adds Additional Module methods

`in?` and `is?` methods to check for inclusion of the environments

Uses rails style for Amber environment checks
elorest pushed a commit that referenced this pull request Nov 17, 2017
Amber currently ships with 3 different environments: development, test
and production.

As a developer I would like to sometimes run code conditionally
depending on the environment that the application is.

```crystal
if Amber.env.development?
  # ... code here ...
end

```

This PR addresses the issue by creating a Amber::Env module that
contains 3 module methods:

```crystal
Amber.env.development?
Amber.env.test?
Amber.env.production?
Amber.env.integration?
Amber.env.staging?
Amber.env.sandbox?

Amber.env.in? %w(development test)
Amber.env.in? %i(development test)

Amber.env.is? "test"
Amber.env.is? :test
```

With the changes in this PR a developer should be able to call the
appropriate method to check for the desired environment.

Adds Additional Module methods

`in?` and `is?` methods to check for inclusion of the environments

Uses rails style for Amber environment checks
@faustinoaq faustinoaq added this to Done in Framework 2018 May 5, 2018
@faustinoaq faustinoaq removed this from Done in Framework 2018 Jun 12, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

None yet

6 participants