assembler 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 710b5f3b455cad26bf924085ddb529d5f0f2be3d
4
- data.tar.gz: 411e7b9d2ff6cce59cc57b8eb65b236aec9806af
3
+ metadata.gz: 459053f97aea6e47c8993857b8bdb82695c39354
4
+ data.tar.gz: eb0b24fda83cfe8b556a97f0cdcd5108af2970b7
5
5
  SHA512:
6
- metadata.gz: 0857a9705d3ed323475d2629853ca0aec90bec6572b3e9cf1693a8017202cd12150a23902e07218a191044f5b0c671f49a0c924f1b59121ba10259cd6e26b01d
7
- data.tar.gz: 2a26f698cf4103bed5f8521c5e21764731eee1ccacafbbbaba84733a2a9b10f4d1b9f450a7997964ed1b0d2e85ea1bc8fff90ca16589349e809c6093e590c022
6
+ metadata.gz: 6a52ab6904aec79e71a8725aded5372880c75172c52a3101c6794b50a8bd5e4520a12f20d8e7ae4fe4c369376b1d6e5d2c8a4440679e5a62611aa0bf8cb4d3ec
7
+ data.tar.gz: 4566485a70fc557fb3321bf0586d58e11f1f69f041f946ce166b7e34d7188e5df3d2ab664683142e54def16f3b6e014912e94d5479aec5e18c07836ba97979a0
@@ -3,7 +3,7 @@ rvm:
3
3
  - 2.1.1
4
4
  - 2.1.0
5
5
  - 2.0.0
6
- # - 1.9.3
7
- # - jruby-19mode
6
+ - 1.9.3
7
+ - jruby-19mode
8
8
  script:
9
9
  - bundle exec rake
data/CHANGES.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changes
2
2
 
3
+ ## 1.1.0
4
+
5
+ * Make Ruby 1.9-compatible. (Ryan Michael)
6
+ * Rename `assembler_initializer` to `assemble_from`. (Ben Hamill)
7
+ * Better examples in the README. (Ben Hamill)
8
+
3
9
  ## 1.0.0
4
10
 
5
11
  * Initial Release. (Ben Hamill)
data/README.md CHANGED
@@ -17,10 +17,10 @@ care of storing the parameters and gives you private accessors, too.
17
17
  You use it like this:
18
18
 
19
19
  ```ruby
20
- class AwesomeThing
20
+ class IMAPConnection
21
21
  extend Assembler
22
22
 
23
- assembler_initializer :required_param, optional_param: 'default value'
23
+ assemble_from :hostname, use_ssl: true, port: nil
24
24
 
25
25
  # Additional business logic here...
26
26
  end
@@ -31,51 +31,116 @@ For example:
31
31
 
32
32
  ```ruby
33
33
  # These two are equivalent:
34
- AwesomeThing.new(required_param: 'specialness')
35
- AwesomeThing.new do |aw|
36
- aw.required_param = 'specialness'
34
+ IMAPConnection.new(hostname: 'imap.example.com')
35
+ IMAPConnection.new do |aw|
36
+ aw.hostname = 'imap.example.com'
37
37
  end
38
38
 
39
39
  # These two are equivalent:
40
- AwesomeThing.new(required_param: 'specialness', optional_param: 'override')
41
- AwesomeThing.new do |aw|
42
- aw.required_param = 'specialness'
43
- aw.optional_param = 'override'
40
+ IMAPConnection.new(hostname: 'imap.example.com', use_ssl: false)
41
+ IMAPConnection.new do |aw|
42
+ aw.hostname = 'imap.example.com'
43
+ aw.use_ssl = false
44
44
  end
45
45
  ```
46
46
 
47
- This enables some trickery when you're dealing with a world of uncertainty:
47
+ Note that when we set `use_ssl` to `false`, the code respects that, rather than
48
+ over-writing anything falsey with the default. If you don't want that, override
49
+ it like with `port`, below.
50
+
51
+ You get private `attr_reader`s for the parameters you specify, but you can
52
+ always override them, if you like. You might have this lower down in your
53
+ `IMAPConnection` class:
48
54
 
49
55
  ```ruby
