action_network_rest 0.2.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cc85d83854d521199b82e855ee4369c66c076a8487753756cc454010a0a22907
4
- data.tar.gz: 684db90a396a39ebbdc54ffec3fcdba678a2338fbc334052786f7422d4990eb9
3
+ metadata.gz: a6ad7612c6bccf090f5e717750753d3f47314b53b0a36d0b59907102f1dcd1eb
4
+ data.tar.gz: adddc2d4bb8bab60b0db1ebb4312651793e757f193f177c68562c2b96d57cdd2
5
5
  SHA512:
6
- metadata.gz: fa5f2ece5e76ef8bfbffd96349eb0c545c423da441a318fab71458d86f7ebfd483a4bc7f512f25df73ad9a5f1acfc32a1f60e1acb69770f5b0c75b8b695420ec
7
- data.tar.gz: '0897288683f87fc8a9a273d360bf01bbbcf0da24bf7d90ffbb1176299a79f376a01d55e57af7a7680a771c8787579f78353eb5d32a08b0691d131b76f4431b45'
6
+ metadata.gz: f9e77003bda8400d416e299575383eb36c4d9aa43e8451abb29877e7fd329d5fad8dd58655137218525d351ae49e6b274e75f80e75db90a94161f4ac9eeb9f43
7
+ data.tar.gz: 171aa0166b8a8667f9ee1540ca5bdf3182401a9a7c91badd0bb701815d17e4f0ae22435da8e9202d636a25d7f9a3dd607272f13519238d0110cc4944e0f66021
data/.env.sample ADDED
@@ -0,0 +1,2 @@
1
+ # API key used on example.rb, you don't need to define this in the gem including code
2
+ API_KEY=xyz
data/.gitignore CHANGED
@@ -11,25 +11,12 @@
11
11
  /tmp/
12
12
 
13
13
  # Used by dotenv library to load environment variables.
14
- # .env
14
+ .env
15
15
 
16
16
  # Ignore Byebug command history file.
17
17
  .byebug_history
18
18
 
19
- ## Specific to RubyMotion:
20
- .dat*
21
- .repl_history
22
- build/
23
- *.bridgesupport
24
- build-iPhoneOS/
25
- build-iPhoneSimulator/
26
-
27
- ## Specific to RubyMotion (use of CocoaPods):
28
- #
29
- # We recommend against adding the Pods directory to your .gitignore. However
30
- # you should judge for yourself, the pros and cons are mentioned at:
31
- # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
32
- #
19
+
33
20
  # vendor/Pods/
34
21
 
35
22
  ## Documentation cache and generated files:
@@ -56,3 +43,6 @@ Gemfile.lock
56
43
  # .rubocop-https?--*
57
44
 
58
45
  .rspec_status
46
+ .DS_store
47
+ .idea/
48
+ .rakeTasks
data/.rubocop.yml ADDED
@@ -0,0 +1,14 @@
1
+ require:
2
+ - rubocop-performance
3
+
4
+ AllCops:
5
+ NewCops: enable
6
+ TargetRubyVersion: 2.6
7
+ Metrics/BlockLength:
8
+ Enabled: false
9
+ Naming/AccessorMethodName:
10
+ Enabled: false
11
+ Naming/MemoizedInstanceVariableName:
12
+ Enabled: false
13
+ Style/Documentation:
14
+ Enabled: false
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.6.6
1
+ 2.7.3
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.7
4
+ cache: bundler
5
+ before_install:
6
+ - gem install bundler
7
+ script:
8
+ - bundle exec rspec
9
+ - bundle exec rubocop
data/Gemfile CHANGED
@@ -1,6 +1,8 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ source 'https://rubygems.org'
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
6
 
5
7
  # Specify your gem's dependencies in action_network_rest.gemspec
6
8
  gemspec
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # ActionNetworkRest
2
2
 
