coconut 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -63,8 +63,8 @@ environment the app is running on. If this variable is not set or is empty it
63
63
  will default to `:development`.
64
64
 
65
65
  If your ecosystem uses something that is not RACK based you can specify how
66
- Coconut should find out the environment with the `environment` method on the
67
- **Application** level
66
+ Coconut should find out the environment with the `take_environment_from` method
67
+ on the **Application** level
68
68
  (See the *Specifying how the environment should be found* section on
69
69
  *Application* under *Coconut Anatomy*).
70
70
 
@@ -109,7 +109,7 @@ determine which configuration to use you can tell Coconut how to find out:
109
109
 
110
110
  ```ruby
111
111
  Coconut.configure MyApp do
112
- environment { MyApp::find_out_environment }
112
+ take_environment_from { MyApp::find_out_environment }
113
113
  # ...
114
114
  end
115
115
  ```
@@ -1,11 +1,19 @@
1
1
  # Coconut release changes
2
2
 
3
- ## Version 0.0.1
4
- - Single file configuration preview.
3
+ ## Version 0.2.0
4
+ - Including `Coconut` as a module to define the `configure` method.
5
+ - Querying the configuration using constants.
6
+ - Asset setup hook.
7
+ - Improved error messages and warnings.
8
+ - Improved constant resolution.
9
+
10
+ ## Version 0.1.1
11
+ - Add *file list flavour* support.
5
12
 
6
13
  ## Version 0.1.0
7
14
  - Remove Hashie dependency.
8
15
  - Add *folder flavour* support.
9
16
 
10
- ## Version 0.1.1
11
- - Add *file list flavour* support.
17
+ ## Version 0.0.1
18
+ - Single file configuration preview.
19
+
@@ -0,0 +1,25 @@
1
+ Feature: Setting up an asset in the configuration
2
+
3
+ Many times you use your configuration values to setup a gem or external
4
+ library. Coconut will allow you to put this code where it belongs: your
5
+ configuration files.
6
+
7
+ Scenario: Setting up an asset
8
+ Given I have my application config in "/tmp/coconut_config/config.rb" with content:
9
+ """
10
+ Coconut.configure(MyApp) do
11
+ ftp do
12
+ environment(:development) do
13
+ user 'root'
14
+ pass '1234'
15
+ end
16
+ setup do
17
+ DummyFtp.user = user
18
+ DummyFtp.pass = pass
19
+ end
20
+ end
21
+ end
22
+ """
23
+ When I run my application on the "development" environment
24
+ Then my setup block should have been called with the correct values
25
+
@@ -19,3 +19,8 @@ end
19
19
  Then /^the configured value should be "(.*?)"$/ do |expected_result|
20
20
  eval(@query).should eq expected_result
21
21
  end
22
+
23
+ Then /^my setup block should have been called with the correct values$/ do
24
+ DummyFtp.user.should eq 'root'
25
+ DummyFtp.pass.should eq '1234'
26
+ end
@@ -0,0 +1,5 @@
1
+ class DummyFtp
2
+ class << self
3
+ attr_accessor :user, :pass
4
+ end
5
+ end
@@ -4,24 +4,48 @@ require_relative 'coconut/dsl/application'
4
4
  module Coconut
5
5
  include Dsl
6
6
 
7
+ def self.included(base)
8
+ configure_method = method(:configure)
9
+ base.singleton_class.instance_eval do
10
+ define_method(:configure) { |*args, &block| configure_method.(base, &block) }
11
+ end
12
+ end
13
+
7
14
  def self.configure(namespace, &config)
8
- define_config_method namespace, Application.configure(environment, &config)
15
+ config = Application.configure(environment, &config)
16
+ check_for_unconfigured_assets(config)
17
+ define_config_method(namespace, config)
18
+ define_config_constant(namespace, config)
9
19
  end
10
20
 
11
21
  def self.environment
12
- return @__coconut_environment.() unless @__coconut_environment.nil?
22
+ return @_coconut_environment.() unless @_coconut_environment.nil?
13
23
  ENV['RACK_ENV'] || :development
14
24
  end
15
25
 
16
26
  def self.take_environment_from(&block)
17
- @__coconut_environment = block
27
+ @_coconut_environment = block
18
28
  end
19
29
 
20
30
  private
21
31
 
22
32
  def self.define_config_method(namespace, configuration)
23
33
  namespace.singleton_class.instance_eval do