50
- class Foo
51
- extend Assembler
52
- assembler_initializer :name, :awesome, favorite_color: 'green'
56
+ class IMAPConnection
57
+ attr_reader :hostname # makes `hostname` public
58
+
59
+ def ssl?
60
+ !!use_ssl
61
+ end
53
62
 
54
- def awesome?
55
- !!awesome
63
+ def port
64
+ @port ||= ssl? ? 993 : 143
56
65
  end
57
66
  end
67
+ ```
58
68
 
59
- def delegating_method(name, awesome=true, favorite_color=nil)
60
- Foo.new do |foo|
61
- foo.name = name
62
- foo.awesome = awesome
69
+ These various syntaxes enable some trickery when you're dealing with a world of
70
+ uncertainty. Let's look at a more complicated example.
63
71
 
64
- foo.favorite_color = favorite_color if favorite_color
65
- end
72
+ Say we've got a class that lets us describe an Elastic Load Balancer for Amazon
73
+ Web Services. There's a lot of complexity in what each of these arguments might
74
+ be, but the key thing for our example is this: If you have `subnets`, you
75
+ shouldn't have `availability_zones` and if you have `availability_zones`, you
76
+ shouldn't have `subnets`. And, importantly, you shouldn't send in extraneous
77
+ keys.
78
+
79
+ ```ruby
80
+ class AmazonELB
81
+ extend Assembler
82
+ assemble_from(
83
+ :name,
84
+ load_balancer_name: nil,
85
+ health_check: nil,
86
+ listeners: nil,
87
+ security_groups: nil,
88
+ instances: nil,
89
+ subnets: nil,
90
+ availability_zones: nil,
91
+ )
92
+
93
+ # Additional, complex business logic...
66
94
  end
