assembler 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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