better_sqs 0.1.1 → 0.2.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: 3bc6925375407c2cbf92a02ea941fd69473be9bc
4
- data.tar.gz: e1edc6bf3cd3bdb58c44587f26be969c5abe8bc2
3
+ metadata.gz: 9fc0e03ed8b4c5106c87e9046b2911ededc75b45
4
+ data.tar.gz: b38ac02b1f0aac3bc3ee50424e98b54fa7851a31
5
5
  SHA512:
6
- metadata.gz: 6541159a743aebac803e31cba94bb5e9836b05f520f1012c38390456483d69d7e7f6f37cb95153da653a2998a62bf752985add2513dbcab1d319a06c5891864f
7
- data.tar.gz: 4323c5e50a27a610f2151e093996ebf7757c7196ad7c82f402f3f164c98261608af243087d6ffa6f925386f32c04851640fa89edf14aa8ad5a3940eebad6a4d9
6
+ metadata.gz: 286e9d755d6444667bc77abcaa124b0224e45c3fab2b6fa4470576a261c3607a5ebd33f377921717471899c90d72370c5d1f84a2093cced2edee5ef2721531c0
7
+ data.tar.gz: dcbdcfa04471da11f5033ffc6572f32b10b0b40f861c0a2fa12b2dbfb6ce433372aee278acebbd7d38b24ab5f57f4512b8140ff540ec7c1ae696217f28ecef18
data/.rubocop_todo.yml CHANGED
@@ -1,12 +1,19 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2016-01-26 02:10:21 +0000 using RuboCop version 0.35.1.
3
+ # on 2016-04-12 01:43:20 +0000 using RuboCop version 0.35.1.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 15
9
+ # Offense count: 1
10
+ # Cop supports --auto-correct.
11
+ # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods.
12
+ Lint/UnusedMethodArgument:
13
+ Exclude:
14
+ - 'spec/support/mocks.rb'
15
+
16
+ # Offense count: 57
10
17
  # Configuration parameters: AllowURI, URISchemes.
11
18
  Metrics/LineLength:
12
19
  Max: 173
data/README.md CHANGED
@@ -21,6 +21,44 @@ puts message.message_body
21
21
  message.delete