67
95
  ```
68
96
 
69
- The delegating method, here, is empowered to reverse the default for `awesome`,
70
- but then respect the default for `favorite_color` if the calling code doesn't
71
- pass anything in (assuming `nil` is unacceptable). It also respects if `awesome`
72
- has a falsey value passed in.
97
+ Now, since there's a lot of complexity in what each of these arguments might be,
98
+ say we've developed some best-practices about what each of them should be. And
99
+ we want to make it easy to pop off slight variations on what we consider to be a
100
+ "standard" ELB.
101
+
102
+ ``` ruby
103
+ module ELBFactory
104
+ def self.make_me_an_elb(subnet_ids=nil, availability_zones=nil, name_prefix='', instance_ids=[], security_groups=[])
105
+ AmazonELB.new do |elb|
106
+ elb.name = name(name_prefix)
107
+ elb.load_balancer_name = name(name_prefix)
108
+ elb.security_groups = security_groups
109
+ elb.instance_ids = instance_ids
110
+
111
+ elb.health_check = HealthCheck.new (
112
+ target: 'HTTP:8000/',
113
+ healthy_threshold: '3',
114
+ unhealthy_threshold: '5',
115
+ interval: '30',
116
+ timeout: '5'
117
+ )
118
+ elb.listeners = [Listener.new(...), Listener.new(...)]
119
+
120
+ if subnet_ids
121
+ elb.subnets = subnet_ids
122
+ else
123
+ elb.availability_zones = availability_zones
124
+ end
125
+ end
126
+ end
127
+
128
+ def self.name(name_prefix)
129
+ "#{sanitize_for_name(name_prefix)}LoadBalancer"
130
+ end
131
+
132
+ def self.sanitize_for_name(string)
133
+ # ...
134
+ end
135
+ end
136
+ ```
73
137
 
74
- Especially when you have objects with a lot of potential arguments being passed
75
- in and don't want to pass keys that you don't have any information about (did
76
- my caller pass in this `nil`, or is it my own default?), you can use conditional
77
- logic in the block, rather than conditionally build of a hash just to pass to a
78
- constructor method.
138
+ Note the `if`/`else` block near the end of the initialization block. If the
139
+ initialization method only took hashes, you would either have to wrap object
140
+ creation in an `if`/`else` and repeat all the constructor arguments that were
141
+ shared between the two cases, or else pre-construct your argument hash, which
142
+ would look similar to the above, but require you to assign an intermediate
143
+ variable for no semantic benefit.
79
144
 
80
145
 
81
146
  ## Contributing
@@ -2,16 +2,37 @@ require "assembler/version"
2
2
  require "assembler/initializer"
3
3
 
4
4
  module Assembler
5
- attr_reader :required_params, :optional_params, :all_param_names
5
+ attr_writer :required_params, :optional_params
6
+
7
+ def assemble_from(*args)
8
+ optional = args.last.is_a?(Hash) ? args.pop : {}
9
+ required = args
6
10
 
7
- def assembler_initializer(*required, **optional)
8
11
  include Assembler::Initializer
9
12
 
10
- @required_params = required
11
- @optional_params = optional
12
- @all_param_names = (required + optional.keys).map(&:to_sym)
13
+ self.required_params += required
14
+ self.optional_params = optional_params.merge(optional)
13
15
 
14
16
  attr_reader *all_param_names
15
17
  private *all_param_names
16
18
  end
19
+ alias_method :assemble_with, :assemble_from
20
+
21
+ def assembler_initializer(*args)
22
+ caller_file, caller_line, _ = caller.first.split(':')
23
+ warn "The `assembler_initializer` method is deprecated and will be phased out in version 2.0. Please use `assemble_from` instead. Called from #{caller_file}:#{caller_line}."
24
+ assemble_from(*args)
25
+ end
26
+
27
+ def required_params
28
+ @required_params ||= []
29
+ end
30
+
31
+ def optional_params
32
+ @optional_params ||= {}
33
+ end
34
+
35
+ def all_param_names
36
+ (required_params + optional_params.keys).map(&:to_sym)
37
+ end
17
38
  end
@@ -1,3 +1,3 @@
1
1
  module Assembler
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -2,13 +2,13 @@ require 'spec_helper'
2
2
  require 'assembler'
3
3
 
4
4
  describe Assembler do
5
- describe "#assembler_initializer" do
5
+ describe "#assemble_from" do
6
6
  context "without parameters" do
7
7
  subject do
8
8
  Class.new do
9
9
  extend Assembler
10
10
 
11
- assembler_initializer
11
+ assemble_from
12
12
  end
13
13
  end
14
14
 
@@ -30,7 +30,7 @@ describe Assembler do
30
30
  Class.new do
31
31
  extend Assembler
32
32
 
33
- assembler_initializer :foo, bar: 'bar'
33
+ assemble_from :foo, bar: 'bar'
34
34
  end
35
35
  end
36
36
 
@@ -83,5 +83,26 @@ describe Assembler do
83
83
  }.to raise_error(NoMethodError)
84
84
  end
85
85
  end
86
+
87
+ context "when called more than once" do
88
+ subject do
89
+ Class.new do
90
+ extend Assembler
91
+
92
+ assemble_from :foo
93
+ assemble_from bar: 'bar'
94
+ end
95
+ end
96
+
97
+ it "still takes both arguments" do
98
+ built_object = subject.new do |builder|
99
+ builder.foo = 'baz'
100
+ builder.bar = 'qux'
101
+ end
102
+
103
+ expect(built_object.instance_variable_get(:@foo)).to eq('baz')
104
+ expect(built_object.instance_variable_get(:@bar)).to eq('qux')
105
+ end
106
+ end
86
107
  end
87
108
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: assembler
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Hamill
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-01 00:00:00.000000000 Z
11
+ date: 2014-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler