client and api

Dylan Montgomery committed Jun 03, 2015
commit dd437eacd3487f0296758e2e2d2b373db8769a4d
Showing 6 changed files with 200 additions and 1 deletions
Gemfile +2 -0
@@ @@ -5,5 +5,7 @@ gemspec
group :test do
gem 'rspec'
+ gem 'webmock'
gem 'vcr'
+ gem 'dotenv'
end
bidsketch.rb b/lib/bidsketch.rb +3 -1
@@ @@ -1,9 +1,11 @@
require "bidsketch/version"
+ require "bidsketch/api"
+ require "bidsketch/client"
module Bidsketch
class << self
def api_key
- @api_key
+ @api_key || ENV['BIDSKETCH_API_KEY']
end
def api_key=(key)
bidsketch/api.rb b/lib/bidsketch/api.rb +40 -0
@@ @@ -0,0 +1,40 @@
+ require 'rest_client'
+ require 'json'
+
+ module Bidsketch
+ class API
+ BASE_URL = 'https://bidsketch.com/api/v1'
+
+ class << self
+ def get(path, options = {})
+ url = api_url(path)
+ if options[:params]
+ url += "&#{querify(options[:params])}"
+ end
+
+ headers = { authorization: "Token token=#{ENV['BIDSKETCH_API_KEY']}" }
+ normalize_response RestClient.get(url, headers)
+ end
+
+
+ private
+
+ def normalize_response(response)
+ JSON.parse(response)
+ end
+
+ def api_url(path)
+ "#{BASE_URL}#{tokenize(path)}"
+ end
+
+ def querify(hash)
+ hash.map { |k, v| "#{k}=#{v}".to_s }.join('&')
+ end
+
+ def tokenize(path)
+ param_separator = path.include?('?') ? '&' : '?'
+ path += "#{param_separator}token=#{Bidsketch.api_key}"
+ end
+ end
+ end
+ end
bidsketch/client.rb b/lib/bidsketch/client.rb +16 -0
@@ @@ -0,0 +1,16 @@
+ module Bidsketch
+ class Client
+ class << self
+ def all
+ Bidsketch::API.get('/clients.json').map { |client| OpenStruct.new(client) }
+ end
+
+ def find(id)
+ response = Bidsketch::API.get("/clients/#{id}.json")
+ if response
+ OpenStruct.new(response)
+ end
+ end
+ end
+ end
+ end
\ No newline at end of file
spec/client_spec.rb +33 -0
@@ @@ -0,0 +1,33 @@
+ describe Bidsketch::Client do
+ describe '#all' do
+ it 'returns all clients', vcr: true do
+ clients = Bidsketch::Client.all
+ client = clients.first
+ attributes = [
+ :id, :first_name, :last_name, :email, :name, :phone,
+ :url, :app_url, :created_at, :updated_at
+ ]
+
+ attributes.each do |attribute|
+ expect(client.respond_to?(attribute)).to be true
+ end
+ end
+ end
+
+ describe '#find' do
+ let(:client_id) { 356834 }
+ it 'returns a client', vcr: true do
+ client = Bidsketch::Client.find(client_id)
+ attributes = [
+ :id, :first_name, :last_name, :email, :name, :phone, :alt_phone,
+ :website, :address_field_one, :address_field_two, :city, :state,
+ :postal_zip, :country, :notes, :other_contact, :url, :app_url,
+ :created_at, :updated_at
+ ]
+
+ attributes.each do |attribute|
+ expect(client.respond_to?(attribute)).to be true
+ end
+ end
+ end
+ end
spec/spec_helper.rb +106 -0
@@ @@ -0,0 +1,106 @@
+ require 'bidsketch'
+ require 'vcr'
+ require 'dotenv'
+
+ Dotenv.load
+
+ # This file was generated by the `rspec --init` command. Conventionally, all
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
+ # this file to always be loaded, without a need to explicitly require it in any
+ # files.
+ #
+ # Given that it is always loaded, you are encouraged to keep this file as
+ # light-weight as possible. Requiring heavyweight dependencies from this file
+ # will add to the boot time of your test suite on EVERY test run, even for an
+ # individual file that may not need all of that loaded. Instead, consider making
+ # a separate helper file that requires the additional dependencies and performs
+ # the additional setup, and require it from the spec files that actually need
+ # it.
+ #
+ # The `.rspec` file also contains a few flags that are not defaults but that
+ # users commonly want.
+ #
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
+
+ VCR.configure do |c|
+ c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
+ c.hook_into :webmock
+ c.ignore_localhost = false
+ c.configure_rspec_metadata!
+ c.default_cassette_options = { record: :once }
+ end
+
+ RSpec.configure do |config|
+ # rspec-expectations config goes here. You can use an alternate
+ # assertion/expectation library such as wrong or the stdlib/minitest
+ # assertions if you prefer.
+ config.expect_with :rspec do |expectations|
+ # This option will default to `true` in RSpec 4. It makes the `description`
+ # and `failure_message` of custom matchers include text for helper methods
+ # defined using `chain`, e.g.:
+ # be_bigger_than(2).and_smaller_than(4).description
+ # # => "be bigger than 2 and smaller than 4"
+ # ...rather than:
+ # # => "be bigger than 2"
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
+ end
+
+ # rspec-mocks config goes here. You can use an alternate test double
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
+ config.mock_with :rspec do |mocks|
+ # Prevents you from mocking or stubbing a method that does not exist on
+ # a real object. This is generally recommended, and will default to
+ # `true` in RSpec 4.
+ mocks.verify_partial_doubles = true
+ end
+
+ # The settings below are suggested to provide a good initial experience
+ # with RSpec, but feel free to customize to your heart's content.
+ =begin
+ # These two settings work together to allow you to limit a spec run
+ # to individual examples or groups you care about by tagging them with
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
+ # get run.
+ config.filter_run :focus
+ config.run_all_when_everything_filtered = true
+
+ # Limits the available syntax to the non-monkey patched syntax that is
+ # recommended. For more details, see:
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
+ config.disable_monkey_patching!
+
+ # This setting enables warnings. It's recommended, but in some cases may
+ # be too noisy due to issues in dependencies.
+ config.warnings = true
+
+ # Many RSpec users commonly either run the entire suite or an individual
+ # file, and it's useful to allow more verbose output when running an
+ # individual spec file.
+ if config.files_to_run.one?
+ # Use the documentation formatter for detailed output,
+ # unless a formatter has already been configured
+ # (e.g. via a command-line flag).
+ config.default_formatter = 'doc'
+ end
+
+ # Print the 10 slowest examples and example groups at the
+ # end of the spec run, to help surface which specs are running
+ # particularly slow.
+ config.profile_examples = 10
+
+ # Run specs in random order to surface order dependencies. If you find an
+ # order dependency and want to debug it, you can fix the order by providing
+ # the seed, which is printed after each run.
+ # --seed 1234
+ config.order = :random
+
+ # Seed global randomization in this process using the `--seed` CLI option.
+ # Setting this allows you to use `--seed` to deterministically reproduce
+ # test failures related to randomization by passing the same `--seed` value
+ # as the one that triggered the failure.
+ Kernel.srand config.seed
+ =end
+ end