Permalink
Browse files

Inherit configuration

Closes #20
  • Loading branch information...
paulcsmith committed May 1, 2018
1 parent 29cdca6 commit bea638e86425a48cdeb7a0d7944bb97ab50a2d47
Showing with 75 additions and 21 deletions.
  1. +25 −0 spec/habitat_spec.cr
  2. +50 −21 src/habitat.cr
View
@@ -16,6 +16,23 @@ class FakeServer
end
end
class Parent
Habitat.create do
setting parent_setting : Bool = true
end
end
class Child < Parent
Habitat.create do
setting is_child : Bool = true
setting another_one : String?
end
end
# Test that config is inherited from Parent without calling Habitat
class AnotherChild < Parent
end
describe Habitat do
it "works with simple types" do
setup_server(port: 8080)
@@ -27,6 +44,14 @@ describe Habitat do
FakeServer.new.available_in_instance_methods.should eq 8080
end
it "works with inherited config" do
Parent.settings.parent_setting.should be_true
Child.settings.parent_setting.should be_true
Child.settings.is_child.should be_true
AnotherChild.settings.parent_setting.should be_true
AnotherChild.settings.responds_to?(:another_one).should be_false
end
it "works with union types" do
setup_server(something_that_can_be_multiple_types: "string")
FakeServer.settings.something_that_can_be_multiple_types.should eq "string"
View
@@ -35,11 +35,13 @@ class Habitat
end
macro create
include Habitat::SettingHelpers
include Habitat::TempConfig
Habitat.track(\{{ @type }})
REQUIRED_SETTINGS = [] of TypeDeclaration
include Habitat::TempConfig
include Habitat::SettingsHelpers
REQUIRED_SETTINGS = [] of Nil
HABITAT_SETTINGS = [] of Crystal::Macros::TypeDeclaration
def self.configure
with self yield
@@ -57,31 +59,43 @@ class Habitat
end
{{ yield }}
end
module TempConfig
macro temp_config(**settings_with_values)
{% for setting_name, setting_value in settings_with_values %}
original_{{ setting_name }} = {{ @type.name }}.settings.{{setting_name}}
{{ @type.name }}.settings.{{ setting_name }} = {{ setting_value }}
{% end %}
{{ yield }}
{% for setting_name, _unused in settings_with_values %}
{{ @type.name }}.settings.{{ setting_name }} = original_{{ setting_name }}
{% end %}
inherit_habitat_settings_from_superclass
macro finished
Habitat.create_settings_methods(\{{ @type }})
end
end
module SettingHelpers
module SettingsHelpers
macro setting(decl)
{% if decl.type.is_a?(Union) && decl.type.types.map(&.id).includes?(Nil.id) %}
{% nilable = true %}
{% else %}
{% nilable = false %}
{% if !decl.type.is_a?(Union) ||
(decl.type.is_a?(Union) && !decl.type.types.map(&.id).includes?(Nil.id)) %}
{% REQUIRED_SETTINGS << decl %}
{% end %}
class Settings
{% HABITAT_SETTINGS << decl %}
end
macro inherit_habitat_settings_from_superclass
{% if @type.superclass.constant(:HABITAT_SETTINGS) %}
{% for decl in @type.superclass.constant(:HABITAT_SETTINGS) %}
{% HABITAT_SETTINGS << decl %}
{% end %}
{% end %}
end
end
macro create_settings_methods(type_with_habitat)
class Settings
{% type_with_habitat = type_with_habitat.resolve %}
{% for decl in type_with_habitat.constant(:HABITAT_SETTINGS) %}
{% if decl.type.is_a?(Union) && decl.type.types.map(&.id).includes?(Nil.id) %}
{% nilable = true %}
{% else %}
{% nilable = false %}
{% end %}
{% has_default = decl.value || decl.value == false %}
@@{{ decl.var }} : {{decl.type}} | Nil {% if has_default %} = {{ decl.value }}{% end %}
@@ -96,7 +110,22 @@ class Habitat
def self.{{ decl.var }}?
@@{{ decl.var }}
end
end
{% end %}
end
end
module TempConfig
macro temp_config(**settings_with_values)
{% for setting_name, setting_value in settings_with_values %}
original_{{ setting_name }} = {{ @type.name }}.settings.{{setting_name}}
{{ @type.name }}.settings.{{ setting_name }} = {{ setting_value }}
{% end %}
{{ yield }}
{% for setting_name, _unused in settings_with_values %}
{{ @type.name }}.settings.{{ setting_name }} = original_{{ setting_name }}
{% end %}
end
end
end

0 comments on commit bea638e

Please sign in to comment.