acts_as_icontact 0.3.0 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -1,19 +1,20 @@
1
1
  ActsAsIcontact
2
2
  ==============
3
- ActsAsIcontact connects Ruby applications with the [iContact e-mail marketing service](http://icontact.com) using the iContact API v2.0. Building on the [RestClient](http://rest-client.heroku.com) gem, it offers two significant feature sets:
3
+ ActsAsIcontact connects Ruby applications with the [iContact e-mail marketing service][1] using the iContact API v2.0. Building on the [RestClient][2] gem, it offers three significant feature sets:
4
4
 
5
- * Simple, consistent access to all resources in the iContact API; and
5
+ * Simple, consistent access to all resources in the iContact API;
6
+ * A simple command-line client; and
6
7
  * Automatic synchronizing between ActiveRecord models and iContact contact lists for Rails applications.
7
8
 
8
9
  Prerequisites
9
10
  -------------
10
11
  You'll need the following to use this gem properly:
11
12
 
12
- 1. **Ruby 1.9** Yeah, we know, change is _scary_ and a zillion of your other gems only work in 1.8. But ActsAsIcontact makes use of a few 1.9 features for efficiency, such as Enumerators. It's _possible_ that this might work in 1.8.7 if you install the **JSON** gem and `require 'enumerator'` explicitly -- but the author hasn't tested it. If you need it to work in 1.8, speak up. Or better yet, make it work and submit a patch.
13
+ 1. **Ruby 1.9:** Yes, we know, many other gems still only work in 1.8. But ActsAsIcontact makes use of a few 1.9.1 features for efficiency, such as fiber-based Enumerators to step through large collections without instantiating a thousand objects at once. It's _possible_ that this might work in 1.8.7 if you install the **JSON** gem and `require 'enumerator'` explicitly -- but the author hasn't tested it. If you need it to work in 1.8, speak up. Or better yet, make it work and submit a patch.
13
14
 
14
- 2. **Rails 2.1** _(If using Rails integration)_ We use ActiveRecord's 'dirty fields' feature that first appeared in 2.1 to determine whether iContact needs updating. If you're on a version of Rails older than this, it's probably worth your while to update anyway.
15
+ 2. **Rails 2.1 or higher:** _(If using Rails integration)_ We use ActiveRecord's 'dirty fields' feature that first appeared in 2.1 to determine whether iContact needs updating. If you're on a version of Rails older than this, it's probably worth your while to update anyway.
15
16
 
16
- 3. **rest-client** This gem _should_ install when you install the **acts\_as\_icontact** gem. But we include it here for completeness.
17
+ 3. **Other gems:** This gem requires the [RestClient][2], [ActiveSupport][3] and [Bond][4] gems in order to work. Simply doing a `gem install` _should_ install these dependencies as well.
17
18
 
18
19
  Setting Up
19
20
  ----------
@@ -31,21 +32,36 @@ Using ActsAsIcontact is easy, but going through iContact's authorization process
31
32
 
32
33
  * **PRODUCTION:** Go to <http://app.icontact.com/icp/core/externallogin> and enter `IYDOhgaZGUKNjih3hl1ItLln7zpAtWN2` for the Application Id. Choose a password for ActsAsIcontact that's different from your account password.
33
34
 
34
- 4. Set your _(sandbox, if applicable)_ account username and the password you just chose for API access. You can either set the environment variables `ICONTACT_MODE`, `ICONTACT_USERNAME`, and `ICONTACT_PASSWORD`, or you can explicitly do it with calls to the Config module:
35
+ 4. Set your _(sandbox, if applicable)_ account username and the password you just chose for API access. See the next section for how to specify these.
36
+
37
+ 5. Rinse and repeat with production credentials when you're ready to move out of the sandbox environment. For more information, consult the [iContact API developer documentation][5].
38
+
39
+ Authentication
40
+ --------------
41
+ ActsAsIcontact already knows iContact's URL and its own Application Id, so the only things you need to tell it are your username, password, and whether you want to access the production or sandbox environments. There are three simple ways to do that:
42
+
43
+ 1. Set the environment variables `ICONTACT_MODE`, `ICONTACT_USERNAME`, and `ICONTACT_PASSWORD`. The `ICONTACT_MODE` environment variable should have a value of either ___production___ or ___sandbox___.
44
+
45
+ 2. Create a directory called **.icontact** under your home directory and place a YAML file in it titled **config.yml**:
46
+ ---
47
+ mode: production
48
+ username: my_username
49
+ password: my_password
50
+ This hidden directory is also used for the command line client's history file, and future versions of ActsAsIcontact may use it for caching.
51
+
52
+ 3. You can explicitly set them anywhere in your code with calls to the Config module (note that the mode is a symbol, not a string):
35
53
 
36
54
  require 'rubygems'
37
55
  require 'acts_as_icontact'
38
56
 
39
57
  ActsAsIcontact::Config.mode = :sandbox
40
- ActsAsIcontact::Config.username = my_sandbox_username
41
- ActsAsIcontact::Config.password = my_api_password
58
+ ActsAsIcontact::Config.username = "my_sandbox_username"
59
+ ActsAsIcontact::Config.password = "my_api_password"
42
60
 
43
61
  If you're using Rails, the recommended approach is to require the gem with `config.gem 'acts_as_icontact'` in your **config/environment.rb** file, and then set up an initializer (i.e. **config/initializers/acts\_as\_icontact.rb**) with the above code. See more about Rails below.
44
62
 
45
- 5. Rinse and repeat with production credentials when you're ready to move out of the sandbox environment.
46
-
47
- API Access
48
- ----------
63
+ Using the API
64
+ -------------
49
65
  Whether or not you're using Rails, retrieving and modifying iContact resources is simple. The gem autodiscovers your account and client folder IDs (you only have one of each unless you're an 'agency' account), so you can jump straight to the good parts:
50
66
 
51
67
  contacts = ActsAsIcontact::Contact.find(:all) # => <#ActsAsIcontact::ResourceCollection>
@@ -61,7 +77,7 @@ Whether or not you're using Rails, retrieving and modifying iContact resources i
61
77
 
