mad_mimi 0.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ .rvmrc
2
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,42 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ mad_mimi (0.0.1)
5
+ faraday (= 0.5.4)
6
+ faraday_middleware (= 0.3.1)
7
+ multi_xml (= 0.2.0)
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ addressable (2.2.3)
13
+ crack (0.1.8)
14
+ diff-lcs (1.1.2)
15
+ faraday (0.5.4)
16
+ addressable (~> 2.2.2)
17
+ multipart-post (~> 1.1.0)
18
+ rack (>= 1.1.0, < 2)
19
+ faraday_middleware (0.3.1)
20
+ faraday (~> 0.5.3)
21
+ multi_xml (0.2.0)
22
+ multipart-post (1.1.0)
23
+ rack (1.2.1)
24
+ rspec (2.4.0)
25
+ rspec-core (~> 2.4.0)
26
+ rspec-expectations (~> 2.4.0)
27
+ rspec-mocks (~> 2.4.0)
28
+ rspec-core (2.4.0)
29
+ rspec-expectations (2.4.0)
30
+ diff-lcs (~> 1.1.2)
31
+ rspec-mocks (2.4.0)
32
+ webmock (1.6.2)
33
+ addressable (>= 2.2.2)
34
+ crack (>= 0.1.7)
35
+
36
+ PLATFORMS
37
+ ruby
38
+
39
+ DEPENDENCIES
40
+ mad_mimi!
41
+ rspec (~> 2.4.0)
42
+ webmock (~> 1.6.2)
data/License.txt ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2011 Ozéias Sant'ana
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest ADDED
@@ -0,0 +1,2 @@
1
+ Rakefile
2
+ Manifest
data/README.rdoc ADDED
@@ -0,0 +1,8 @@
1
+ = MadMimi
2
+
3
+ Manage your MadMimi audience
4
+
5
+ == Copyright
6
+
7
+ Copyright (c) 2011 Ozéias Sant'ana. See LICENSE.txt for
8
+ further details.
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ $:.unshift File.expand_path("../lib", __FILE__)
2
+ require 'bundler'
3
+ require 'rake'
4
+ begin
5
+ Bundler::GemHelper.install_tasks
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+
12
+ require 'rspec'
13
+ require 'rspec/core/rake_task'
14
+ RSpec::Core::RakeTask.new(:spec) do |spec|
15
+ spec.pattern = FileList['spec/**/*_spec.rb']
16
+ end
17
+ task :default => :spec
18
+
19
+ desc 'Open an irb session preloaded with this library'
20
+ task :console do
21
+ sh 'irb -rubygems -I lib -r mad_mimi.rb'
22
+ end
data/lib/mad_mimi.rb ADDED
@@ -0,0 +1,44 @@
1
+ require "singleton"
2
+
3
+ require "mad_mimi/audience"
4
+ require "mad_mimi/config"
5
+
6
+ module MadMimi #:nodoc
7
+ class << self
8
+ # Sets the MadMimi configuration options. Best used by passing a block.
9
+ #
10
+ # Example:
11
+ #
12
+ # MadMimi.configure do |config|
13
+ # config.username = "emailaddress"
14
+ # config.api_key = "api_key"
15
+ # end
16
+ #
17
+ # Returns:
18
+ #
19
+ # The MadMimi +Config+ singleton instance.
20
+ def configure
21
+ config = MadMimi::Config.instance
22
+ block_given? ? yield(config) : config
23
+ end
24
+ alias :config :configure
25
+
26
+ # Authentication hash
27
+ #
28
+ # return [Hash]
29
+ def authentication
30
+ {
31
+ :username => configure.username,
32
+ :api_key => configure.api_key
33
+ }
34
+ end
35
+
36
+ def api_url
37
+ 'http://api.madmimi.com'
38
+ end
39
+
40
+ def audience
41
+ MadMimi::Audience.new
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,64 @@
1
+ require File.expand_path('../request', __FILE__)
2
+ module MadMimi #:nodoc
3
+ class Audience #:nodoc
4
+ include Request
5
+
6
+ # Get Audience Members
7
+ #
8
+ # Returns audience members paged in XML format.
9
+ #
10
+ # == Optional parameters are:
11
+ # * <tt>:page</tt> -- the current page to fetch
12
+ # * <tt>:per_page</tt> -- the number of audience members returned per page. Must be between 1 and 100
13
+ # * <tt>:order</tt> -- the ordering. Must be one of email, first_name, last_name and created_at
14
+ #
15
+ # See {Get Audience Members}[http://madmimi.com/developer/lists]
16
+ def members(options = {})
17
+ members = get('/audience_members')
18
+ members ? members["audience"]["member"] : members
19
+ end
20
+
21
+ # Get all Audience Lists
22
+ #
23
+ # Returns all audience lists
24
+ #
25
+ # See {Get all Audience Lists}[http://madmimi.com/developer/lists/get-all-audience-lists]
26
+ def lists
27
+ lists = get('/audience_lists/lists.xml')
28
+ lists ? lists["lists"]["list"] : lists
29
+ end
30
+
31
+ # Add Audience List Membership
32
+ #
33
+ # This will add an existing member to a list or create a new audience member with that
34
+ # email address and add that member to the list. Any additional parameters passed (such as
35
+ # first_name and last_name) will be +added+ or +updated+ on the audience member.
36
+ #
37
+ # See {Add Audience List Membership}[http://madmimi.com/developer/lists/add-membership]
38
+ def add_to_list(list, options = {})
39
+ post("/audience_lists/#{list}/add", options, true)
40
+ end
41
+
42
+ # Remove Audience List Membership
43
+ #
44
+ # Removes an existing email address from an audience list. The member is not deleted
45
+ # and will remain on any other lists. The email address is simply removed from that
46
+ # audience list.
47
+ #
48
+ # See {Remove Audience List Membership}[http://madmimi.com/developer/lists/remove-membership]
49
+ def remove_from_list(list, email)
50
+ post("/audience_lists/#{list}/remove", {:email => email})
51
+ end
52
+
53
+ # Suppress an Audience Member
54
+ #
55
+ # This adds the audience member to your suppression list, effectively preventing sending
56
+ # newsletters to that member (unsubscribing them). Audience members on your suppression
57
+ # list do not count towards your total active audience.
58
+ #
59
+ # See {Suppress an Audience Member}[http://madmimi.com/developer/lists/suppress-email]
60
+ def suppress(email)
61
+ post("/audience_members/#{email}/suppress_email")
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,8 @@
1
+ module MadMimi #:nodoc
2
+ class Config #:nodoc
3
+ include Singleton
4
+ attr_accessor :username, :api_key
5
+
6
+ def initialize;end
7
+ end
8
+ end
@@ -0,0 +1,45 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+
4
+ module MadMimi
5
+ # Defines HTTP request methods
6
+ module Request
7
+ def get(path, options={}, raw = false)
8
+ request(:get, path, options, raw)
9
+ end
10
+
11
+ def post(path, options={}, raw = false)
12
+ request(:post, path, options, raw)
13
+ end
14
+
15
+ private
16
+ def request(method, path, options, raw = false)
17
+ response = connection(raw).send(method) do |request|
18
+ options = options.merge(MadMimi.authentication)
19
+ case method
20
+ when :get
21
+ request.url(path, options)
22
+ when :post
23
+ request.path = path
24
+ request.body = options unless options.empty?
25
+ end
26
+ end
27
+ raw ? response : response.body
28
+ end
29
+
30
+ def connection(raw = false)
31
+ options = {
32
+ :headers => {'Accept' => "application/xml", 'User-Agent' => 'MadMimi Gem'},
33
+ :ssl => { :verify => false },
34
+ :url => MadMimi.api_url
35
+ }
36
+
37
+ Faraday::Connection.new(options) do |builder|
38
+ builder.adapter Faraday.default_adapter
39
+ unless raw
40
+ builder.use Faraday::Response::ParseXml
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,3 @@
1
+ module MadMimi
2
+ VERSION = "0.0.1" unless defined?(::MadMimi::VERSION)
3
+ end
data/mad_mimi.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ lib = File.expand_path('../lib/', __FILE__)
2
+ $:.unshift lib unless $:.include?(lib)
3
+
4
+ require 'mad_mimi/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'mad_mimi'
8
+ s.version = MadMimi::VERSION
9
+
10
+ s.authors = "Ozéias Sant'ana"
11
+ s.email = 'oz.santana@gmail.com'
12
+ s.homepage = 'http://railsbox.org'
13
+
14
+ s.summary = %q{Manage your MadMimi audience}
15
+
16
+ s.required_rubygems_version = Gem::Requirement.new('>= 1.3.7') if s.respond_to? :required_rubygems_version=
17
+
18
+ s.add_runtime_dependency 'faraday', '0.5.4'
19
+
20
+ s.add_dependency 'faraday_middleware', '0.3.1'
21
+ s.add_dependency 'multi_xml', '0.2.0'
22
+
23
+ s.add_development_dependency 'rspec', '~> 2.4.0'
24
+ s.add_development_dependency 'webmock', '~> 1.6.2'
25
+
26
+ s.files = `git ls-files`.split("\n")
27
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
28
+ s.require_paths = ['lib']
29
+ end
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <lists>
3
+ <list display_name="" subscriber_count="1" name="Friends" id="102938"/>
4
+ <list display_name="" subscriber_count="1" name="Clients" id="102939"/>
5
+ </lists>
@@ -0,0 +1,11 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <audience count="1" page="1" total_pages="1" per_page="30">
3
+ <member suppressed="false">
4
+ <first_name>Ozéias</first_name>
5
+ <last_name>Sant'ana</last_name>
6
+ <email>oz.santana@gmail.com</email>
7
+ <created_at>Fri Dec 10 18:09:50 -0500 2010</created_at>
8
+ <city></city>
9
+ <lists></lists>
10
+ </member>
11
+ </audience>
@@ -0,0 +1,92 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe MadMimi::Audience do
4
+ before (:all) do
5
+ MadMimi.configure do |config|
6
+ config.username = "email@example.com"
7
+ config.api_key = "api_key"
8
+ end
9
+ end
10
+
11
+ it "should connect using the api_url configuration" do
12
+ audience = MadMimi::Audience.new
13
+ connection = audience.send(:connection).build_url(nil).to_s
14
+ connection.should == "http://api.madmimi.com/"
15
+ end
16
+
17
+ describe ".members" do
18
+ before do
19
+ stub_get('/audience_members').
20
+ with(:headers => {'Accept'=>'application/xml', 'User-Agent'=>'MadMimi Gem'}).
21
+ to_return(:status => 200, :body => fixture("audience_members.xml"), :headers => {:content_type => "application/xml; charset=utf-8"})
22
+ end
23
+
24
+ it "should get the audience members" do
25
+ MadMimi.audience.members.should == {"city"=>nil, "created_at"=>"Fri Dec 10 18:09:50 -0500 2010", "suppressed"=>"false", "lists"=>nil, "last_name"=>"Sant'ana", "email"=>"oz.santana@gmail.com", "first_name"=>"Ozéias"}
26
+ end
27
+ end
28
+
29
+ describe ".lists" do
30
+ before do
31
+ stub_get('/audience_lists/lists.xml').
32
+ with(:headers => {'Accept'=>'application/xml', 'User-Agent'=>'MadMimi Gem'}).
33
+ to_return(:status => 200, :body => fixture("audience_lists.xml"), :headers => {:content_type => "application/xml; charset=utf-8"})
34
+ end
35
+
36
+ it "should get the audience members" do
37
+ MadMimi.audience.lists.should == [{"name"=>"Friends", "subscriber_count"=>"1", "id"=>"102938", "display_name"=>""}, {"name"=>"Clients", "subscriber_count"=>"1", "id"=>"102939", "display_name"=>""}]
38
+ end
39
+ end
40
+
41
+ describe ".add_to_list" do
42
+ before do
43
+ stub_post('/audience_lists/Clients/add').
44
+ with(:headers => {'Accept'=>'application/xml', 'User-Agent'=>'MadMimi Gem'}).
45
+ to_return(:status => 200, :body => " ", :headers => {:content_type => "text/html; charset=utf-8"})
46
+ end
47
+
48
+ it "should add audience list membership" do
49
+ client = {:first_name => 'Denise', :last_name => 'T. Guillen', :email => 'denise.t@example.com'}
50
+ MadMimi.audience.add_to_list('Clients', client)
51
+
52
+ a_post('/audience_lists/Clients/add').
53
+ with(:body => client.merge(MadMimi.authentication)).
54
+ with(:headers => {'Accept'=>'application/xml', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=>'MadMimi Gem'}).
55
+ should have_been_made
56
+ end
57
+ end
58
+
59
+ describe ".remove_from_list" do
60
+ before do
61
+ stub_post('/audience_lists/Clients/remove').
62
+ with(:headers => {'Accept'=>'application/xml', 'User-Agent'=>'MadMimi Gem'}).
63
+ to_return(:status => 200, :body => " ", :headers => {:content_type => "text/html; charset=utf-8"})
64
+ end
65
+
66
+ it "should remove audience list membership" do
67
+ MadMimi.audience.remove_from_list('Clients', 'denise.t@example.com')
68
+
69
+ a_post('/audience_lists/Clients/remove').
70
+ with(:body => {:email => 'denise.t@example.com'}.merge(MadMimi.authentication)).
71
+ with(:headers => {'Accept'=>'application/xml', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=>'MadMimi Gem'}).
72
+ should have_been_made
73
+ end
74
+ end
75
+
76
+ describe ".suppress" do
77
+ before do
78
+ stub_post('/audience_members/denise.t@example.com/suppress_email').
79
+ with(:headers => {'Accept'=>'application/xml', 'User-Agent'=>'MadMimi Gem'}).
80
+ to_return(:status => 200, :body => " ", :headers => {:content_type => "text/html; charset=utf-8"})
81
+ end
82
+
83
+ it "should suppress an audience member" do
84
+ MadMimi.audience.suppress('denise.t@example.com')
85
+
86
+ a_post('/audience_members/denise.t@example.com/suppress_email').
87
+ with(:body => MadMimi.authentication).
88
+ with(:headers => {'Accept'=>'application/xml', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=>'MadMimi Gem'}).
89
+ should have_been_made
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe MadMimi do
4
+ describe ".configure" do
5
+ ['username', 'api_key'].each do |key|
6
+ it "should set the #{key}" do
7
+ MadMimi.configure do |config|
8
+ config.send("#{key}=", key)
9
+ MadMimi.configure.send(key).should == key
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ describe ".authentication" do
16
+ before do
17
+ MadMimi.configure do |config|
18
+ config.username = "email@example.com"
19
+ config.api_key = "api_key"
20
+ end
21
+ end
22
+
23
+ it "should return the authentication hash" do
24
+ MadMimi.authentication.should == { :api_key => "api_key", :username => "email@example.com" }
25
+ end
26
+ end
27
+
28
+ describe ".api_url" do
29
+ it "should return the default api_url" do
30
+ MadMimi.api_url.should == 'http://api.madmimi.com'
31
+ end
32
+ end
33
+
34
+ describe ".audience" do
35
+ it "should be a MadMimi::Audience" do
36
+ MadMimi.audience.should be_a MadMimi::Audience
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,30 @@
1
+ require File.expand_path('../../lib/mad_mimi', __FILE__)
2
+
3
+ require 'rspec'
4
+ require 'webmock/rspec'
5
+ include WebMock::API
6
+
7
+ def a_post(path)
8
+ a_request(:post, MadMimi.api_url + path)
9
+ end
10
+
11
+ def stub_get(path)
12
+ path = path + '?' + parameterize(MadMimi.authentication)
13
+ stub_request(:get, MadMimi.api_url + path)
14
+ end
15
+
16
+ def stub_post(path)
17
+ stub_request(:post, MadMimi.api_url + path)
18
+ end
19
+
20
+ def fixture_path
21
+ File.expand_path("../fixtures", __FILE__)
22
+ end
23
+
24
+ def fixture(file)
25
+ File.new(fixture_path + '/' + file)
26
+ end
27
+
28
+ def parameterize(params)
29
+ URI.escape(params.collect{|k,v| "#{k}=#{v}"}.join('&'))
30
+ end
metadata ADDED
@@ -0,0 +1,169 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mad_mimi
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - "Oz\xC3\xA9ias Sant'ana"
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-23 00:00:00 -02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: faraday
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - "="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ - 5
33
+ - 4
34
+ version: 0.5.4
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: faraday_middleware
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - "="
44
+ - !ruby/object:Gem::Version
45
+ hash: 17
46
+ segments:
47
+ - 0
48
+ - 3
49
+ - 1
50
+ version: 0.3.1
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: multi_xml
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - "="
60
+ - !ruby/object:Gem::Version
61
+ hash: 23
62
+ segments:
63
+ - 0
64
+ - 2
65
+ - 0
66
+ version: 0.2.0
67
+ type: :runtime
68
+ version_requirements: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ prerelease: false
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ hash: 31
78
+ segments:
79
+ - 2
80
+ - 4
81
+ - 0
82
+ version: 2.4.0
83
+ type: :development
84
+ version_requirements: *id004
85
+ - !ruby/object:Gem::Dependency
86
+ name: webmock
87
+ prerelease: false
88
+ requirement: &id005 !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ hash: 11
94
+ segments:
95
+ - 1
96
+ - 6
97
+ - 2
98
+ version: 1.6.2
99
+ type: :development
100
+ version_requirements: *id005
101
+ description:
102
+ email: oz.santana@gmail.com
103
+ executables: []
104
+
105
+ extensions: []
106
+
107
+ extra_rdoc_files: []
108
+
109
+ files:
110
+ - .gitignore
111
+ - Gemfile
112
+ - Gemfile.lock
113
+ - License.txt
114
+ - Manifest
115
+ - README.rdoc
116
+ - Rakefile
117
+ - lib/mad_mimi.rb
118
+ - lib/mad_mimi/audience.rb
119
+ - lib/mad_mimi/config.rb
120
+ - lib/mad_mimi/request.rb
121
+ - lib/mad_mimi/version.rb
122
+ - mad_mimi.gemspec
123
+ - spec/fixtures/audience_lists.xml
124
+ - spec/fixtures/audience_members.xml
125
+ - spec/mad_mimi/audience_spec.rb
126
+ - spec/mad_mimi_spec.rb
127
+ - spec/spec_helper.rb
128
+ has_rdoc: true
129
+ homepage: http://railsbox.org
130
+ licenses: []
131
+
132
+ post_install_message:
133
+ rdoc_options: []
134
+
135
+ require_paths:
136
+ - lib
137
+ required_ruby_version: !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ hash: 3
143
+ segments:
144
+ - 0
145
+ version: "0"
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
147
+ none: false
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ hash: 21
152
+ segments:
153
+ - 1
154
+ - 3
155
+ - 7
156
+ version: 1.3.7
157
+ requirements: []
158
+
159
+ rubyforge_project:
160
+ rubygems_version: 1.3.7
161
+ signing_key:
162
+ specification_version: 3
163
+ summary: Manage your MadMimi audience
164
+ test_files:
165
+ - spec/fixtures/audience_lists.xml
166
+ - spec/fixtures/audience_members.xml
167
+ - spec/mad_mimi/audience_spec.rb
168
+ - spec/mad_mimi_spec.rb
169
+ - spec/spec_helper.rb