22
22
  ```
23
23
 
24
+ If you prefer you can interact with a Queue directly for enqueue and dequeue operations
25
+
26
+ ```ruby
27
+ require "better_sqs"
28
+
29
+ better = BetterSqs::Client.new
30
+ queue = better.queue "better_sqs_dev_queue"
31
+ queue.push "You pushed the message successfully!"
32
+ message = queue.reserve
33
+
34
+ puts message.message_body
35
+ message.delete
36
+ ```
37
+
38
+ ### Inspecting a queue
39
+
40
+ BetterSqs makes it easy to check on the attributes of a SQS queue.
41
+
42
+ ```ruby
43
+ require "better_sqs"
44
+
45
+ better = BetterSqs::Client.new
46
+ queue = better.queue("better_sqs_dev_queue")
47
+ queue.approximate_number_of_messages
48
+ queue.approximate_number_of_messages_not_visible
49
+ queue.visibility_timeout
50
+ queue.created_timestamp
51
+ queue.last_modified_timestamp
52
+ queue.policy
53
+ queue.maximum_message_size
54
+ queue.message_retention_period
55
+ queue.queue_arn
56
+ queue.approximate_number_of_messages_delayed
57
+ queue.delay_seconds
58
+ queue.receive_message_wait_time_seconds
59
+ queue.redrive_policy
60
+ ```
61
+
24
62
  ## Configuration
25
63
 
26
64
  To configure BetterSqs use the configuration block pattern
data/better_sqs.gemspec CHANGED
@@ -1,8 +1,8 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "better_sqs"
3
- s.version = "0.1.1"
3
+ s.version = "0.2.0"
4
4
  s.license = "MIT"
5
- s.date = "2016-02-24"
5
+ s.date = "2016-04-12"
6
6
  s.summary = "A more idiomatic interface to SQS."
7
7
  s.description = "A convenient API for developers to interact with SQS with a trivial amount of effort"
8
8
  s.authors = ["Courtland Caldwell"]
@@ -13,6 +13,7 @@ Gem::Specification.new do |s|
13
13
  "https://github.com/Referly/better_sqs"
14
14
  s.add_runtime_dependency "lincoln_logger", "~> 1.0" # Mattermark gem
15
15
  s.add_runtime_dependency "aws-sdk", "~> 2" # Apache2 https://github.com/aws/aws-sdk-ruby/blob/master/LICENSE.txt
16
+ s.add_runtime_dependency "activesupport"
16
17
  s.add_development_dependency "rspec", "~> 3.2" # MIT - @link https://github.com/rspec/rspec/blob/master/License.txt
17
18
  s.add_development_dependency "byebug", "~> 3.5" # BSD (content is BSD) https://github.com/deivid-rodriguez/byebug/blob/master/LICENSE
18
19
  s.add_development_dependency "simplecov", "~> 0.10" # MIT - @link https://github.com/colszowka/simplecov/blob/master/MIT-LICENSE
@@ -60,5 +60,13 @@ module BetterSqs
60
60
  def url_for_queue(queue_name)
61
61
  sqs.create_queue(queue_name: queue_name).queue_url
62
62
  end
63
+
64
+ # Get a BetterSqs::Queue instance
65
+ #
66
+ # @param queue_name [String, Symbol] the name of the SQS queue
67
+ # @return [BetterSqs::Queue] the requested Queue instance
68
+ def queue(queue_name)
69
+ Queue.new self, queue_name
70
+ end
63
71
  end
64
72
  end
@@ -0,0 +1,52 @@
1
+ require "active_support/inflector"
2
+ module BetterSqs
3
+ # A Class for interacting with an SQS queue as an OOP style entity
4
+ class Queue
5
+ attr_accessor :better_client,
6
+ :queue_name
7
+
8
+ def initialize(better_client, queue_name)
9
+ @better_client = better_client
10
+ @queue_name = queue_name
11
+ end
12
+
13
+ # Push a message onto a queue
14
+ #
15
+ # @param message_body [String] the message as it will be pushed onto the queue, no serialization occurs as
16
+ # part of this method. You need to encode or serialize your object to a string before sending it to this method
17
+ # @return [Types::SendMessageResult] the sent message object returned from s3
18
+ def push(message_body)
19
+ better_client.push queue_name, message_body
20
+ end
21
+
22
+ # Reserve a message from the specified queue
23
+ #
24
+ # @return [Messages::Sqs, NilClass] the message retrieved from the queue
25
+ def reserve
26
+ better_client.reserve queue_name
27
+ end
28
+
29
+ QUEUE_ATTRIBUTES = [
30
+ :approximate_number_of_messages,
31
+ :approximate_number_of_messages_not_visible,
32
+ :visibility_timeout,
33
+ :created_timestamp,
34
+ :last_modified_timestamp,
35
+ :policy,
36
+ :maximum_message_size,
37
+ :message_retention_period,
38
+ :queue_arn,
39
+ :approximate_number_of_messages_delayed,
40
+ :delay_seconds,
41
+ :receive_message_wait_time_seconds,
42
+ :redrive_policy,
43
+ ]
44
+ QUEUE_ATTRIBUTES.each do |queue_attribute|
45
+ define_method queue_attribute do
46
+ resp = better_client.sqs.get_queue_attributes queue_url: better_client.url_for_queue(queue_name),
47
+ attribute_names: [queue_attribute.to_s.camelize]
48
+ resp.attributes[queue_attribute.to_s.camelize]
49
+ end
50
+ end
51
+ end
52
+ end
data/lib/better_sqs.rb CHANGED
@@ -2,6 +2,7 @@ require "lincoln_logger"
2
2
  require "better_sqs/configuration"
3
3
  require "better_sqs/client"
4
4
  require "better_sqs/message"
5
+ require "better_sqs/queue"
5
6
  module BetterSqs
6
7
  class << self
7
8
  # Allows the user to set configuration options
@@ -4,7 +4,8 @@ describe BetterSqs::Client do
4
4
  subject { described_class.new }
5
5
 
6
6
  let(:queue_name) { "anotherqueue" }
7
- let(:sqs) { mock_aws_sqs_client queue_url: "sqs://foo/bar" }
7
+ let(:queue_url) { "sqs://foo/bar" }
8
+ let(:sqs) { mock_aws_sqs_client }
8
9
  let(:sqs_message) { mock_sqs_message }
9
10
 
10
11
  before do
@@ -17,7 +18,7 @@ describe BetterSqs::Client do
17
18
  it "enqueues the message into the SQS queue" do
18
19
  expect(sqs).
19
20
  to receive(:send_message).
20
- with(queue_url: sqs.url_for_queue(queue_name), message_body: message_body).
21
+ with(queue_url: sqs.queues[queue_name].queue_url, message_body: message_body).
21
22
  and_return(double "SendMessageResult")
22
23
 
23
24
  subject.push queue_name, message_body
@@ -33,7 +34,7 @@ describe BetterSqs::Client do
33
34
  it "retrieves a message from SQS" do
34
35
  expect(sqs).
35
36
  to receive(:receive_message).
36
- with(queue_url: sqs.url_for_queue(queue_name), max_number_of_messages: 1).
37
+ with(queue_url: sqs.queues[queue_name].queue_url, max_number_of_messages: 1).
37
38
  and_return receive_message_response
38
39
 
39
40
  subject.reserve queue_name
@@ -54,7 +55,7 @@ describe BetterSqs::Client do
54
55
  sqs_message: sqs_message
55
56
  expect(sqs).
56
57
  to receive(:delete_message).
57
- with(queue_url: sqs.url_for_queue(queue_name), receipt_handle: sqs_message.receipt_handle)
58
+ with(queue_url: sqs.queues[queue_name].queue_url, receipt_handle: sqs_message.receipt_handle)
58
59
 
59
60
  subject.delete message_to_delete
60
61
  end
@@ -64,7 +65,7 @@ describe BetterSqs::Client do
64
65
  let(:mock_queue) {
65
66
  mq = SqsMocks::MockQueue.new
66
67
  mq.queue_name = queue_name
67
- mq.queue_url = sqs.queue_url
68
+ mq.queue_url = queue_url
68
69
  mq
69
70
  }
70
71
  it "creates the queue" do
@@ -73,7 +74,7 @@ describe BetterSqs::Client do
73
74
  end
74
75
 
75
76
  it "is the queue_url for the queue" do
76
- expect(subject.url_for_queue queue_name).to eq sqs.queue_url
77
+ expect(subject.url_for_queue queue_name).to eq sqs.queues.values.first.queue_url
77
78
  end
78
79
  end
79
80
 
@@ -85,7 +86,7 @@ describe BetterSqs::Client do
85
86
 
86
87
  expect(sqs).
87
88
  to receive(:change_message_visibility).
88
- with(queue_url: sqs.url_for_queue(queue_name),
89
+ with(queue_url: sqs.queues[queue_name].queue_url,
89
90
  receipt_handle: message_to_defer.receipt_handle,
90
91
  visibility_timeout: BetterSqs.configuration.sqs_message_deferral_seconds)
91
92
  subject.defer_retry message_to_defer
@@ -0,0 +1,47 @@
1
+ require "spec_helper"
2
+
3
+ describe BetterSqs::Queue do
4
+ subject { described_class.new better_client, queue_name }
5
+
6
+ let(:better_client) {
7
+ b = BetterSqs::Client.new
8
+ allow(b).to receive(:sqs).and_return mock_sqs
9
+ b
10
+ }
11
+ let(:mock_sqs) { SqsMocks::MockClient.new }
12
+ # let(:queue_url) { "some arn" }
13
+ let(:queue_name) { "superdupertuberqueue" }
14
+ let(:encoded_message) { { foo: "i am a foo" }.to_json }
15
+
16
+ describe "#push" do
17
+ it "pushes the encoded message onto the SQS queue" do
18
+ subject.push encoded_message
19
+ expect(mock_sqs.queues[queue_name].messages).to eq [encoded_message]
20
+ end
21
+ end
22
+
23
+ describe "#reserve" do
24
+ context "when there are messages in the queue to be received" do
25
+ it "returns a message from the queue" do
26
+ expected_message = BetterSqs::Message.new queue_client: better_client, queue: queue_name, sqs_message: encoded_message
27
+
28
+ subject.push encoded_message
29
+
30
+ expect(subject.reserve).to eq expected_message
31
+ end
32
+ end
33
+ context "when there are no messages in the queue to be received" do
34
+ it "is nil" do
35
+ expect(subject.reserve).to be_nil
36
+ end
37
+ end
38
+ end
39
+
40
+ described_class::QUEUE_ATTRIBUTES.each do |queue_attribute|
41
+ describe "##{queue_attribute}" do
42
+ it "gets the queue attribute: '#{queue_attribute}' from SQS" do
43
+ expect(subject.public_send queue_attribute).to eq SqsMocks::MockClient::FAUX_ATTRIBUTES[queue_attribute.to_s.camelize]
44
+ end
45
+ end
46
+ end
47
+ end
@@ -1,3 +1,5 @@
1
+ require "securerandom"
2
+
1
3
  def mock_queue_client
2
4
  double "QueueClient"
3
5
  end
@@ -12,30 +14,98 @@ end
12
14
 
13
15
  module SqsMocks
14
16
  class MockQueue
15
- attr_accessor :queue_name, :queue_url
16
- end
17
+ attr_accessor :queue_name, :queue_url, :messages
17
18
 
18
- class MockClient
19
- attr_accessor :queue_name, :queue_url
19
+ def initialize
20
+ @messages = []
21
+ end
22
+ end
20
23
 
21
- def initialize(queue_url)
22
- @queue_url = queue_url
24
+ class MockQueues < Hash
25
+ def [](key)
26
+ existing_val = super
27
+ return existing_val if existing_val
28
+ self[key] = create_queue queue_name: key
23
29
  end
24
30
 
25
- def create_queue(queue_name)
26
- @queue_name = queue_name
31
+ def create_queue(queue_name: nil)
27
32
  q = MockQueue.new
28
33
  q.queue_name = queue_name
34
+ queue_url = SecureRandom.hex(10)
29
35
  q.queue_url = queue_url
30
36
  q
31
37
  end
38
+ end
39
+
40
+ class MockClient
41
+ FAUX_ATTRIBUTES = {
42
+ "ApproximateNumberOfMessages" => 5,
43
+ "ApproximateNumberOfMessagesNotVisible" => 2,
44
+ "VisibilityTimeout" => 10,
45
+ "CreatedTimestamp" => 123_456,
46
+ "LastModifiedTimestamp" => 123_456,
47
+ "Policy" => :some_policy,
48
+ "MaximumMessageSize" => 256_000,
49
+ "MessageRetentionPeriod" => 86_400,
50
+ "QueueArn" => "arn:aws:sqs:us-east-1:201024061765:dolla-custom_list_creation_delete_user_tag_lots",
51
+ "ApproximateNumberOfMessagesDelayed" => 3,
52
+ "DelaySeconds" => 12,
53
+ "ReceiveMessageWaitTimeSeconds" => 25,
54
+ "RedrivePolicy" => :redrive_policy,
55
+ }
56
+ attr_accessor :queues
57
+
58
+ def initialize
59
+ @queues = MockQueues.new
60
+ end
61
+
62
+ def create_queue(queue_name: nil)
63
+ queues[queue_name]
64
+ end
65
+
66
+ def send_message(queue_url: nil, message_body: nil)
67
+ queue = queue_by_url queue_url
68
+ queue.messages << message_body
69
+ end
70
+
71
+ # If we get to the point of needing to mock visiblity then this approximation will not be adequate
72
+ def receive_message(queue_url: nil, max_number_of_messages: nil)
73
+ queue = queue_by_url queue_url
74
+ r = MockResponse.new
75
+ r.messages = Array(queue.messages.shift max_number_of_messages) if queue.messages.any?
76
+ r
77
+ end
78
+
79
+ # Just a static mock of the get_queue_attributes API
80
+ def get_queue_attributes(queue_url: nil, attribute_names: nil)
81
+ r = MockResponse.new
82
+ if attribute_names == "All"
83
+ r.attributes = FAUX_ATTRIBUTES
84
+ else
85
+ attribute_names.each do |attribute_name|
86
+ r.attributes[attribute_name] = FAUX_ATTRIBUTES[attribute_name]
87
+ end
88
+ end
89
+ r
90
+ end
91
+
92
+ private
93
+
94
+ def queue_by_url(queue_url)
95
+ queues.select { |_queue_name, q| q.queue_url == queue_url }.values.first
96
+ end
97
+ end
98
+
99
+ class MockResponse
100
+ attr_accessor :messages, :attributes
32
101
 
33
- def url_for_queue(_queue_name)
34
- @queue_url
102
+ def initialize
103
+ @messages = []
104
+ @attributes = {}
35
105
  end
36
106
  end
37
107
  end
38
108
 
39
- def mock_aws_sqs_client(queue_url: nil)
40
- SqsMocks::MockClient.new queue_url
109
+ def mock_aws_sqs_client
110
+ SqsMocks::MockClient.new
41
111
  end
metadata CHANGED
@@ -1,111 +1,125 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_sqs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Courtland Caldwell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-24 00:00:00.000000000 Z
11
+ date: 2016-04-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lincoln_logger
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: aws-sdk
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
33
  version: '2'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
40
  version: '2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rspec
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
- - - "~>"
59
+ - - ~>
46
60
  - !ruby/object:Gem::Version
47
61
  version: '3.2'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
- - - "~>"
66
+ - - ~>
53
67
  - !ruby/object:Gem::Version
54
68
  version: '3.2'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: byebug
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
- - - "~>"
73
+ - - ~>
60
74
  - !ruby/object:Gem::Version
61
75
  version: '3.5'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
- - - "~>"
80
+ - - ~>
67
81
  - !ruby/object:Gem::Version
68
82
  version: '3.5'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: simplecov
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
- - - "~>"
87
+ - - ~>
74
88
  - !ruby/object:Gem::Version
75
89
  version: '0.10'
76
90
  type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
- - - "~>"
94
+ - - ~>
81
95
  - !ruby/object:Gem::Version
82
96
  version: '0.10'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: rubocop
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
- - - "~>"
101
+ - - ~>
88
102
  - !ruby/object:Gem::Version
89
103
  version: '0.31'
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
- - - "~>"
108
+ - - ~>
95
109
  - !ruby/object:Gem::Version
96
110
  version: '0.31'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: rspec_junit_formatter
99
113
  requirement: !ruby/object:Gem::Requirement
100
114
  requirements:
101
- - - "~>"
115
+ - - ~>
102
116
  - !ruby/object:Gem::Version
103
117
  version: '0.2'
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
- - - "~>"
122
+ - - ~>
109
123
  - !ruby/object:Gem::Version
110
124
  version: '0.2'
111
125
  description: A convenient API for developers to interact with SQS with a trivial amount
@@ -115,9 +129,9 @@ executables: []
115
129
  extensions: []
116
130
  extra_rdoc_files: []
117
131
  files:
118
- - ".gitignore"
119
- - ".rubocop.yml"
120
- - ".rubocop_todo.yml"
132
+ - .gitignore
133
+ - .rubocop.yml
134
+ - .rubocop_todo.yml
121
135
  - LICENSE
122
136
  - README.md
123
137
  - better_sqs.gemspec
@@ -126,8 +140,10 @@ files:
126
140
  - lib/better_sqs/client.rb
127
141
  - lib/better_sqs/configuration.rb
128
142
  - lib/better_sqs/message.rb
143
+ - lib/better_sqs/queue.rb
129
144
  - spec/better_sqs/client_spec.rb
130
145
  - spec/better_sqs/message_spec.rb
146
+ - spec/better_sqs/queue_spec.rb
131
147
  - spec/better_sqs_spec.rb
132
148
  - spec/simplecov_custom_profile.rb
133
149
  - spec/spec_helper.rb
@@ -142,23 +158,24 @@ require_paths:
142
158
  - lib
143
159
  required_ruby_version: !ruby/object:Gem::Requirement
144
160
  requirements:
145
- - - ">="
161
+ - - '>='
146
162
  - !ruby/object:Gem::Version
147
163
  version: '0'
148
164
  required_rubygems_version: !ruby/object:Gem::Requirement
149
165
  requirements:
150
- - - ">="
166
+ - - '>='
151
167
  - !ruby/object:Gem::Version
152
168
  version: '0'
153
169
  requirements: []
154
170
  rubyforge_project:
155
- rubygems_version: 2.2.2
171
+ rubygems_version: 2.4.2
156
172
  signing_key:
157
173
  specification_version: 4
158
174
  summary: A more idiomatic interface to SQS.
159
175
  test_files:
160
176
  - spec/better_sqs/client_spec.rb
161
177
  - spec/better_sqs/message_spec.rb
178
+ - spec/better_sqs/queue_spec.rb
162
179
  - spec/better_sqs_spec.rb
163
180
  - spec/simplecov_custom_profile.rb
164
181
  - spec/spec_helper.rb