3
- Ruby client for interacting with the [ActionNetwork REST API](https://actionnetwork.org/docs/)
3
+ Ruby client for interacting with the [ActionNetwork REST API](https://actionnetwork.org/docs/) from the engineering team at [ControlShift](https://www.controlshiftlabs.com/).
4
+
5
+ [![Build Status](https://travis-ci.org/controlshift/action-network-rest.svg?branch=master)](https://travis-ci.org/controlshift/action-network-rest)
4
6
 
5
7
  ## Installation
6
8
 
@@ -21,6 +23,8 @@ Or install it yourself as:
21
23
  ## Usage
22
24
 
23
25
  ```
26
+ require 'action_network_rest'
27
+
24
28
  client = ActionNetworkRest.new(api_key: YOUR_API_KEY)
25
29
 
26
30
  # Check that our API key is working. Returns true or false.
@@ -33,10 +37,29 @@ client.entry_point.get
33
37
  person = client.people.create(email_addresses: [{address: 'foo@example.com'}])
34
38
  person_id = person.action_network_id
35
39
 
40
+ # List people
41
+ people = client.people.list
42
+
43
+ # Iterate over a list of people
44
+ page_number = 1
45
+ loop do
46
+ people = client.people.list(page: page_number)
47
+ break if people.empty?
48
+ page_number += 1
49
+ end
50
+
36
51
  # Retrieve a Person's data
37
52
  person = client.people.get(person_id)
38
53
  puts person.email_addresses
39
54
 
55
+ # Retrieve a Person's data by their email address
56
+ person = client.people.find_by_email(person_email)
57
+ person_id = person.action_network_id
58
+ puts person.email_addresses
59
+
60
+ # Update a Person
61
+ client.people.update(person_id, {custom_fields: {custom_id: "12345"}})
62
+
40
63
  # Unsubscribe a Person
41
64
  client.people.unsubscribe(person_id)
42
65
 
@@ -63,6 +86,34 @@ puts signature.created_date
63
86
 
64
87
  # Update a Signature
65
88
  client.petitions(petition_id).signatures.update(signature_id, {comments: 'new comments'})
89
+
90
+ # Create a Tag
91
+ tag = client.tags.create('Volunteers')
92
+ tag_id = tag.action_network_id
93
+
94
+ # Retrieve a Tag
95
+ tag = client.tags.get(tag_id)
96
+
97
+ # Retrieve a Tag by name
98
+ tag = client.tags.find_by_name('Volunteers')
99
+
100
+ # Apply a Tag to a Person
101
+ tagging = client.tags(tag_id).create({identifiers: ['external:123']}, person_id: person_id)
102
+ tagging_id = tagging.action_network_id
103
+
104
+ # Retrieve a Tagging
105
+ tagging = client.tags(tag_id).taggings.get(tagging_id)
106
+
107
+ # Delete a Tagging
108
+ client.tags(tag_id).taggings.delete(tagging_id)
109
+
110
+ # List Events in an Event Campaign
111
+ event_campaign_id = '123e4567-e89b-12d3-a456-426614174000'
112
+ client.event_campaigns(event_campaign_id).events.list
113
+
114
+ # Add an Attendance
115
+ event_id = '123e4567-e89b-12d3-a456-426655440000'
116
+ client.events(event_id).attendances.create({ person: {email_addresses: [{address: 'alice@example.com'}]}})
66
117
  ```
67
118
 
68
119
  ## Development
@@ -71,6 +122,8 @@ After checking out the repo, run `bundle install` to install dependencies. Then,
71
122
 
72
123
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
73
124
 
125
+ To run a REPL with an initialized client object you'll need to create your own `.env` file based off `.env.sample` and then run `bundle exec ruby example.rb`.
126
+
74
127
  ## Contributing
75
128
 
76
129
  Bug reports and pull requests are welcome on GitHub at https://github.com/controlshift/action-network-rest. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- task :default => :spec
8
+ task default: :spec
@@ -1,29 +1,36 @@
1
+ # frozen_string_literal: true
1
2
 
2
- lib = File.expand_path("../lib", __FILE__)
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "action_network_rest/version"
5
+ require 'action_network_rest/version'
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = "action_network_rest"
8
+ spec.name = 'action_network_rest'
8
9
  spec.version = ActionNetworkRest::VERSION
9
- spec.authors = ["Grey Moore"]
10
- spec.email = ["grey@controlshiftlabs.com"]
10
+ spec.authors = ['Grey Moore']
11
+ spec.email = ['grey@controlshiftlabs.com']
11
12
 
12
- spec.summary = "Ruby client for interacting with the ActionNetwork REST API"
13
- spec.homepage = "https://github.com/controlshift/action-network-rest"
14
- spec.license = "MIT"
13
+ spec.summary = 'Ruby client for interacting with the ActionNetwork REST API'
14
+ spec.homepage = 'https://github.com/controlshift/action-network-rest'
15
+ spec.license = 'MIT'
15
16
 
16
17
  # Specify which files should be added to the gem when it is released.
17
18
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
18
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
19
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
19
20
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
21
  end
21
- spec.require_paths = ["lib"]
22
+ spec.require_paths = ['lib']
22
23
 
23
- spec.add_runtime_dependency "vertebrae", "~> 0.6.0"
24
+ spec.required_ruby_version = '>= 2.6'
24
25
 
25
- spec.add_development_dependency "bundler", "~> 2.1"
26
- spec.add_development_dependency "rake", "~> 13.0"
27
- spec.add_development_dependency "rspec", "~> 3.0"
26
+ spec.add_runtime_dependency 'vertebrae', '~> 0.6.0'
27
+
28
+ spec.add_development_dependency 'bundler', '~> 2.1'
29
+ spec.add_development_dependency 'byebug', '~> 11.1'
30
+ spec.add_development_dependency 'dotenv', '~> 2.7'
31
+ spec.add_development_dependency 'rake', '~> 13.0'
32
+ spec.add_development_dependency 'rspec', '~> 3.0'
33
+ spec.add_development_dependency 'rubocop'
34
+ spec.add_development_dependency 'rubocop-performance'
28
35
  spec.add_development_dependency 'webmock', '~> 3.8.3'
29
36
  end
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'action_network_rest'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require 'irb'
15
+ IRB.start(__FILE__)
data/bin/rake ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rake' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require 'pathname'
12
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path('bundle', __dir__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300))
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require 'rubygems'
27
+ require 'bundler/setup'
28
+
29
+ load Gem.bin_path('rake', 'rake')
data/bin/rspec ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rspec' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require 'pathname'
12
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path('bundle', __dir__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300))
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require 'rubygems'
27
+ require 'bundler/setup'
28
+
29
+ load Gem.bin_path('rspec-core', 'rspec')
data/example.rb ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/action_network_rest'
4
+ require 'dotenv'
5
+ require 'byebug'
6
+
7
+ Dotenv.load('.env')
8
+ raise 'Must set API_KEY environmental variable. See .env.sample for details' if ENV['API_KEY'].nil?
9
+
10
+ client = ActionNetworkRest.new(api_key: ENV['API_KEY']) # rubocop:disable Lint/UselessAssignment
11
+
12
+ puts "Ready to call Action Network API using 'client' object"
13
+ byebug # rubocop:disable Lint/Debugger
14
+
15
+ puts 'Bye!'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'vertebrae'
2
4
 
3
5
  module ActionNetworkRest
@@ -10,11 +12,16 @@ module ActionNetworkRest
10
12
  end
11
13
  end
12
14
 
13
- require "action_network_rest/version"
14
- require "action_network_rest/client"
15
+ require 'action_network_rest/version'
16
+ require 'action_network_rest/client'
15
17
  require 'action_network_rest/base'
16
18
 
19
+ require 'action_network_rest/attendances'
17
20
  require 'action_network_rest/entry_point'
21
+ require 'action_network_rest/events'
22
+ require 'action_network_rest/event_campaigns'
18
23
  require 'action_network_rest/people'
19
24
  require 'action_network_rest/petitions'
20
25
  require 'action_network_rest/signatures'
26
+ require 'action_network_rest/taggings'
27
+ require 'action_network_rest/tags'
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionNetworkRest
4
+ class Attendances < Base
5
+ attr_accessor :event_campaign_id, :event_id
6
+
7
+ def base_path
8
+ if event_campaign_id.present?
9
+ "event_campaigns/#{url_escape(event_campaign_id)}/events/#{url_escape(event_id)}/attendances/"
10
+ else
11
+ "events/#{url_escape(event_id)}/attendances/"
12
+ end
13
+ end
14
+
15
+ def create(attendance_data)
16
+ response = client.post_request base_path, attendance_data
17
+ object_from_response(response)
18
+ end
19
+
20
+ def update(id, attendance_data)
21
+ response = client.put_request "#{base_path}#{url_escape(id)}", attendance_data
22
+ object_from_response(response)
23
+ end
24
+
25
+ private
26
+
27
+ def osdi_key
28
+ 'osdi:attendance'
29
+ end
30
+ end
31
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionNetworkRest
2
4
  class Base < Vertebrae::Model
3
5
  def get(id)
@@ -5,25 +7,31 @@ module ActionNetworkRest
5
7
  object_from_response(response)
6
8
  end
7
9
 
10
+ def list(page: 1)
11
+ response = client.get_request "#{base_path}?page=#{url_escape(page)}"
12
+ objects = response.body.dig('_embedded', osdi_key)
13
+ return [] if objects.nil?
14
+
15
+ objects.each { |obj| set_action_network_id_on_object(obj) }
16
+
17
+ objects
18
+ end
19
+
8
20
  private
9
21
 
10
22
  def url_escape(string)
11
23
  CGI.escape(string.to_s)
12
24
  end
13
25
 
14
- def object_from_response(response)
15
- obj = response.body
16
-
17
- # The response we get from Action Network may contain an "identifiers" block that looks something like:
18
- #
26
+ def set_action_network_id_on_object(obj)
27
+ # Takes an object which may contain an `identifiers` key, which may contain an action_network identifier
28
+ # If so, we pull out the action_network identifier and stick it in a top-level key "action_network_id",
29
+ # for the convenience of callers using the returned object.
19
30
  # "identifiers": [
20
31
  # "action_network:d6bdf50e-c3a4-4981-a948-3d8c086066d7",
21
32
  # "some_external_system:1",
22
33
  # "another_external_system:57"
23
34
  # ]
24
- #
25
- # If so, we pull out the action_network identifier and stick it in a top-level key "action_network_id",
26
- # for the convenience of callers using the returned object.
27
35
  identifiers = obj[:identifiers] || []
28
36
  qualified_actionnetwork_id = identifiers.find do |id|
29
37
  id.split(':').first == 'action_network'
@@ -35,6 +43,11 @@ module ActionNetworkRest
35
43
  obj
36
44
  end
37
45
 
46
+ def object_from_response(response)
47
+ obj = response.body
48
+ set_action_network_id_on_object(obj)
49
+ end
50
+
38
51
  def action_network_url(path)
39
52
  client.connection.configuration.endpoint + path
40
53
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionNetworkRest
2
4
  class Client < Vertebrae::API
3
5
  attr_accessor :api_key
4
6
 
5
- def initialize(options={}, &block)
7
+ def initialize(options = {}, &block)
6
8
  self.api_key = options[:api_key]
7
- super(options={}, &block)
9
+ super(options, &block)
8
10
  end
9
11
 
10
12
  def default_options
@@ -12,7 +14,7 @@ module ActionNetworkRest
12
14
  host: 'actionnetwork.org',
13
15
  prefix: '/api/v2',
14
16
  content_type: 'application/json',
15
- additional_headers: {'OSDI-API-Token' => api_key},
17
+ additional_headers: { 'OSDI-API-Token' => api_key },
16
18
  user_agent: 'ruby: ActionNetworkRest'
17
19
  }
18
20
  end
@@ -23,6 +25,26 @@ module ActionNetworkRest
23
25
 
24
26
  ## Helpers to let users do things like `an_client.people.create(params)`
25
27
 
28
+ def events(event_id = nil)
29
+ if @_events&.send(:[], event_id).nil?
30
+ @_events = {} if @_events.nil?
31
+
32
+ @_events[event_id] = ActionNetworkRest::Events.new(event_id: event_id, client: self)
33
+ end
34
+
35
+ @_events[event_id]
36
+ end
37
+
38
+ def event_campaigns(event_campaign_id = nil)
39
+ if @_event_campaigns&.send(:[], event_campaign_id).nil?
40
+ @_event_campaigns = {} if @_event_campaigns.nil?
41
+
42
+ @_event_campaigns[event_campaign_id] = ActionNetworkRest::EventCampaigns.new(event_campaign_id, client: self)
43
+ end
44
+
45
+ @_event_campaigns[event_campaign_id]
46
+ end
47
+
26
48
  def entry_point
27
49
  @_entry_point ||= ActionNetworkRest::EntryPoint.new(client: self)
28
50
  end
@@ -31,8 +53,24 @@ module ActionNetworkRest
31
53
  @_people ||= ActionNetworkRest::People.new(client: self)
32
54
  end
33
55
 
34
- def petitions(petition_id=nil)
35
- @_petitions ||= ActionNetworkRest::Petitions.new(petition_id, client: self)
56
+ def petitions(petition_id = nil)
57
+ if @_petitions&.send(:[], petition_id).nil?
58
+ @_petitions = {} if @_petitions.nil?
59
+
60
+ @_petitions[petition_id] = ActionNetworkRest::Petitions.new(petition_id, client: self)
61
+ end
62
+
63
+ @_petitions[petition_id]
64
+ end
65
+
66
+ def tags(tag_id = nil)
67
+ if @_tags&.send(:[], tag_id).nil?
68
+ @_tags = {} if @_tags.nil?
69
+
70
+ @_tags[tag_id] = ActionNetworkRest::Tags.new(tag_id, client: self)
71
+ end
72
+
73
+ @_tags[tag_id]
36
74
  end
37
75
  end
38
76
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionNetworkRest
2
4
  class EntryPoint < Vertebrae::Model
3
5
  def base_path
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionNetworkRest
4
+ class EventCampaigns < Base
5
+ attr_accessor :event_campaign_id
6
+
7
+ # Without a event_campaign_id, this class is used for EventCampaign creation/update endpoints.
8
+ # With a event_campaign_id, this class is used to initialise the Events class,
9
+ # like client.event_campaigns(123).events
10
+ def initialize(event_campaign_id = nil, client:)
11
+ super(client: client, event_campaign_id: event_campaign_id)
12
+ end
13
+
14
+ def base_path
15
+ 'event_campaigns/'
16
+ end
17
+
18
+ def create(event_campaign_data)
19
+ response = client.post_request(base_path, event_campaign_data)
20
+ object_from_response(response)
21
+ end
22
+
23
+ def events(event_id = nil)
24
+ @_events ||= ActionNetworkRest::Events.new(event_campaign_id: event_campaign_id, event_id: event_id,
25
+ client: client)
26
+ end
27
+
28
+ private
29
+
30
+ def osdi_key
31
+ 'action_network:event_campaigns'
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionNetworkRest
4
+ class Events < Base
5
+ attr_accessor :event_campaign_id, :event_id
6
+
7
+ def initialize(client:, event_campaign_id: nil, event_id: nil)
8
+ super(client: client, event_id: event_id, event_campaign_id: event_campaign_id)
9
+ end
10
+
11
+ def base_path
12
+ if event_campaign_id.present?
13
+ "event_campaigns/#{url_escape(event_campaign_id)}/events/"
14
+ else
15
+ 'events/'
16
+ end
17
+ end
18
+
19
+ def create(event_data)
20
+ response = client.post_request(base_path, event_data)
21
+ object_from_response(response)
22
+ end
23
+
24
+ def attendances
25
+ @_attendances ||= ActionNetworkRest::Attendances.new(client: client, event_id: event_id,
26
+ event_campaign_id: event_campaign_id)
27
+ end
28
+
29
+ private
30
+
31
+ def osdi_key
32
+ 'osdi:events'
33
+ end
34
+ end
35
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionNetworkRest
2
4
  class People < Base
3
5
  def base_path
@@ -5,19 +7,48 @@ module ActionNetworkRest
5
7
  end
6
8
 
7
9
  def create(person_data, tags: [])
8
- post_body = {'person' => person_data}
9
- if tags.any?
10
- post_body['add_tags'] = tags
11
- end
10
+ post_body = { 'person' => person_data }
11
+ post_body['add_tags'] = tags if tags.any?
12
12
 
13
13
  response = client.post_request base_path, post_body
14
14
  object_from_response(response)
15
15
  end
16
16
 
17
17
  def unsubscribe(id)
18
- request_body = {email_addresses: [{status: 'unsubscribed'}]}
18
+ request_body = { email_addresses: [{ status: 'unsubscribed' }] }
19
19
  response = client.put_request "#{base_path}#{url_escape(id)}", request_body
20
20
  object_from_response(response)
21
21
  end
22
+
23
+ def find_by_email(email)
24
+ # This works for parsing exactly 1 person's info out of the response.
25
+ # The response we get from Action Network is expected to have
26
+ #
27
+ # "_embedded": {
28
+ # "osdi:people": [{
29
+ # "identifiers": [
30
+ # "action_network:c947bcd0-929e-11e3-a2e9-12313d316c29"
31
+ # ....
32
+ # ]
33
+ # }]
34
+ # }
35
+ #
36
+ url_encoded_filter_string = url_escape("email_address eq '#{email}'")
37
+ response = client.get_request "#{base_path}?filter=#{url_encoded_filter_string}"
38
+ person_object = response.body[:_embedded][osdi_key].first
39
+ set_action_network_id_on_object(person_object) if person_object.present?
40
+ end
41
+
42
+ def update(id, person_data)
43
+ people_path = "#{base_path}#{url_escape(id)}"
44
+ response = client.put_request people_path, person_data
45
+ object_from_response(response)
46
+ end
47
+
48
+ private
49
+
50
+ def osdi_key
51
+ 'osdi:people'
52
+ end
22
53
  end
23
54
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionNetworkRest
2
4
  class Petitions < Base
3
5
  attr_accessor :petition_id
@@ -5,7 +7,7 @@ module ActionNetworkRest
5
7
  # Without a petition_id, this class is used for Petition creation/update endpoints.
6
8
  # With a petition_id, this class is used to initialise the Signatures class,
7
9
  # like client.petitions(123).signatures
8
- def initialize(petition_id=nil, client:)
10
+ def initialize(petition_id = nil, client:)
9
11
  super(client: client, petition_id: petition_id)
10
12
  end
11
13
 
@@ -21,7 +23,7 @@ module ActionNetworkRest
21
23
  post_body = petition_data
22
24
  if creator_person_id.present?
23
25
  creator_person_url = action_network_url("/people/#{url_escape(creator_person_id)}")
24
- post_body['_links'] = {'osdi:creator' => {href: creator_person_url}}
26
+ post_body['_links'] = { 'osdi:creator' => { href: creator_person_url } }
25
27
  end
26
28
 
27
29
  response = client.post_request base_path, post_body
@@ -33,5 +35,11 @@ module ActionNetworkRest
33
35
  response = client.put_request petition_path, petition_data
34
36
  object_from_response(response)
35
37
  end
38
+
39
+ private
40
+
41
+ def osdi_key
42
+ 'osdi:petitions'
43
+ end
36
44
  end
37
45
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionNetworkRest
2
4
  class Signatures < Base
3
5
  attr_accessor :petition_id
@@ -6,24 +8,23 @@ module ActionNetworkRest
6
8
  "petitions/#{url_escape(petition_id)}/signatures/"
7
9
  end
8
10
 
9
- def get(id)
10
- response = client.get_request "#{base_path}#{url_escape(id)}"
11
- object_from_response(response)
12
- end
13
-
14
11
  def create(signature_data, tags: [])
15
12
  post_body = signature_data
16
- if tags.any?
17
- post_body['add_tags'] = tags
18
- end
13
+ post_body['add_tags'] = tags if tags.any?
19
14
 
20
- response = client.post_request base_path, post_body
15
+ response = client.post_request(base_path, post_body)
21
16
  object_from_response(response)
22
17
  end
23
18
 
24
19
  def update(id, signature_data)
25
- response = client.put_request "#{base_path}#{url_escape(id)}", signature_data
20
+ response = client.put_request("#{base_path}#{url_escape(id)}", signature_data)
26
21
  object_from_response(response)
27
22
  end
23
+
24
+ private
25
+
26
+ def osdi_key
27
+ 'osdi:signatures'
28
+ end
28
29
  end
29
30
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionNetworkRest
4
+ class Taggings < Base
5
+ attr_accessor :tag_id
6
+
7
+ def base_path
8
+ "tags/#{url_escape(tag_id)}/taggings/"
9
+ end
10
+
11
+ def create(tagging_data, person_id:)
12
+ post_body = tagging_data
13
+ person_url = action_network_url("/people/#{url_escape(person_id)}")
14
+ post_body['_links'] = { 'osdi:person' => { href: person_url } }
15
+
16
+ response = client.post_request base_path, post_body
17
+ object_from_response(response)
18
+ end
19
+
20
+ def delete(id)
21
+ response = client.delete_request "#{base_path}#{url_escape(id)}"
22
+ object_from_response(response)
23
+ end
24
+
25
+ private
26
+
27
+ def osdi_key
28
+ 'osdi:taggings'
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionNetworkRest
4
+ class Tags < Base
5
+ attr_accessor :tag_id
6
+
7
+ # Without a tag_id, this class is used for the Tag creation endpoint.
8
+ # With a tag_id, this class is used to initialise the Taggings class,
9
+ # like client.tags(123).taggings
10
+ def initialize(tag_id = nil, client:)
11
+ super(client: client, tag_id: tag_id)
12
+ end
13
+
14
+ def taggings
15
+ @_taggings ||= ActionNetworkRest::Taggings.new(client: client, tag_id: tag_id)
16
+ end
17
+
18
+ def base_path
19
+ 'tags/'
20
+ end
21
+
22
+ def create(name)
23
+ post_body = { name: name }
24
+ response = client.post_request base_path, post_body
25
+ object_from_response(response)
26
+ end
27
+
28
+ def find_by_name(name)
29
+ # Action Network API doesn't support currently OData querying for tags
30
+ # (https://actionnetwork.org/docs/v2#odata) so we need to retrieve a list of
31
+ # all tags and iterate to find the one we're looking for.
32
+ page = 1
33
+ loop do
34
+ tags = list(page: page)
35
+ return nil if tags.empty?
36
+
37
+ found_tag = tags.find { |t| t.name == name }
38
+ return found_tag unless found_tag.nil?
39
+
40
+ page += 1
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def osdi_key
47
+ 'osdi:tags'
48
+ end
49
+ end
50
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionNetworkRest
2
- VERSION = "0.2.0"
4
+ VERSION = '0.7.0'
3
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: action_network_rest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Grey Moore
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-29 00:00:00.000000000 Z
11
+ date: 2021-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: vertebrae
@@ -38,6 +38,34 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '2.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: byebug
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '11.1'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '11.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: dotenv
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.7'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.7'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: rake
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +94,34 @@ dependencies:
66
94
  - - "~>"
67
95
  - !ruby/object:Gem::Version
68
96
  version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-performance
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
69
125
  - !ruby/object:Gem::Dependency
70
126
  name: webmock
71
127
  requirement: !ruby/object:Gem::Requirement
@@ -87,22 +143,34 @@ executables: []
87
143
  extensions: []
88
144
  extra_rdoc_files: []
89
145
  files:
146
+ - ".env.sample"
90
147
  - ".gitignore"
148
+ - ".rubocop.yml"
91
149
  - ".ruby-gemset"
92
150
  - ".ruby-version"
151
+ - ".travis.yml"
93
152
  - CODE_OF_CONDUCT.md
94
153
  - Gemfile
95
154
  - LICENSE
96
155
  - README.md
97
156
  - Rakefile
98
157
  - action_network_rest.gemspec
158
+ - bin/console
159
+ - bin/rake
160
+ - bin/rspec
161
+ - example.rb
99
162
  - lib/action_network_rest.rb
163
+ - lib/action_network_rest/attendances.rb
100
164
  - lib/action_network_rest/base.rb
101
165
  - lib/action_network_rest/client.rb
102
166
  - lib/action_network_rest/entry_point.rb
167
+ - lib/action_network_rest/event_campaigns.rb
168
+ - lib/action_network_rest/events.rb
103
169
  - lib/action_network_rest/people.rb
104
170
  - lib/action_network_rest/petitions.rb
105
171
  - lib/action_network_rest/signatures.rb
172
+ - lib/action_network_rest/taggings.rb
173
+ - lib/action_network_rest/tags.rb
106
174
  - lib/action_network_rest/version.rb
107
175
  homepage: https://github.com/controlshift/action-network-rest
108
176
  licenses:
@@ -116,14 +184,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
116
184
  requirements:
117
185
  - - ">="
118
186
  - !ruby/object:Gem::Version
119
- version: '0'
187
+ version: '2.6'
120
188
  required_rubygems_version: !ruby/object:Gem::Requirement
121
189
  requirements:
122
190
  - - ">="
123
191
  - !ruby/object:Gem::Version
124
192
  version: '0'
125
193
  requirements: []
126
- rubygems_version: 3.1.2
194
+ rubygems_version: 3.1.6
127
195
  signing_key:
128
196
  specification_version: 4
129
197
  summary: Ruby client for interacting with the ActionNetwork REST API