62
78
 
63
79
  ### Nesting
64
- The interface is deliberately as "ActiveRecord-like" as possible, with methods linking resources that are either nested in iContact's URLs or logically related. Messages have a Message#bounces method. Lists have List#subscribers to list the Contacts subscribed to them, and Contacts have Contact#lists. Read the documentation for each class to find out what you can do:
80
+ The interface is deliberately as "ActiveRecord-like" as possible, with methods linking resources that are either nested in iContact's URLs or logically related. Messages have a Message#bounces method. Lists have `List#subscribers` to list the Contacts subscribed to them, and Contacts have `Contact#lists`. Read the [documentation][5] for each class to find out what you can do:
65
81
 
66
82
  * ActsAsIcontact::Account
67
83
  * ActsAsIcontact::ClientFolder
@@ -86,17 +102,64 @@ The interface is deliberately as "ActiveRecord-like" as possible, with methods l
86
102
  * ActsAsIcontact::Time
87
103
 
88
104
  ### Searching
89
- Searches are handled in a sane way using the same query options that iContact accepts. The following are all valid:
105
+ Searches are handled using the same query options that iContact accepts, but with a syntax based on ActiveRecord. At this time, special searches (i.e. _gte_, _bet_ etc.) are not yet supported. Fields requiring dates must be given a string corresponding to the ISO8601 timestamp (e.g. `2006-09-16T14:30:00-06:00`); proper date/time conversion will happen soon. See the [iContact developer docs][5] for available search options.
106
+
107
+ The following class methods are offered (using the Message class as an example):
108
+
109
+ #### Message.first
110
+
111
+ Returns a single Message. With no parameters, it returns the first Message in iContact's system, which may be arbitrary. You can specify one or more search parameters as an options hash (note the Ruby 1.9 syntax):
112
+ Message.first(messageType: "welcome") # => The first welcome message
113
+ Message.first(orderby: "createDate:desc") # => Most recent message
114
+
115
+ If no records can be found matching the parameters, the **first** method returns nil.
116
+
117
+ #### Message.all
118
+
119
+ Returns a collection of Messages matching the search parameters. The _limit_ and _offset_ parameters are important here; if no _limit_ is provided, a default limit of 500 records is used. (That default is also the maximum, at the request of iContact's technical staff.)
120
+
121
+ The collection is an object of type ResourceCollection, and it acts both as an array and an enumerator. For efficiency, individual Message objects are instantiated only when you access them.
122
+ Message.all(messageType: "confirmation") # => All confirmation messages (up to 500)
123
+ Message.all(limit: 20) # => The first 20 messages
124
+ Message.all(limit: 20, offset: 40) # => Messages 41-60
125
+ Message.all(offset:500) # => Messages 501-1000
126
+
127
+ # Example of collection iteration
128
+ @messages = Message.all # => Assigns the first 500 messages to @messages
129
+ @messages.count # => Number of messages
130
+ @messages[11] # => Twelfth message in the collection (arrays are 0-based)
131
+ @messages.first # => First message
132
+ @messages.next # => Second message
133
+ @messages.next # => Third message (et cetera)
134
+
135
+ If no records can be found matching the parameters, the **all** method returns nil.
136
+
137
+ #### Message.find
90
138
 
91
- `Messages.all` -- *Same as `Messages.find(:all)`*
92
- `Messages.first` -- *Same as `Messages.find(:first)`*
93
- `Messages.find(:all, :limit => 20)` -- *First 20 messages*
94
- `Messages.find(:all, :limit => 20, :offset => 40)` -- *Messages 41-60*
95
- `Messages.first(:subject => "Fnord")` -- *First message with the given subject*
96
- `Messages.all(:orderby => createDate, :desc => true)` -- *Messages ordered by most recent first*
97
- `Messages.all(:messageType => "welcome", :campaignId => 11)` -- *Welcome messages from the given campaign*
139
+ Like its ActiveRecord role model, #find has several behaviors depending on its parameter list:
140
+
141
+ Message.find(:first, messageType: "welcome") # => Identical to Message.first(messageType: "welcome")
142
+ Message.find(:all, limit: 20) # => Identical to Message.all(limit: 20)
143
+ Message.find(7) # => Single Message found with messageId of 7
144
+ Message.find("foo") # => Single Message found with subject of "foo"
145
+
146
+ The _integer_ and _string_ parameter modes warrant some explanation. Passing an integer to **find** on most resource classes will do a primary key lookup. So Accounts will match on the accountId, Contacts will match on the contactId, etc. The integer variant is unsupported for the CustomField and Subscription classes, which use string-based primary keys.
147
+
148
+ Passing a string to **find** on most resource classes will do a single-record search based on the field most likely to be unique and important:
149
+
150
+ * **Account:** userName
151
+ * **Campaign:** name
152
+ * **ClientFolder:** name
153
+ * **Contact:** email
154
+ * **CustomField:** customFieldId _(primary key)_
155
+ * **List:** name
156
+ * **Message:** subject
157
+ * **Segment:** name
158
+ * **Subscription:** subscriptionId _(primary key)_
159
+ * **User:** userName
160
+
161
+ If no records can be found using **find**, the _:first_ and _:all_ variants will return nil (just like **first** and **all**). The _integer_ and _string_ variants will return an exception, on the assumption that you knew exactly what you were looking for and expected it to be there. (I.e., matching the behavior of ActiveRecord.)
98
162
 
99
- At this time, special searches are not yet supported. Fields requiring dates must also be given a string corresponding to the ISO8601 timestamp (e.g. `2006-09-16T14:30:00-06:00`). Proper date/time conversion will happen soon.
100
163
 
101
164
  ### Updating
102
165
 
@@ -107,11 +170,11 @@ Again, think ActiveRecord. When you initialize an object, you can optionally pa
107
170
  :email => "bob@example.org")
108
171
  c.address = "123 Test Street"
109
172
 