24
- define_method(:config) { @__coconut_configuration ||= configuration }
34
+ define_method(:config) { @_coconut_configuration ||= configuration }
35
+ end
36
+ end
37
+
38
+ def self.define_config_constant(namespace, configuration)
39
+ namespace.instance_eval do
40
+ remove_const(:CONFIG) if const_defined?(:CONFIG, false)
41
+ const_set(:CONFIG, configuration)
42
+ end
43
+ end
44
+
45
+ def self.check_for_unconfigured_assets(config)
46
+ config.to_hash.each do |asset, properties|
47
+ Kernel.warn "WARNING: \"#{asset}\" asset has no properties set up for \
48
+ current environment (#{environment})" if properties.empty?
25
49
  end
26
50
  end
27
51
  end
@@ -1,8 +1,10 @@
1
1
  module Coconut
2
2
  class Config
3
- def initialize(properties)
4
- @properties = properties
5
- @config = config_from(properties)
3
+ def self.with(properties)
4
+ dup.tap do |new_config|
5
+ new_config.instance_variable_set('@properties', properties)
6
+ new_config.instance_variable_set('@config', config_from(properties))
7
+ end
6
8
  end
7
9
 
8
10
  # Coconut::Config objects will respond to methods if its name is
@@ -10,29 +12,27 @@ module Coconut
10
12
  # make its behaviour consistent with Coconut::Config#method_missing
11
13
  #
12
14
  # @return [Boolean] whether a config object knows how to respond to method "name"
13
- def respond_to?(name)
15
+ def self.respond_to?(name)
14
16
  property?(name) or super
15
17
  end
16
18
 
17
19
  # @return [Hash] a Hash representation of the configuration object
18
- def to_hash
20
+ def self.to_hash
19
21
  @properties.dup
20
22
  end
21
23
 
22
- private
23
-
24
- def config_from(properties)
24
+ def self.config_from(properties)
25
25
  properties.each_with_object({}) do |(property, value), config|
26
26
  config[property]= config_value_for(value)
27
27
  end
28
28
  end
29
29
 
30
- def config_value_for(value)
31
- return Config.new(value) if value.is_a? Hash
30
+ def self.config_value_for(value)
31
+ return Config.with(value) if value.is_a? Hash
32
32
  value
33
33
  end
34
34
 
35
- def method_missing(name, *args, &block)
35
+ def self.method_missing(name, *args, &block)
36
36
  if property?(name)
37
37
  define_property_accessor(name)
38
38
  return @config[name]
@@ -40,14 +40,34 @@ module Coconut
40
40
  super
41
41
  end
42
42
 
43
- def property?(name)
43
+ def self.const_missing(name)
44
+ if property?(name.downcase)
45
+ define_constant(name)
46
+ return @config[name.downcase]
47
+ end
48
+ super
49
+ end
50
+
51
+ def self.property?(name)
52
+ return false if @config.nil?
44
53
  @config.has_key?(name)
45
54
  end
46
55
 
47
- def define_property_accessor(name)
56
+ def self.define_property_accessor(name)
48
57
  singleton_class.instance_eval do
49
58
  define_method(name) { @config[name] }
50
59
  end
51
60
  end
61
+
62
+ def self.define_constant(name)
63
+ self.const_set(name, @config[name.downcase])
64
+ end
65
+
66
+ private_class_method :config_from,
67
+ :config_value_for,
68
+ :define_constant,
69
+ :define_property_accessor,
70
+ :method_missing,
71
+ :property?
52
72
  end
53
73
  end
@@ -1,5 +1,6 @@
1
1
  require_relative 'asset'
2
2
  require_relative 'asset_folder'
3
+ require_relative 'asset_file_list'
3
4
 
4
5
  module Coconut
5
6
  module Dsl
@@ -15,21 +16,25 @@ module Coconut
15
16
  def run(&config)
16
17
  @assets_config = {}
17
18
  instance_eval &config
18
- Config.new(@assets_config)
19
+ Config.with(@assets_config)
19
20
  end
20
21
 
21
22
  private
22
23
 
23
24
  def asset_folder(path)
24
- instance_eval AssetFolder.config_from(path, IGNORED_FILES)
25
+ AssetFolder.new(path, IGNORED_FILES).each do |asset_config, path|
26
+ instance_eval(asset_config, path)
27
+ end
25
28
  end
26
29
 
27
30
  def asset_files(*files)
28
- instance_eval AssetFileList.config_from(*files)
31
+ AssetFileList.new(*files).each do |asset_config, path|
32
+ instance_eval(asset_config, path)
33
+ end
29
34
  end
30
35
 
31
36
  def method_missing(asset, *args, &config)
32
- ::Kernel::raise InvalidName, __taken_error_message(asset, 'asset name') if __taken?(asset)
37
+ ::Kernel::raise InvalidName, "#{asset} can't be used as asset name" if _taken?(asset)
33
38
  @assets_config[asset] = Asset.configure(@current_environment, &config)
34
39
  end
35
40
 
@@ -1,5 +1,5 @@
1
- require_relative '../config'
2
1
  require_relative './environment'
2
+ require_relative './asset_setup'
3
3
 
4
4
  module Coconut
5
5
  module Dsl
@@ -20,19 +20,23 @@ module Coconut
20
20
 
21
21
  private
22
22
 
23
+ def setup(&code)
24
+ AssetSetup.new(@properties).instance_eval(&code)
25
+ end
26
+
23
27
  def environment(*environments, &config)
24
- environments.each { |environment| __configure(environment, config) }
28
+ environments.each { |environment| _configure(environment, config) }
25
29
  end
26
30
 
27
31
  alias :env :environment
28
32
  alias :envs :environment
29
33
  alias :environments :environment
30
34
 
31
- def __configure(environment, config)
32
- @properties.merge! Environment.configure(&config) if __current?(environment)
35
+ def _configure(environment, config)
36
+ @properties.merge! Environment.configure(&config) if _current?(environment)
33
37
  end
34
38
 
35
- def __current?(environment)
39
+ def _current?(environment)
36
40
  @current_environment.to_sym == environment.to_sym
37
41
  end
38
42
  end
@@ -1,18 +1,12 @@
1
- require_relative 'asset_file'
2
-
3
1
  module Coconut
4
2
  module Dsl
5
3
  class AssetFileList
6
- def self.config_from(*file_paths)
7
- new(*file_paths).assets_config
8
- end
9
-
10
4
  def initialize(*file_paths)
11
- @files = file_paths.map { |file| AssetFile.new(file) }
5
+ @paths = file_paths
12
6
  end
13
7
 
14
- def assets_config
15
- @files.map { |file| file.asset_config }.join("\n")
8
+ def each(&block)
9
+ @paths.each { |path| yield File.read(path), path }
16
10
  end
17
11
  end
18
12
  end
@@ -3,17 +3,13 @@ require_relative 'asset_file_list'
3
3
  module Coconut
4
4
  module Dsl
5
5
  class AssetFolder
6
- def self.config_from(path, ignored_files)
7
- new(path, ignored_files).assets_config
8
- end
9
-
10
6
  def initialize(path, ignored_files)
11
7
  @path = path
12
8
  @ignored_files = ignored_files.map(&method(:path_to))
13
9
  end
14
10
 
15
- def assets_config
16
- AssetFileList.new(*asset_files_in_folder).assets_config
11
+ def each(&block)
12
+ AssetFileList.new(*asset_files_in_folder).each(&block)
17
13
  end
18
14
 
19
15
  private
@@ -38,6 +34,5 @@ module Coconut
38
34
  File.expand_path(File.join(@path, file))
39
35
  end
40
36
  end
41
-
42
- end
37
+ end
43
38
  end
@@ -0,0 +1,16 @@
1
+ require_relative 'blank_slate'
2
+
3
+ module Coconut
4
+ module Dsl
5
+ class AssetSetup < BlankSlate
6
+ def initialize(properties)
7
+ @properties = properties
8
+ end
9
+
10
+ def method_missing(name, *args, &block)
11
+ return @properties[name] if @properties.has_key? name
12
+ super
13
+ end
14
+ end
15
+ end
16
+ end
@@ -2,32 +2,33 @@ require_relative '../config'
2
2
 
3
3
  module Coconut
4
4
  module Dsl
5
- class InvalidName < Exception; end
5
+ class InvalidName < RuntimeError; end
6
6
 
7
7
  class BlankSlate < BasicObject
8
8
  def self.__forbidden_names
9
- Config.instance_methods + PERMANENT_METHODS
9
+ Config.instance_methods + PERMANENT_PUBLIC_METHODS
10
10
  end
11
11
 
12
12
  private
13
13
 
14
- def __taken?(name)
14
+ def _taken?(name)
15
15
  Config.instance_methods.include? name
16
16
  end
17
17
 
18
- def __taken_error_message(name, usage)
19
- "#{name} can't be used as #{usage}: it will collide with Coconut::Config methods"
18
+ def self.const_missing(name)
19
+ super unless self.class.const_defined?(name)
20
+ self.class.const_get(name)
20
21
  end
21
22
 
22
23
  def self.inherited(subclass)
23
- __eraseable_methods.each{ |method_name| undef_method method_name }
24
+ _eraseable_methods.each{ |method_name| undef_method method_name }
24
25
  end
25
26
 
26
- def self.__eraseable_methods
27
- instance_methods - PERMANENT_METHODS
27
+ def self._eraseable_methods
28
+ instance_methods - PERMANENT_PUBLIC_METHODS
28
29
  end
29
30
 
30
- PERMANENT_METHODS = [:instance_eval, :__send__, :object_id, :__taken?, :__taken_error_message, :asset_folder]
31
+ PERMANENT_PUBLIC_METHODS = [:instance_eval, :__send__, :object_id, :__forbidden_names]
31
32
  end
32
33
  end
33
34
  end
@@ -20,7 +20,7 @@ module Coconut
20
20
  private
21
21
 
22
22
  def method_missing(name, *args, &block)
23
- ::Kernel::raise InvalidName, __taken_error_message(name, 'property name') if __taken?(name)
23
+ ::Kernel::raise InvalidName, "#{name} can't be used as property name" if _taken?(name)
24
24
  @properties[name] = args.first
25
25
  end
26
26
  end
@@ -1,3 +1,3 @@
1
1
  module Coconut
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -1,9 +1,19 @@
1
1
  require 'coconut'
2
2
 
3
- class MyClass; end
4
- module MyModule; end
5
3
 
6
4
  describe Coconut do
5
+ before do
6
+ class MyClass; end
7
+ module MyModule; end
8
+ end
9
+
10
+ after do
11
+ Object.instance_eval do
12
+ remove_const(:MyClass)
13
+ remove_const(:MyModule)
14
+ end
15
+ end
16
+
7
17
  it 'defines a config method in the provided namespace' do
8
18
  Coconut.configure(MyClass){}
9
19
  MyClass.should respond_to(:config)
@@ -11,14 +21,35 @@ describe Coconut do
11
21
  MyModule.should respond_to(:config)
12
22
  end
13
23
 
24
+ it 'defines a config constant in the provided namespace' do
25
+ Coconut.configure(MyClass){}
26
+ MyClass::CONFIG.should_not be_nil
27
+ Coconut.configure(MyModule){}
28
+ MyModule::CONFIG.should_not be_nil
29
+ end
30
+
14
31
  it "allows the app's configuration to be run twice" do
15
32
  Coconut.configure(MyClass) { asset { env(:development){ property 'initial value' } } }
16
33
  Coconut.configure(MyClass) { asset { env(:development){ property 'latest value' } } }
17
34
  MyClass::config.asset.property.should eq 'latest value'
18
35
  end
19
36
 
37
+ it 'checks the configuration for assets without properties' do
38
+ Kernel.should_receive(:warn).with(/asset|current environment|development/)
39
+ Coconut.configure MyClass do
40
+ asset {}
41
+ end
42
+ end
43
+
44
+ context 'when included' do
45
+ it 'defines a configure method' do
46
+ module MyModule; include Coconut; end
47
+ expect { module MyModule; configure{}; end }.not_to raise_error
48
+ end
49
+ end
50
+
20
51
  context 'finding out the environment' do
21
- before { Coconut.instance_variable_set(:@__coconut_environment, nil) }
52
+ before { Coconut.instance_variable_set(:@_coconut_environment, nil) }
22
53
 
23
54
  it 'uses the expression provided by the user if any' do
24
55
  Coconut.take_environment_from { :somewhere }
@@ -1,34 +1,47 @@
1
1
  require 'coconut/config'
2
2
 
3
3
  describe Coconut::Config do
4
- subject { described_class.new(application) }
5
- let(:application) { Hash[twitter: properties] }
6
- let(:properties) { Hash[property: 'value', other: 'other'] }
4
+ subject { described_class.with(assets) }
5
+ let(:assets) { Hash[twitter: properties] }
6
+ let(:properties) { Hash[property: 'value', other: 'other'] }
7
7
 
8
8
  context 'newly created' do
9
9
  it 'has no property methods' do
10
- (subject.methods - Object.instance_methods).should eq [:to_hash]
10
+ (subject.public_methods - Class.public_methods).should eq [:with, :to_hash]
11
11
  end
12
12
 
13
- it 'responds to every property' do
13
+ it 'responds to every property' do
14
14
  subject.should respond_to :twitter
15
15
  end
16
16
  end
17
17
 
18
- context 'when a property is queried' do
19
- it 'returns the property value' do
18
+ context 'when a property is queried as a method' do
19
+ it 'returns the property value' do
20
20
  subject.twitter.property.should eq 'value'
21
21
  subject.twitter.other.should eq 'other'
22
22
  end
23
23
 
24
- it 'defines a new method to access the property' do
24
+ it 'defines a new method to access the property' do
25
25
  subject.methods.should_not include(:twitter)
26
26
  subject.twitter
27
27
  subject.methods.should include(:twitter)
28
28
  end
29
29
  end
30
30
 
31
- it 'can be transformed to a hash' do
32
- subject.to_hash.should eq application
31
+ context 'when a property is queried as a constant' do
32
+ it 'returns the property value' do
33
+ subject::TWITTER::PROPERTY.should eq 'value'
34
+ subject::TWITTER::OTHER.should eq 'other'
35
+ end
36
+
37
+ it 'defines a new constant to access the property' do
38
+ subject.constants.should_not include(:TWITTER)
39
+ subject::TWITTER
40
+ subject.constants.should include(:TWITTER)
41
+ end
42
+ end
43
+
44
+ it 'can be transformed to a hash' do
45
+ subject.to_hash.should eq assets
33
46
  end
34
47
  end
@@ -15,17 +15,26 @@ describe Coconut::Dsl::Application do
15
15
  end
16
16
 
17
17
  it 'can load the asset configuration from a folder' do
18
- path = '.'
19
- Coconut::Dsl::AssetFolder.stub(:config_from).with(path, ['config.rb']).
20
- and_return("asset { environment(:current) { property 'value' } }")
21
- config = described_class.configure(:current) { asset_folder path }
18
+ asset_path = '/file/path.rb'
19
+ asset_config = "asset { environment(:current) { property 'value' } }"
20
+
21
+ asset_folder = stub(:asset_folder)
22
+ Coconut::Dsl::AssetFolder.stub(:new).and_return(asset_folder)
23
+ asset_folder.stub(:each).and_yield(asset_config, asset_path)
24
+
25
+ config = described_class.configure(:current) { asset_folder '.' }
22
26
  config.asset.property.should eq 'value'
23
27
  end
24
28
 
25
- it 'can load asset configuration from a list of files' do
26
- Coconut::Dsl::AssetFileList.stub(:config_from).with('/file/path.rb').
27
- and_return("asset { environment(:current) { property 'value' } }")
28
- config = described_class.configure(:current) { asset_files '/file/path.rb' }
29
+ it 'can load asset configuration from a list of asset files' do
30
+ asset_path = '/file/path.rb'
31
+ asset_config = "asset { environment(:current) { property 'value' } }"
32
+
33
+ asset_file_list = stub(:asset_file_list)
34
+ Coconut::Dsl::AssetFileList.stub(:new).and_return(asset_file_list)
35
+ asset_file_list.stub(:each).and_yield(asset_config, asset_path)
36
+
37
+ config = described_class.configure(:current) { asset_files asset_path }
29
38
  config.asset.property.should eq 'value'
30
39
  end
31
40
  end
@@ -1,6 +1,7 @@
1
1
  require 'coconut/dsl/asset_file_list'
2
2
 
3
3
  describe Coconut::Dsl::AssetFileList do
4
+ subject { described_class.new(path1, path2) }
4
5
  let(:path1) { '/tmp/asset1.rb' }
5
6
  let(:path2) { '/tmp/asset2.rb' }
6
7
  let(:config1) { "asset1 { env(:current) { property 'value for asset1' } }" }
@@ -15,7 +16,10 @@ describe Coconut::Dsl::AssetFileList do
15
16
  File.delete('/tmp/asset1.rb', '/tmp/asset2.rb')
16
17
  end
17
18
 
18
- it 'reads the content of the asset file at path' do
19
- described_class.config_from(path1, path2).should eq "#{config1}\n#{config2}"
19
+ it "yields each asset file's config and path in the list" do
20
+ configs, paths = [], []
21
+ subject.each { |config, path| paths << path and configs << config }
22
+ paths.should include(path1, path2)
23
+ configs.should include(config1, config2)
20
24
  end
21
25
  end
@@ -1,36 +1,53 @@
1
1
  require 'coconut/dsl/asset_folder'
2
2
 
3
3
  describe 'Assets configuration from files in folder', integration: true do
4
+ subject { Coconut::Dsl::AssetFolder.new(path, ignored) }
4
5
  let(:path) { '/tmp/coconut-testing/' }
5
6
  let(:ignored) { ['config.rb'] }
6
7
 
7
- let(:config) { "" }
8
8
  let(:s3_config) { "s3 { environment(:current) { property 'p1' } }" }
9
9
  let(:db_config) { "database { environment(:current) { property 'p2' } }" }
10
10
 
11
- before :all do
12
- `rm -rf #{path}`
11
+ before do
13
12
  Dir::mkdir path
14
- File.open(File.join(path, 'config.rb'), 'w+') { |f| f.write '' }
15
- File.open(File.join(path, 's3.rb'), 'w+') { |f| f.write s3_config }
16
- File.open(File.join(path, 'db.rb'), 'w+') { |f| f.write db_config }
13
+ File.open(File.join(path, 's3.rb'), 'w+') { |f| f.write s3_config }
14
+ File.open(File.join(path, 'db.rb'), 'w+') { |f| f.write db_config }
17
15
  end
18
16
 
19
- it 'evals every asset file in the folder as application config' do
20
- configuration_from_folder.should eq "#{db_config}\n#{s3_config}"
17
+ after do
18
+ `rm -rf #{path}`
21
19
  end
22
20
 
23
- context 'with other files that are not Ruby files' do
24
- before do
25
- File.open(File.join(path, 'readme.md'), 'w+') { |f| f.write 'readme' }
21
+ shared_examples_for 'a folder with asset files only' do
22
+ let(:paths) { [] }
23
+ let(:configs) { [] }
24
+
25
+ it "yields every asset file's config and path" do
26
+ subject.each { |config, path| paths << path and configs << config }
27
+ paths.length.should be 2
28
+ paths.should include('/tmp/coconut-testing/s3.rb', '/tmp/coconut-testing/db.rb')
29
+ configs.length.should be 2
30
+ configs.should include(s3_config, db_config)
26
31
  end
32
+ end
33
+
34
+ context 'with asset files only' do
35
+ it_behaves_like 'a folder with asset files only'
36
+ end
27
37
 
28
- it 'ignores non Ruby files' do
29
- configuration_from_folder.should eq "#{db_config}\n#{s3_config}"
38
+ context 'with asset files and a config.rb file' do
39
+ before do
40
+ File.open(File.join(path, 'config.rb'), 'w+') { |f| f.write '#config' }
30
41
  end
42
+
43
+ it_behaves_like 'a folder with asset files only'
31
44
  end
32
45
 
33
- def configuration_from_folder
34
- Coconut::Dsl::AssetFolder.config_from(path, ignored)
46
+ context 'with asset files and non Ruby files' do
47
+ before do
48
+ File.open(File.join(path, 'readme.md'), 'w+') { |f| f.write 'readme' }
49
+ end
50
+
51
+ it_behaves_like 'a folder with asset files only'
35
52
  end
36
53
  end
@@ -46,4 +46,15 @@ describe Coconut::Dsl::Asset do
46
46
  asset_config.fetch(:property3).should eq 3
47
47
  asset_config.fetch(:property4).should eq 4
48
48
  end
49
+
50
+ it 'has a setup hook' do
51
+ setup_value = nil
52
+ asset_config = described_class.configure(:current) do
53
+ env(:current) { property 'value' }
54
+ setup do
55
+ setup_value = property
56
+ end
57
+ end
58
+ setup_value.should eq 'value'
59
+ end
49
60
  end
@@ -2,8 +2,14 @@ require 'coconut/dsl/blank_slate'
2
2
 
3
3
  describe Coconut::Dsl::BlankSlate do
4
4
  it 'knows the forbidden names' do
5
- expected_names = described_class::PERMANENT_METHODS + [:one]
5
+ expected_names = described_class::PERMANENT_PUBLIC_METHODS + [:one]
6
6
  Coconut::Config.stub(:instance_methods).and_return([:one])
7
7
  described_class.__forbidden_names.should include(*expected_names)
8
8
  end
9
+
10
+ it 'can look up for constants on the global namespace' do
11
+ context = described_class.new
12
+ expect { context.instance_eval('Kernel') }.not_to raise_error NameError
13
+ end
9
14
  end
15
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coconut
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-26 00:00:00.000000000 Z
12
+ date: 2013-01-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cucumber
@@ -92,16 +92,18 @@ files:
92
92
  - coconut.gemspec
93
93
  - features/folder_configuration.feature
94
94
  - features/multiple_file_configuration.feature
95
+ - features/setup.feature
95
96
  - features/single_file_configuration.feature
96
97
  - features/step_definitions/configuration_steps.rb
98
+ - features/support/dummy_ftp.rb
97
99
  - features/support/env.rb
98
100
  - lib/coconut.rb
99
101
  - lib/coconut/config.rb
100
102
  - lib/coconut/dsl/application.rb
101
103
  - lib/coconut/dsl/asset.rb
102
- - lib/coconut/dsl/asset_file.rb
103
104
  - lib/coconut/dsl/asset_file_list.rb
104
105
  - lib/coconut/dsl/asset_folder.rb
106
+ - lib/coconut/dsl/asset_setup.rb
105
107
  - lib/coconut/dsl/blank_slate.rb
106
108
  - lib/coconut/dsl/environment.rb
107
109
  - lib/coconut/version.rb
@@ -109,7 +111,6 @@ files:
109
111
  - spec/coconut/config_spec.rb
110
112
  - spec/coconut/dsl/application_spec.rb
111
113
  - spec/coconut/dsl/asset_file_list_spec.rb
112
- - spec/coconut/dsl/asset_file_spec.rb
113
114
  - spec/coconut/dsl/asset_folder_spec.rb
114
115
  - spec/coconut/dsl/asset_spec.rb
115
116
  - spec/coconut/dsl/blank_slate_spec.rb
@@ -128,7 +129,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
128
129
  version: '0'
129
130
  segments:
130
131
  - 0
131
- hash: -2312631787946944813
132
+ hash: 2150013374139596454
132
133
  required_rubygems_version: !ruby/object:Gem::Requirement
133
134
  none: false
134
135
  requirements:
@@ -137,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
137
138
  version: '0'
138
139
  segments:
139
140
  - 0
140
- hash: -2312631787946944813
141
+ hash: 2150013374139596454
141
142
  requirements: []
142
143
  rubyforge_project:
143
144
  rubygems_version: 1.8.24
@@ -148,14 +149,15 @@ summary: Coconut is a simple DSL that allows you to easily write and query your
148
149
  test_files:
149
150
  - features/folder_configuration.feature
150
151
  - features/multiple_file_configuration.feature
152
+ - features/setup.feature
151
153
  - features/single_file_configuration.feature
152
154
  - features/step_definitions/configuration_steps.rb
155
+ - features/support/dummy_ftp.rb
153
156
  - features/support/env.rb
154
157
  - spec/coconut/coconut_spec.rb
155
158
  - spec/coconut/config_spec.rb
156
159
  - spec/coconut/dsl/application_spec.rb
157
160
  - spec/coconut/dsl/asset_file_list_spec.rb
158
- - spec/coconut/dsl/asset_file_spec.rb
159
161
  - spec/coconut/dsl/asset_folder_spec.rb
160
162
  - spec/coconut/dsl/asset_spec.rb
161
163
  - spec/coconut/dsl/blank_slate_spec.rb
@@ -1,13 +0,0 @@
1
- module Coconut
2
- module Dsl
3
- class AssetFile
4
- def initialize(path)
5
- @path = path
6
- end
7
-
8
- def asset_config
9
- ::File.read(@path)
10
- end
11
- end
12
- end
13
- end
@@ -1,19 +0,0 @@
1
- require 'coconut/dsl/asset_file'
2
-
3
- describe Coconut::Dsl::AssetFile do
4
- subject { described_class.new(path) }
5
- let(:path) { '/tmp/asset.rb' }
6
- let(:config) { "asset { env(:current) { property 'value' } }" }
7
-
8
- before do
9
- File.open('/tmp/asset.rb', 'w+') { |f| f.write(config) }
10
- end
11
-
12
- after do
13
- File.delete('/tmp/asset.rb')
14
- end
15
-
16
- it 'reads the content of the asset file at path' do
17
- subject.asset_config.should eq config
18
- end
19
- end