110
- Each resource class has a `#save` method which returns true or false. If false, the `#error` method contains the reply back from iContact about what went wrong. (Which may or may not be informative, but we can't tell you more than they do.) There's also a`#save!`method which throws an exception instead.
173
+ Each resource object has a **#save** method which returns true or false. If false, the **#error** method contains the reply back from iContact about what went wrong. (Which may or may not be informative, but we can't tell you more than they do.) There's also a **#save!** method which throws an exception on failure instead of returning false.
111
174
 
112
- Nested resources can be created using the `build_` method (which returns an object but doesn't save it right away) or `create_` method (which does save it upon creation). The full panoply of ActiveRecord association methods are not implemented yet. (Hey, we said it was AR-_like._)
175
+ Nested resources can be created using the **build\_foo** method (which returns an object but doesn't save it right away) or **create\_foo** method (which does save it upon creation). The full panoply of ActiveRecord association methods are not implemented yet. (Hey, we said it was AR-_like._)
113
176
 
114
- The `#delete` method on each class works as you'd expect, assuming iContact allows deletes on that resource. Resource collections containing the resource are not updated, however, so you may need to requery.
177
+ The **#delete** method on each object works as you'd expect, assuming iContact allows deletes on that resource. Resource collections containing the resource are not updated, however, so you may need to requery.
115
178
 
116
179
  Multiple-record updates are not implemented at this time.
117
180
 
@@ -197,4 +260,10 @@ iContact's interface is really quite good at handling pretty much every other re
197
260
 
198
261
  Copyright
199
262
  ---------
200
- Copyright (c) 2009 Stephen Eley. See LICENSE for details.
263
+ Copyright (c) 2009 Stephen Eley. See LICENSE for details.
264
+
265
+ [1]: http://icontact.com "iContact"
266
+ [2]: http://rest-client.heroku.com "Rest-Client"
267
+ [3]: http://as.rubyonrails.org/ "ActiveSupport"
268
+ [4]: http://tagaholic.me/bond "Bond"
269
+ [5]: http://developer.icontact.com/ "iContact Developer Portal"
data/Rakefile CHANGED
@@ -10,7 +10,18 @@ begin
10
10
  gem.homepage = "http://github.com/SFEley/acts_as_icontact"
11
11
  gem.authors = ["Stephen Eley"]
12
12
  gem.rubyforge_project = "actsasicontact"
13
+ gem.executables = "icontact"
14
+ gem.has_rdoc = true
13
15
  gem.extra_rdoc_files = ["README.markdown"]
16
+ gem.rdoc_options << '--all'
17
+ gem.add_dependency 'rest-client', '>= 1.0'
18
+ gem.add_dependency 'activesupport', '>= 2.3.2'
19
+ gem.add_dependency 'bond', '>= 0.1.4'
20
+ gem.add_development_dependency 'rspec'
21
+ gem.add_development_dependency 'mocha'
22
+ gem.add_development_dependency 'fakeweb'
23
+
24
+
14
25
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
26
  gem.description = <<ENDDESC
16
27
  ActsAsIcontact connects Ruby applications with the iContact e-mail marketing service using the iContact API v2.0. Building on the RestClient gem, it offers two significant feature sets:
@@ -40,7 +51,7 @@ end
40
51
 
41
52
  task :default => :spec
42
53
 
43
- require 'hanna/rdoctask'
54
+ require 'rake/rdoctask'
44
55
  Rake::RDocTask.new do |rdoc|
45
56
  if File.exist?('VERSION.yml')
46
57
  config = YAML.load(File.read('VERSION.yml'))
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.3.2
@@ -1,12 +1,15 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
1
4
  # -*- encoding: utf-8 -*-
2
5
 
3
6
  Gem::Specification.new do |s|
4
7
  s.name = %q{acts_as_icontact}
5
- s.version = "0.3.0"
8
+ s.version = "0.3.2"
6
9
 
7
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
11
  s.authors = ["Stephen Eley"]
9
- s.date = %q{2009-08-01}
12
+ s.date = %q{2009-08-08}
10
13
  s.default_executable = %q{icontact}
11
14
  s.description = %q{ActsAsIcontact connects Ruby applications with the iContact e-mail marketing service using the iContact API v2.0. Building on the RestClient gem, it offers two significant feature sets:
12
15
 
@@ -40,6 +43,7 @@ Gem::Specification.new do |s|
40
43
  "lib/acts_as_icontact/resource.rb",
41
44
  "lib/acts_as_icontact/resource_collection.rb",
42
45
  "lib/acts_as_icontact/resources/account.rb",
46
+ "lib/acts_as_icontact/resources/campaign.rb",
43
47
  "lib/acts_as_icontact/resources/client.rb",
44
48
  "lib/acts_as_icontact/resources/contact.rb",
45
49
  "lib/acts_as_icontact/resources/custom_field.rb",
@@ -56,7 +60,8 @@ Gem::Specification.new do |s|
56
60
  "spec/resource_collection_spec.rb",
57
61
  "spec/resource_spec.rb",
58
62
  "spec/resources/account_spec.rb",
59
- "spec/resources/client_spec.rb",
63
+ "spec/resources/campaign_spec.rb",
64
+ "spec/resources/clientfolder_spec.rb",
60
65
  "spec/resources/contact_spec.rb",
61
66
  "spec/resources/custom_field_spec.rb",
62
67
  "spec/resources/list_spec.rb",
@@ -69,7 +74,7 @@ Gem::Specification.new do |s|
69
74
  "spec/support/spec_fakeweb.rb"
70
75
  ]
71
76
  s.homepage = %q{http://github.com/SFEley/acts_as_icontact}
72
- s.rdoc_options = ["--charset=UTF-8"]
77
+ s.rdoc_options = ["--charset=UTF-8", "--all"]
73
78
  s.require_paths = ["lib"]
74
79
  s.rubyforge_project = %q{actsasicontact}
75
80
  s.rubygems_version = %q{1.3.5}
@@ -84,7 +89,8 @@ Gem::Specification.new do |s|
84
89
  "spec/resource_collection_spec.rb",
85
90
  "spec/resource_spec.rb",
86
91
  "spec/resources/account_spec.rb",
87
- "spec/resources/client_spec.rb",
92
+ "spec/resources/campaign_spec.rb",
93
+ "spec/resources/clientfolder_spec.rb",
88
94
  "spec/resources/contact_spec.rb",
89
95
  "spec/resources/custom_field_spec.rb",
90
96
  "spec/resources/list_spec.rb",
@@ -101,8 +107,26 @@ Gem::Specification.new do |s|
101
107
  s.specification_version = 3
102
108
 
103
109
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
110
+ s.add_runtime_dependency(%q<rest-client>, [">= 1.0"])
111
+ s.add_runtime_dependency(%q<activesupport>, [">= 2.3.2"])
112
+ s.add_runtime_dependency(%q<bond>, [">= 0.1.4"])
113
+ s.add_development_dependency(%q<rspec>, [">= 0"])
114
+ s.add_development_dependency(%q<mocha>, [">= 0"])
115
+ s.add_development_dependency(%q<fakeweb>, [">= 0"])
104
116
  else
117
+ s.add_dependency(%q<rest-client>, [">= 1.0"])
118
+ s.add_dependency(%q<activesupport>, [">= 2.3.2"])
119
+ s.add_dependency(%q<bond>, [">= 0.1.4"])
120
+ s.add_dependency(%q<rspec>, [">= 0"])
121
+ s.add_dependency(%q<mocha>, [">= 0"])
122
+ s.add_dependency(%q<fakeweb>, [">= 0"])
105
123
  end
106
124
  else
125
+ s.add_dependency(%q<rest-client>, [">= 1.0"])
126
+ s.add_dependency(%q<activesupport>, [">= 2.3.2"])
127
+ s.add_dependency(%q<bond>, [">= 0.1.4"])
128
+ s.add_dependency(%q<rspec>, [">= 0"])
129
+ s.add_dependency(%q<mocha>, [">= 0"])
130
+ s.add_dependency(%q<fakeweb>, [">= 0"])
107
131
  end
108
132
  end
data/bin/icontact CHANGED
@@ -12,7 +12,7 @@ module ActsAsIcontact
12
12
  history_file = File.join(ENV["HOME"], '.icontact_history')
13
13
  IO.readlines(history_file).each {|e| Readline::HISTORY << e.chomp } if File.exists?(history_file)
14
14
  print "# ActsAsIcontact command line (type 'exit' to quit)\n"
15
- while (input = Readline.readline('>> ', true)) != 'exit'
15
+ while (input = Readline.readline("\n>> ", true)) != 'exit'
16
16
  begin puts "=> #{eval(input).inspect}"; rescue Exception; puts "Error: #{$!}" end
17
17
  end
18
18
  File.open(history_file, 'w') {|f| f.write Readline::HISTORY.to_a.join("\n") }
@@ -1,5 +1,6 @@
1
1
  require 'activesupport'
2
2
  require 'uri'
3
+ require 'YAML'
3
4
 
4
5
  module ActsAsIcontact
5
6
  # Base class for shared functionality between iContact resources. Supports getting, finding, saving,
@@ -150,6 +151,11 @@ module ActsAsIcontact
150
151
  properties == obj.properties
151
152
  end
152
153
 
154
+ # Returns a nice formatted string for command line use.
155
+ def inspect
156
+ properties.to_yaml
157
+ end
158
+
153
159
  protected
154
160
  # The minimum set of fields that must be sent back to iContact on an update.
155
161
  # Includes any fields that changed or were added, the primary key, and anything
@@ -173,7 +179,7 @@ module ActsAsIcontact
173
179
  # The base RestClient resource that this particular class nests from. Defaults to
174
180
  # the clientFolders path since that's the most common case.
175
181
  def self.base
176
- ActsAsIcontact.client
182
+ ActsAsIcontact.clientfolder
177
183
  end
178
184
 
179
185
  # The name of the singular resource type pulled from iContact. Defaults to the lowercase
@@ -1,15 +1,17 @@
1
1
  module ActsAsIcontact
2
2
  class ResourceCollection < Enumerator
3
- attr_reader :total, :retrieved
3
+ attr_reader :total, :retrieved, :offset, :collection_name
4
4
 
5
5
  def initialize(klass, collection, forwardTo=nil)
6
6
  @klass = klass
7
7
  @forwardTo = forwardTo
8
8
 
9
- @collection = collection[klass.collection_name]
9
+ @collection_name = klass.collection_name
10
+ @collection = collection[collection_name]
10
11
  # Get number of elements
11
12
  @retrieved = @collection.size
12
13
  @total = collection["total"]
14
+ @offset = collection["offset"]
13
15
 
14
16
  enumcode = Proc.new do |yielder|
15
17
  counter = 0
@@ -32,6 +34,18 @@ module ActsAsIcontact
32
34
  self.next
33
35
  end
34
36
 
37
+ # Returns a nice formatted string for command line use.
38
+ def inspect
39
+ if offset.to_i > 0
40
+ "#{retrieved} out of #{total} #{collection_name} (offset #{offset})"
41
+ elsif retrieved != total
42
+ "#{retrieved} out of #{total} #{collection_name}"
43
+ else
44
+ "#{total} #{collection_name}"
45
+ end
46
+
47
+ end
48
+
35
49
  private
36
50
  def resource(properties)
37
51
  if @forwardTo
@@ -0,0 +1,30 @@
1
+ module ActsAsIcontact
2
+ class Campaign < Resource
3
+
4
+ # Defaults forwardToFriend to 0; subscriptionManagement, clickTrackMode to true; and useAccountAddress, archiveByDefault to false
5
+ def initialize(properties={})
6
+ super({:forwardToFriend => 0,
7
+ :clickTrackMode => true,
8
+ :subscriptionManagement => true,
9
+ :useAccountAddress => false,
10
+ :archiveByDefault => false}.merge(properties))
11
+ end
12
+
13
+ # Requires name, fromName, fromEmail, forwardToFriend, subscriptionManagement, clickTrackMode, useAccountAddress, and archiveByDefault
14
+ def self.required_on_create
15
+ super + %w(name fromName fromEmail forwardToFriend subscriptionManagement clickTrackMode useAccountAddress archiveByDefault)
16
+ end
17
+
18
+ # The following can be set with true or false: subscriptionManagement, clickTrackMode, useAccountAddress, archiveByDefault
19
+ def self.boolean_fields
20
+ super + %w(subscriptionManagement clickTrackMode useAccountAddress archiveByDefault)
21
+ end
22
+
23
+ # Returns a collection of all Message resources matching this campaignId. Additional search options can be passed to further restrict the result set.
24
+ def messages(options={})
25
+ search = {:campaignId => id}.merge(options)
26
+ Message.all(search)
27
+ end
28
+
29
+ end
30
+ end
@@ -1,7 +1,7 @@
1
1
  module ActsAsIcontact
2
2
  # The nested Client Folder resource from iContact. Currently only supports retrieval -- and is
3
3
  # highly targeted toward the _first_ client folder, since that seems to be the dominant use case.
4
- class Client < Resource
4
+ class ClientFolder < Resource
5
5
  # Derives from the Account resource.
6
6
  def self.base
7
7
  ActsAsIcontact.account
@@ -26,25 +26,25 @@ module ActsAsIcontact
26
26
 
27
27
  # The clientFolderId retrieved from iContact. Can also be set manually for performance
28
28
  # optimization, but remembers it so that it won't be pulled more than once anyway.
29
- def self.client_id
30
- @client_id ||= Client.first.clientFolderId.to_i
29
+ def self.clientfolder_id
30
+ @clientfolder_id ||= ClientFolder.first.clientFolderId.to_i
31
31
  end
32
32
 
33
33
  # Manually sets the clientFolderId used in subsequent calls. Setting this in your
34
34
  # initializer will save at least one unnecessary request to the iContact server.
35
- def self.client_id=(val)
36
- @client_id = val
35
+ def self.clientfolder_id=(val)
36
+ @clientfolder_id = val
37
37
  end
38
38
 
39
39
  # RestClient subresource scoped to the specific account ID. Most other iContact calls will derive
40
40
  # from this one.
41
- def self.client
42
- @client ||= account["c/#{client_id}"]
41
+ def self.clientfolder
42
+ @clientfolder ||= account["c/#{clientfolder_id}"]
43
43
  end
44
44
 
45
45
  # Clears the account resource from memory. Called by reset_connection! since the only likely reason
46
46
  # to do this is connecting as a different user.
47
- def self.reset_client!
48
- @client = nil
47
+ def self.reset_clientfolder!
48
+ @clientfolder = nil
49
49
  end
50
50
  end
@@ -6,11 +6,6 @@ module ActsAsIcontact
6
6
  super << 'email'
7
7
  end
8
8
 
9
- # Derived from clientFolder
10
- def self.base
11
- ActsAsIcontact.client
12
- end
13
-
14
9
  # Defaults to status=total to return contacts on or off lists
15
10
  def self.default_options
16
11
  super.merge(:status=>:total)
@@ -1,9 +1,5 @@
1
1
  module ActsAsIcontact
2
2
  class List < Resource
3
- # Derives from clientFolder.
4
- def self.base
5
- ActsAsIcontact.client
6
- end
7
3
 
8
4
  # Searches on list name.
9
5
  def self.find_by_string(value)
@@ -15,6 +11,7 @@ module ActsAsIcontact
15
11
  super << "name" << "emailOwnerOnChange" << "welcomeOnManualAdd" << "welcomeOnSignupAdd" << "welcomeMessageId"
16
12
  end
17
13
 
14
+ # The following can be set with true or false: emailOwnerOnChange, welcomeOnManualAdd, welcomeOnSignupAdd
18
15
  def self.boolean_fields
19
16
  super << "emailOwnerOnChange" << "welcomeOnManualAdd" << "welcomeOnSignupAdd"
20
17
  end
@@ -15,5 +15,14 @@ module ActsAsIcontact
15
15
  messageType = %w(normal autoresponder welcome confirmation)
16
16
  raise ActsAsIcontact::ValidationError, "messageType must be one of: " + messageType.join(', ') unless messageType.include?(fields["messageType"])
17
17
  end
18
+
19
+ # Returns the Campaign resource associated with this message, if campaignId is set. Otherwise returns nil. Returns an exception if the campaignId is set but the campaign cannot be found.
20
+ def campaign
21
+ if (c = campaignId.to_i) > 0
22
+ Campaign.find(c)
23
+ else
24
+ nil
25
+ end
26
+ end
18
27
  end
19
28
  end
@@ -24,4 +24,32 @@ describe ActsAsIcontact::ResourceCollection do
24
24
  @this.first.foo.should == "bar"
25
25
  @this.next.yoo.should == "yar"
26
26
  end
27
+
28
+ it "knows its total size" do
29
+ @this.total.should == 2
30
+ end
31
+
32
+ it "knows its count" do
33
+ @this.count.should == 2
34
+ end
35
+
36
+ it "knows its offset" do
37
+ @this.offset.should == 0
38
+ end
39
+
40
+ it "has a nice string representation when all resources are retrieved" do
41
+ r = ActsAsIcontact::Resource.all
42
+ r.inspect.should =~ /^12 resources/
43
+ end
44
+
45
+ it "has a nice string representation when some resources are retrieved" do
46
+ r = ActsAsIcontact::Resource.all(limit: 5)
47
+ r.inspect.should =~ /^5 out of 12 resources/
48
+ end
49
+
50
+ it "has a nice string representation when an offset is used" do
51
+ r = ActsAsIcontact::Resource.all(limit: 5, offset: 5)
52
+ r.inspect.should =~ /^5 out of 12 resources \(offset 5\)/
53
+ end
54
+
27
55
  end
@@ -2,7 +2,7 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe ActsAsIcontact::Resource do
4
4
  it "has a RestClient connection" do
5
- ActsAsIcontact::Resource.connection.url.should == ActsAsIcontact.client['resources'].url
5
+ ActsAsIcontact::Resource.connection.url.should == ActsAsIcontact.clientfolder['resources'].url
6
6
  end
7
7
 
8
8
  it "can return all resources for the given URL" do
@@ -13,6 +13,13 @@ describe ActsAsIcontact::Resource do
13
13
  ActsAsIcontact::Resource.first.should be_a_kind_of(ActsAsIcontact::Resource)
14
14
  end
15
15
 
16
+ it "has a nice string representation" do
17
+ r = ActsAsIcontact::Resource.first
18
+ r.inspect.should =~ /foo: bar/m
19
+ r.inspect.should =~ /resourceId: 1/m
20
+ r.inspect.should =~ /too: bar/m
21
+ end
22
+
16
23
  describe "find method" do
17
24
  it "returns a ResourceCollection when given :all" do
18
25
  r = ActsAsIcontact::Resource.find(:all)
@@ -104,7 +111,7 @@ describe ActsAsIcontact::Resource do
104
111
 
105
112
  it "has its own connection if it's not new" do
106
113
  r = ActsAsIcontact::Resource.first
107
- r.connection.url.should == ActsAsIcontact.client['resources/1'].url
114
+ r.connection.url.should == ActsAsIcontact.clientfolder['resources/1'].url
108
115
  end
109
116
 
110
117
  it "does not have a connection if it's new" do
@@ -113,7 +120,7 @@ describe ActsAsIcontact::Resource do
113
120
  end
114
121
 
115
122
  it "knows its REST base resource" do
116
- ActsAsIcontact::Resource.base.should == ActsAsIcontact.client
123
+ ActsAsIcontact::Resource.base.should == ActsAsIcontact.clientfolder
117
124
  end
118
125
 
119
126
  it "knows its primary key" do
@@ -0,0 +1,58 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe ActsAsIcontact::Campaign do
4
+ before(:each) do
5
+ @contact = ActsAsIcontact::Campaign.new
6
+ end
7
+
8
+ it "requires a name" do
9
+ lambda{@contact.save}.should raise_error(ActsAsIcontact::ValidationError, /name/)
10
+ end
11
+
12
+ it "requires a fromName" do
13
+ lambda{@contact.save}.should raise_error(ActsAsIcontact::ValidationError, /fromName/)
14
+ end
15
+
16
+
17
+ it "requires a fromEmail" do
18
+ lambda{@contact.save}.should raise_error(ActsAsIcontact::ValidationError, /fromEmail/)
19
+ end
20
+
21
+
22
+ it "defaults forwardToFriend to 0" do
23
+ @contact.forwardToFriend.should == 0
24
+ end
25
+
26
+ it "defaults subscriptionManagement to true" do
27
+ @contact.subscriptionManagement.should be_true
28
+ end
29
+
30
+ it "defaults clickTrackMode to true" do
31
+ @contact.subscriptionManagement.should be_true
32
+ end
33
+
34
+ it "defaults useAccountAddress to false" do
35
+ @contact.useAccountAddress.should be_false
36
+ end
37
+
38
+ it "defaults archiveByDefault to false" do
39
+ @contact.archiveByDefault.should be_false
40
+ end
41
+
42
+ context "associations" do
43
+ before(:each) do
44
+ @campaign = ActsAsIcontact::Campaign.first
45
+ end
46
+
47
+ it "knows which messages it has (if any)" do
48
+ m = @campaign.messages
49
+ m.count.should == 2
50
+ end
51
+
52
+ it "can narrow down the messages list" do
53
+ m = @campaign.messages(messageType: "welcome")
54
+ m.count.should == 1
55
+ end
56
+ end
57
+
58
+ end
@@ -2,51 +2,51 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
3
  describe ActsAsIcontact, "account_id" do
4
4
  it "returns the ID from the first client folder returned by iContact" do
5
- ActsAsIcontact.client_id.should == 222222
5
+ ActsAsIcontact.clientfolder_id.should == 222222
6
6
  end
7
7
 
8
8
  it "can be set by the user" do
9
- ActsAsIcontact.client_id = 456
10
- ActsAsIcontact.client_id.should == 456
9
+ ActsAsIcontact.clientfolder_id = 456
10
+ ActsAsIcontact.clientfolder_id.should == 456
11
11
  end
12
12
 
13
13
  after(:each) do
14
- ActsAsIcontact.client_id = nil
14
+ ActsAsIcontact.clientfolder_id = nil
15
15
  end
16
16
  end
17
17
 
18
18
 
19
- describe ActsAsIcontact, "client method" do
19
+ describe ActsAsIcontact, "clientfolder method" do
20
20
  it "returns a RestClient resource" do
21
- ActsAsIcontact.client.should be_a_kind_of(RestClient::Resource)
21
+ ActsAsIcontact.clientfolder.should be_a_kind_of(RestClient::Resource)
22
22
  end
23
23
 
24
24
  it "builds upon the 'account' object" do
25
25
  ActsAsIcontact.expects(:account).returns(ActsAsIcontact.instance_variable_get(:@account))
26
- ActsAsIcontact.client.should_not be_nil
26
+ ActsAsIcontact.clientfolder.should_not be_nil
27
27
  end
28
28
 
29
29
  it "can be cleared with the reset_account! method" do
30
- ActsAsIcontact.reset_client!
31
- ActsAsIcontact.instance_variable_get(:@client).should be_nil
30
+ ActsAsIcontact.reset_clientfolder!
31
+ ActsAsIcontact.instance_variable_get(:@clientfolder).should be_nil
32
32
  end
33
33
 
34
34
  after(:each) do
35
- ActsAsIcontact.reset_client!
35
+ ActsAsIcontact.reset_clientfolder!
36
36
  end
37
37
  end
38
38
 
39
- describe ActsAsIcontact::Client do
39
+ describe ActsAsIcontact::ClientFolder do
40
40
  it "can return all clients for the given account" do
41
- ActsAsIcontact::Client.all.count.should == 1
41
+ ActsAsIcontact::ClientFolder.all.count.should == 1
42
42
  end
43
43
 
44
44
  it "can return the first client" do
45
- ActsAsIcontact::Client.first.should be_a_kind_of(ActsAsIcontact::Client)
45
+ ActsAsIcontact::ClientFolder.first.should be_a_kind_of(ActsAsIcontact::ClientFolder)
46
46
  end
47
47
 
48
48
  it "knows its properties" do
49
- c = ActsAsIcontact::Client.first
49
+ c = ActsAsIcontact::ClientFolder.first
50
50
  c.emailRecipient.should == "bob@example.org"
51
51
  end
52
52
  end
@@ -22,7 +22,9 @@ describe ActsAsIcontact::Message do
22
22
  @message = ActsAsIcontact::Message.first(:subject => "Test Message")
23
23
  end
24
24
 
25
- it "knows which campaign it has (if any)"
25
+ it "knows which campaign it has (if any)" do
26
+ @message.campaign.name.should == "Test Campaign"
27
+ end
26
28
  end
27
29
 
28
30
  end
@@ -7,7 +7,7 @@ ic = "#{i}/a/111111/c/222222"
7
7
 
8
8
  # Resources (this one's a fake stub for pure testing)
9
9
  FakeWeb.register_uri(:get, "#{ic}/resources?limit=500", :body => %q<{"resources":[{"foo":"bar","resourceId":"1","too":"bar"},{"foo":"aar","resourceId":"2"},{"foo":"far","resourceId":"3"},{"foo":"car","resourceId":"4"},{"foo":"dar","resourceId":"5"},{"foo":"ear","resourceId":"6"},{"foo":"gar","resourceId":"7"},{"foo":"har","resourceId":"8"},{"foo":"iar","resourceId":"9"},{"foo":"jar","resourceId":"10"},{"foo":"kar","resourceId":"11"},{"foo":"yar","resourceId":"12"}],"total":12,"limit":20,"offset":0}>)
10
- FakeWeb.register_uri(:get, "#{ic}/resources?limit=1", :body => %q<{"resources":[{"foo":"bar","resourceId":"1","too":"bar"},{"foo":"aar","resourceId":"2"},{"foo":"far","resourceId":"3"},{"foo":"car","resourceId":"4"},{"foo":"dar","resourceId":"5"},{"foo":"ear","resourceId":"6"},{"foo":"gar","resourceId":"7"},{"foo":"har","resourceId":"8"},{"foo":"iar","resourceId":"9"},{"foo":"jar","resourceId":"10"},{"foo":"kar","resourceId":"11"},{"foo":"yar","resourceId":"12"}],"total":12,"limit":20,"offset":0}>)
10
+ FakeWeb.register_uri(:get, "#{ic}/resources?limit=1", :body => %q<{"resources":[{"foo":"bar","resourceId":"1","too":"bar"}],"total":12,"limit":1,"offset":0}>)
11
11
  FakeWeb.register_uri(:get, "#{ic}/resources?limit=5", :body => %q<{"resources":[{"foo":"bar","resourceId":"1"},{"foo":"aar","resourceId":"2"},{"foo":"far","resourceId":"3"},{"foo":"car","resourceId":"4"},{"foo":"dar","resourceId":"5"}],"total":12,"limit":5,"offset":0}>)
12
12
  FakeWeb.register_uri(:get, "#{ic}/resources?limit=500&offset=5", :body => %q<{"resources":[{"foo":"ear","resourceId":"6"},{"foo":"gar","resourceId":"7"},{"foo":"har","resourceId":"8"},{"foo":"iar","resourceId":"9"},{"foo":"jar","resourceId":"10"},{"foo":"kar","resourceId":"11"},{"foo":"yar","resourceId":"12"}],"total":12,"limit":20,"offset":5}>)
13
13
  FakeWeb.register_uri(:get, "#{ic}/resources?offset=5&limit=5", :body => %q<{"resources":[{"foo":"ear","resourceId":"6"},{"foo":"gar","resourceId":"7"},{"foo":"har","resourceId":"8"},{"foo":"iar","resourceId":"9"},{"foo":"jar","resourceId":"10"}],"total":12,"limit":5,"offset":5}>)
@@ -40,12 +40,14 @@ FakeWeb.register_uri(:get, "#{ic}/lists/444444", :body => %q<{"list":{"listId":"
40
40
 
41
41
  # Message
42
42
  #### Test welcome message for List association
43
- FakeWeb.register_uri(:get, "#{ic}/messages/555555", :body => %q<{"message":{"messageId":"555555","subject":"Welcome!","messageType":"welcome","textBody":"Welcome to the Test List!","htmlBody":"<p>Welcome to the <b>Test List</b>!</p>","createDate":"20090725 14:55:12"}}>)
43
+ FakeWeb.register_uri(:get, "#{ic}/messages/555555", :body => %q<{"message":{"messageId":"555555","subject":"Welcome!","messageType":"welcome","textBody":"Welcome to the Test List!","htmlBody":"<p>Welcome to the <b>Test List</b>!</p>","createDate":"20090725 14:55:12","campaignId":"777777"}}>)
44
44
  #### Test confirmation message
45
- FakeWeb.register_uri(:get, "#{ic}/messages/555666", :body => %q<{"message":{"messageId":"555666","subject":"Confirm!","messageType":"confirmation","textBody":"Please confirm your subscription.","htmlBody":"<p>Please confirm your subscription.</p>","createDate":"20090727 14:55:12"}}>)
46
-
45
+ FakeWeb.register_uri(:get, "#{ic}/messages/555666", :body => %q<{"message":{"messageId":"555666","subject":"Confirm!","messageType":"confirmation","textBody":"Please confirm your subscription.","htmlBody":"<p>Please confirm your subscription.</p>","createDate":"20090727 14:55:12","campaignId":"777777"}}>)
46
+ #### Searches from campaignId
47
+ FakeWeb.register_uri(:get, "#{ic}/messages?limit=500&campaignId=777777", :body => %q<{"messages":[{"messageId":"555555","subject":"Welcome!","messageType":"welcome","textBody":"Welcome to the Test List!","htmlBody":"<p>Welcome to the <b>Test List</b>!</p>","createDate":"20090725 14:55:12","campaignId":"777777"},{"messageId":"555666","subject":"Confirm!","messageType":"confirmation","textBody":"Please confirm your subscription.","htmlBody":"<p>Please confirm your subscription.</p>","createDate":"20090727 14:55:12","campaignId":"777777"}],"count":2}>)
48
+ FakeWeb.register_uri(:get, "#{ic}/messages?limit=500&campaignId=777777&messageType=welcome", :body => %q<{"messages":[{"messageId":"555555","subject":"Welcome!","messageType":"welcome","textBody":"Welcome to the Test List!","htmlBody":"<p>Welcome to the <b>Test List</b>!</p>","createDate":"20090725 14:55:12","campaignId":"777777"}],"count":1}>)
47
49
  #### Test message for associations originating from Message spec
48
- FakeWeb.register_uri(:get, "#{ic}/messages?limit=1&subject=Test%20Message", :body => %q<{"messages":[{"messageId":"666666","subject":"Test Message","messageType":"normal","textBody":"Hi there!\nThis is just a test.","htmlBody":"<p><b>Hi there!</b></p><p>This is just a <i>test.</i></p>","createDate":"20090725 14:53:33"}]}>)
50
+ FakeWeb.register_uri(:get, "#{ic}/messages?limit=1&subject=Test%20Message", :body => %q<{"messages":[{"messageId":"666666","subject":"Test Message","messageType":"normal","textBody":"Hi there!\nThis is just a test.","htmlBody":"<p><b>Hi there!</b></p><p>This is just a <i>test.</i></p>","createDate":"20090725 14:53:33","campaignId":"777777"}]}>)
49
51
 
50
52
  # CustomField
51
53
  FakeWeb.register_uri(:get, "#{ic}/customfields?limit=500", :body => %q<{"customfields":[{"privateName":"test_field","publicName":"Test Field","displayToUser":"0","fieldType":"text"},{"privateName":"custom_field","publicName":"This is for the Rails integration specs","displayToUser":1,"fieldType":"text"}],"total":2}>)
@@ -60,3 +62,7 @@ FakeWeb.register_uri(:get, "#{ic}/subscriptions?limit=1&contactId=333444", :body
60
62
  FakeWeb.register_uri(:get, "#{ic}/subscriptions?limit=500&contactId=333444", :body => %q<{"subscriptions":[{"status":"normal","addDate":"2009-07-27T15:36:37-04:00","contactId":333444,"listId":444444, "subscriptionId":"444444_333444","confirmationMessageId":555666}]}>)
61
63
  FakeWeb.register_uri(:get, "#{ic}/subscriptions?limit=500&contactId=333333", :body => %q<{"subscriptions":[{"status":"normal","addDate":"2009-07-27T15:36:37-04:00","contactId":333333,"listId":444444, "subscriptionId":"444444_333333","confirmationMessageId":555666}]}>)
62
64
  FakeWeb.register_uri(:post, "#{ic}/subscriptions", :body => %q<{"subscriptions":[{"status":"normal","addDate":"2009-07-27T15:36:37-04:00","contactId":333333,"listId":444444, "subscriptionId":"444444_333333","confirmationMessageId":555666}]}>)
65
+
66
+ # Campaign
67
+ FakeWeb.register_uri(:get, "#{ic}/campaigns?limit=1", :body => %q<{"campaigns":[{"campaignId":"777777","name":"Test Campaign","fromName":"Bob Smith","fromEmail":"bob@example.org","forwardToFriend":0,"subscriptionManagement":1,"clickTrackMode":1,"useAccountAddress":0,"archiveByDefault":0,"description":""}],"count":1}>)
68
+ FakeWeb.register_uri(:get, "#{ic}/campaigns/777777", :body => %q<{"campaign":{"campaignId":"777777","name":"Test Campaign","fromName":"Bob Smith","fromEmail":"bob@example.org","forwardToFriend":0,"subscriptionManagement":1,"clickTrackMode":1,"useAccountAddress":0,"archiveByDefault":0,"description":""}}>)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts_as_icontact
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Eley
@@ -9,10 +9,69 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-01 00:00:00 -04:00
12
+ date: 2009-08-08 00:00:00 -04:00
13
13
  default_executable: icontact
14
- dependencies: []
15
-
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rest-client
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "1.0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: activesupport
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.3.2
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: bond
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 0.1.4
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: rspec
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: mocha
57
+ type: :development
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ - !ruby/object:Gem::Dependency
66
+ name: fakeweb
67
+ type: :development
68
+ version_requirement:
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ version:
16
75
  description: |
17
76
  ActsAsIcontact connects Ruby applications with the iContact e-mail marketing service using the iContact API v2.0. Building on the RestClient gem, it offers two significant feature sets:
18
77
 
@@ -48,6 +107,7 @@ files:
48
107
  - lib/acts_as_icontact/resource.rb
49
108
  - lib/acts_as_icontact/resource_collection.rb
50
109
  - lib/acts_as_icontact/resources/account.rb
110
+ - lib/acts_as_icontact/resources/campaign.rb
51
111
  - lib/acts_as_icontact/resources/client.rb
52
112
  - lib/acts_as_icontact/resources/contact.rb
53
113
  - lib/acts_as_icontact/resources/custom_field.rb
@@ -64,7 +124,8 @@ files:
64
124
  - spec/resource_collection_spec.rb
65
125
  - spec/resource_spec.rb
66
126
  - spec/resources/account_spec.rb
67
- - spec/resources/client_spec.rb
127
+ - spec/resources/campaign_spec.rb
128
+ - spec/resources/clientfolder_spec.rb
68
129
  - spec/resources/contact_spec.rb
69
130
  - spec/resources/custom_field_spec.rb
70
131
  - spec/resources/list_spec.rb
@@ -82,6 +143,7 @@ licenses: []
82
143
  post_install_message:
83
144
  rdoc_options:
84
145
  - --charset=UTF-8
146
+ - --all
85
147
  require_paths:
86
148
  - lib
87
149
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -113,7 +175,8 @@ test_files:
113
175
  - spec/resource_collection_spec.rb
114
176
  - spec/resource_spec.rb
115
177
  - spec/resources/account_spec.rb
116
- - spec/resources/client_spec.rb
178
+ - spec/resources/campaign_spec.rb
179
+ - spec/resources/clientfolder_spec.rb
117
180
  - spec/resources/contact_spec.rb
118
181
  - spec/resources/custom_field_spec.rb
119
182
  - spec/resources/list_spec.rb