signable 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fc1e8af822245449ffd3e162892afdbf6669f316
4
+ data.tar.gz: f476428be5b19933f2ae20b85491ba4b61af9be7
5
+ SHA512:
6
+ metadata.gz: 1d986bc4150d38e57747fd1a57d17cb6d28344c1d34a2c251dc58c56e1bd7d855346909ef45743f563a2f484e6ba1ab7883c66ee717914bf8dbb734007289e8a
7
+ data.tar.gz: 6e2b2dc96dc6fa180e313927a405bae29e101133a3fbb88365acedf688638007a3e3e82ab270160b22b5839b8a23a04a109688094c9caad0e2747138238526d2
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ ruby '2.1.2'
4
+
5
+ # Specify your gem's dependencies in signable.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Anthony Laibe
2
+
3
+ MIT License
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
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # Signable
2
+
3
+ The signable client provides a simple Ruby interface to the Signable API.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'signable'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install signable
18
+
19
+ ## Usage
20
+
21
+ ### Configuration
22
+
23
+ ```ruby
24
+ Signable.configure do |config|
25
+ config.base_url = ENV.fetch('SIGNABLE_BASE_URL')
26
+ config.api_key = ENV.fetch('SIGNABLE_API_KEY')
27
+ end
28
+ ```
29
+
30
+ ### Retrieve a template
31
+
32
+ ```ruby
33
+ Signable::Template.find 'fingerprint'
34
+ ```
35
+
36
+ ### Build a document
37
+
38
+ ```ruby
39
+ Signable::Document.new(template_fingerprint: fingerprint, title: title)
40
+ ```
41
+
42
+ A document may also contain merge_fields (see signable documentation)
43
+
44
+ ### Build a party
45
+
46
+ ```ruby
47
+ Signable::Party.new(id: id, name: 'name', email: 'email')
48
+ ```
49
+
50
+ Party id can be retrieved from the template
51
+
52
+ ### Create an envelope
53
+
54
+ ```ruby
55
+ envelope = Signable::Envelope.new title: 'title', redirect_url: 'https://www.autoenrolment.co.uk'
56
+ envelope.documents = documents
57
+ envelope.parties = parties
58
+
59
+ envelope.save
60
+ ```
61
+
62
+ ## Contributing
63
+
64
+ 1. Fork it ( http://github.com/<my-github-username>/signable/fork )
65
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
66
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
67
+ 4. Push to the branch (`git push origin my-new-feature`)
68
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/lib/signable.rb ADDED
@@ -0,0 +1,42 @@
1
+ module Signable
2
+ class << self
3
+ attr_accessor :configuration
4
+
5
+ def configuration
6
+ @configuration ||= Configuration.new
7
+ end
8
+
9
+ def configure
10
+ yield(configuration)
11
+ end
12
+ end
13
+ end
14
+
15
+ require "active_support/all"
16
+ require "httparty"
17
+
18
+ require "signable/version"
19
+
20
+ require "signable/configuration"
21
+
22
+ require "signable/concerns/prefix"
23
+ require "signable/model/column"
24
+ require "signable/model/embed"
25
+
26
+ require "signable/list"
27
+
28
+ require "signable/concerns/query"
29
+ require "signable/concerns/embed"
30
+ require "signable/concerns/column"
31
+ require "signable/concerns/model"
32
+ require "signable/base"
33
+
34
+ require "signable/query/response"
35
+ require "signable/query/client"
36
+
37
+ require "signable/contact"
38
+ require "signable/envelope"
39
+ require "signable/template"
40
+ require "signable/party"
41
+ require "signable/merge_field"
42
+ require "signable/document"
@@ -0,0 +1,7 @@
1
+ module Signable
2
+ class Base
3
+ include Signable::Concerns::Query
4
+ include Signable::Concerns::Model
5
+
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ module Signable
2
+ module Concerns
3
+ module Column
4
+ extend ActiveSupport::Concern
5
+
6
+ def required_column
7
+ self.class.columns.select(&:required?)
8
+ end
9
+
10
+ def find_column(name)
11
+ self.class.columns.find { |column| column.match?(name) }
12
+ end
13
+
14
+ module ClassMethods
15
+ def column(name, options = {})
16
+ columns << Signable::Model::Column.new(name, options.merge(prefix: prefix))
17
+ end
18
+
19
+ def columns
20
+ @columns ||= []
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ module Signable
2
+ module Concerns
3
+ module Embed
4
+ extend ActiveSupport::Concern
5
+
6
+ def find_embed(name)
7
+ self.class.embeds.find { |embed| embed.match?(name) }
8
+ end
9
+
10
+ module ClassMethods
11
+ def embed(name, options = {})
12
+ embeds << Signable::Model::Embed.new(name, options.merge({ prefix: prefix }))
13
+ end
14
+
15
+ def embeds
16
+ @embeds ||= []
17
+ end
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,68 @@
1
+ module Signable
2
+ module Concerns
3
+ module Model
4
+ extend ActiveSupport::Concern
5
+ include Signable::Concerns::Embed
6
+ include Signable::Concerns::Column
7
+
8
+ def initialize(attributes = {})
9
+ @attributes = HashWithIndifferentAccess.new
10
+ self.attributes = attributes
11
+ end
12
+
13
+ def attributes=(attributes = {})
14
+ attributes.each do |key, value|
15
+ if column = find_column(key)
16
+ @attributes[column.name] = value
17
+ elsif embed = find_embed(key)
18
+ values = value.map { |hash| embed.embed_class.new(hash) }
19
+ @attributes[embed.name] = values
20
+ end
21
+ end
22
+ end
23
+
24
+ def form_data
25
+ hash = HashWithIndifferentAccess.new
26
+
27
+ @attributes.each do |key, value|
28
+ next if key == :id
29
+
30
+ if (column = self.find_column(key))
31
+ hash[column.name_with_prefix] = value
32
+ elsif (embed = self.find_embed(key))
33
+ hash[embed.name_with_prefix] = value.map(&:form_data)
34
+ end
35
+ end
36
+
37
+ hash
38
+ end
39
+
40
+ def method_missing(method, *args, &block)
41
+ get_method = method.to_s.gsub('=', '')
42
+ object = find_column(get_method) || find_embed(get_method)
43
+ if object
44
+ if get_method.to_sym == method
45
+ @attributes[object.name]
46
+ else
47
+ @attributes[object.name] = args.first
48
+ end
49
+ else
50
+ super
51
+ end
52
+ end
53
+
54
+ def valid?
55
+ required_column.all? do |column|
56
+ @attributes[column.name].present?
57
+ end
58
+ end
59
+
60
+ module ClassMethods
61
+ def prefix
62
+ name.demodulize.underscore
63
+ end
64
+ end
65
+
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,24 @@
1
+ module Signable
2
+ module Concerns
3
+ module Prefix
4
+ extend ActiveSupport::Concern
5
+
6
+ def match?(name)
7
+ [name_without_prefix, name_with_prefix].include? name.to_s
8
+ end
9
+
10
+ def name_with_prefix
11
+ "#{prefix}_#{name}"
12
+ end
13
+
14
+ def name_without_prefix
15
+ name.to_s.gsub("#{prefix}_", "")
16
+ end
17
+
18
+ def prefix
19
+ options[:prefix]
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,68 @@
1
+ module Signable
2
+ module Concerns
3
+ module Query
4
+ extend ActiveSupport::Concern
5
+
6
+ def save
7
+ return false unless valid?
8
+ persisted? ? update : create
9
+ end
10
+
11
+ def delete
12
+ self.class.client.delete self.class.entry_point, id
13
+ end
14
+
15
+ def persisted?
16
+ id.present? rescue false
17
+ end
18
+
19
+ private
20
+
21
+ def update
22
+ response = self.class.client.update self.class.entry_point, id, self
23
+ response.ok?
24
+ end
25
+
26
+ def create
27
+ response = self.class.client.create self.class.entry_point, self
28
+ if response.ok?
29
+ self.attributes = response.object
30
+ true
31
+ else
32
+ false
33
+ end
34
+ end
35
+
36
+ module ClassMethods
37
+ def all(offset = 0, limit = 10)
38
+ response = client.all(entry_point, offset, limit)
39
+
40
+ if response.ok?
41
+ List.new(self, response.object)
42
+ else
43
+ []
44
+ end
45
+ end
46
+
47
+ def find(id)
48
+ response = client.find(entry_point, id)
49
+
50
+ if response.ok?
51
+ self.new response.object
52
+ else
53
+ nil
54
+ end
55
+ end
56
+
57
+ def entry_point
58
+ prefix.pluralize
59
+ end
60
+
61
+ def client
62
+ @client ||= Signable::Query::Client.new
63
+ end
64
+ end
65
+
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,5 @@
1
+ module Signable
2
+ class Configuration
3
+ attr_accessor :base_url, :api_key
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ module Signable
2
+ class Contact < Signable::Base
3
+
4
+ column :id
5
+ column :name, presence: true
6
+ column :email, presence: true
7
+ end
8
+ end
@@ -0,0 +1,16 @@
1
+ module Signable
2
+ class Document
3
+ include Signable::Concerns::Model
4
+
5
+ column :template_fingerprint, presence: true
6
+ column :title, presence: true
7
+ column :pdf_url
8
+ column :pages
9
+ embed :merge_fields
10
+
11
+ def page
12
+ pages.first
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ module Signable
2
+ class Envelope < Signable::Base
3
+
4
+ column :title, presence: true
5
+ column :fingerprint
6
+ column :status
7
+ column :signed_pdf
8
+ column :signing_embed
9
+ column :redirect_url
10
+ embed :documents
11
+ embed :parties
12
+
13
+ def update
14
+ raise "not available"
15
+ end
16
+
17
+ def delete
18
+ raise "not available"
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,27 @@
1
+ module Signable
2
+ class List < Struct.new(:data_type, :hash)
3
+
4
+ def offset
5
+ hash['offset']
6
+ end
7
+
8
+ def limit
9
+ hash['limit']
10
+ end
11
+
12
+ def total
13
+ hash["total_#{data_name}"]
14
+ end
15
+
16
+ def data
17
+ @data ||= hash[data_name].map { |attributes| data_type.new attributes }
18
+ end
19
+
20
+ private
21
+
22
+ def data_name
23
+ data_type.name.demodulize.underscore.pluralize
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,16 @@
1
+ module Signable
2
+ class MergeField
3
+ include Signable::Concerns::Model
4
+
5
+ # Must be before the columns call because the column class method use
6
+ # the prefix method
7
+ def self.prefix
8
+ 'field'
9
+ end
10
+
11
+ column :id
12
+ column :merge
13
+ column :value
14
+
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ module Signable
2
+ module Model
3
+ class Column < Struct.new(:name, :options)
4
+ include Signable::Concerns::Prefix
5
+
6
+ def required?
7
+ options[:presence] == true
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Signable
2
+ module Model
3
+ class Embed < Struct.new(:name, :options)
4
+ include Signable::Concerns::Prefix
5
+
6
+ def embed_class
7
+ "Signable::#{name.to_s.classify}".constantize
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ module Signable
2
+ class Party
3
+ include Signable::Concerns::Model
4
+
5
+ column :id, presence: true
6
+ column :name, presence: true
7
+ column :email, presence: true
8
+
9
+ embed :merge_fields
10
+ end
11
+ end
@@ -0,0 +1,51 @@
1
+ module Signable
2
+ module Query
3
+ class Client
4
+ include HTTParty
5
+
6
+ def initialize
7
+ self.class.base_uri "https://#{Signable.configuration.base_url}/v1"
8
+ self.class.basic_auth Signable.configuration.api_key, ''
9
+ self.class.default_options[:verify] = false
10
+ end
11
+
12
+ def all(entry_point, offset, limit)
13
+ response = self.class.get "/#{entry_point}", query: { offset: offset, limit: limit }
14
+ Response.new response
15
+ end
16
+
17
+ def find(entry_point, id)
18
+ response = self.class.get "/#{entry_point}/#{id}"
19
+ Response.new response
20
+ end
21
+
22
+ def update(entry_point, id, object)
23
+ response = self.class.put "/#{entry_point}/#{id}", body: jsonify(object.form_data)
24
+ Response.new response
25
+ end
26
+
27
+ def create(entry_point, object)
28
+ response = self.class.post "/#{entry_point}", body: jsonify(object.form_data)
29
+ Response.new response
30
+ end
31
+
32
+ def delete(entry_poind, id)
33
+ response = self.class.delete "/#{entry_point}/#{id}"
34
+ Response.new response
35
+ end
36
+
37
+ private
38
+
39
+ def jsonify(hash)
40
+ hash.each do |key, value|
41
+ if value.is_a? Array
42
+ hash[key] = value.to_json
43
+ end
44
+ end
45
+
46
+ hash
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,15 @@
1
+ module Signable
2
+ module Query
3
+ class Response < Struct.new(:http_response)
4
+
5
+ def ok?
6
+ [200, 202].include?(http_response.code.to_i)
7
+ end
8
+
9
+ def object
10
+ @object ||= JSON.parse(http_response.body)
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ module Signable
2
+ class Template < Signable::Base
3
+
4
+ column :id
5
+ column :fingerprint
6
+ column :title
7
+ embed :parties
8
+
9
+ def save
10
+ raise "not available"
11
+ end
12
+
13
+ def update
14
+ raise "not available"
15
+ end
16
+
17
+ def delete
18
+ raise "not available"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ module Signable
2
+ VERSION = "0.0.1"
3
+ end
data/signable.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'signable/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "signable"
8
+ spec.version = Signable::VERSION
9
+ spec.authors = ["Anthony Laibe"]
10
+ spec.email = ["anthony@laibe.cc"]
11
+ spec.summary = %q{The signable client provides a simple Ruby interface to the Signable API.}
12
+ spec.description = %q{The signable client provides a simple Ruby interface to the Signable API.}
13
+ spec.homepage = "https://github.com/smartpension/signable"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake", "~> 10.4"
23
+ spec.add_development_dependency "rspec", "~> 3.2"
24
+
25
+ spec.add_dependency "activesupport", "~> 4.2"
26
+ spec.add_dependency "httparty", "~> 0.13"
27
+
28
+ end
@@ -0,0 +1,8 @@
1
+ require "spec_helper"
2
+
3
+ describe Signable::Base do
4
+
5
+ it_behaves_like 'Query'
6
+ it_behaves_like 'Model'
7
+
8
+ end
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+
3
+ DataType = Struct.new(:hash)
4
+
5
+ describe Signable::List do
6
+
7
+ let(:hash) {{ 'offset' => 5, 'limit' => 12, 'total_data_types' => 2, 'data_types' => [{},{}] }}
8
+ let(:list) { Signable::List.new(DataType, hash) }
9
+
10
+ describe "#offset" do
11
+ subject { list.offset }
12
+
13
+ it { should be 5 }
14
+ end
15
+
16
+ describe "#limit" do
17
+ subject { list.limit }
18
+
19
+ it { should be 12 }
20
+ end
21
+
22
+ describe "#total" do
23
+ subject { list.total }
24
+
25
+ it { should be 2 }
26
+ end
27
+
28
+ describe "#data" do
29
+ context "length" do
30
+ subject { list.data.length }
31
+ it { should be 2 }
32
+ end
33
+
34
+ context "class name" do
35
+ subject { list.data.first.class.name }
36
+ it { should be_eql 'DataType' }
37
+ end
38
+ end
39
+
40
+ end
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+
3
+ describe Signable::Model::Column do
4
+
5
+ it_behaves_like 'Prefix'
6
+
7
+ describe "#required?" do
8
+ subject { column.required? }
9
+ context "when presence is true" do
10
+ let(:column) { Signable::Model::Column.new('name', presence: true) }
11
+ it { should be true }
12
+ end
13
+
14
+ context "when presence is false" do
15
+ let(:column) { Signable::Model::Column.new('name', presence: false) }
16
+ it { should be false }
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,15 @@
1
+ require "spec_helper"
2
+
3
+ describe Signable::Model::Embed do
4
+
5
+ it_behaves_like 'Prefix'
6
+
7
+ describe "#embed_class" do
8
+ let(:column) { Signable::Model::Embed.new('contacts') }
9
+
10
+ subject { column.embed_class }
11
+
12
+ it { should be Signable::Contact }
13
+ end
14
+
15
+ end
@@ -0,0 +1,34 @@
1
+ require "spec_helper"
2
+
3
+ describe Signable::Query::Response do
4
+
5
+ describe "#ok?" do
6
+ let(:response) { Signable::Query::Response.new http_response }
7
+ subject { response.ok? }
8
+
9
+ context "when code is 200" do
10
+ let(:http_response) { double 'http_response', code: 200 }
11
+ it { should be true }
12
+ end
13
+
14
+ context "when code is 202" do
15
+ let(:http_response) { double 'http_response', code: 202 }
16
+ it { should be true }
17
+ end
18
+
19
+ context "when code is !200" do
20
+ let(:http_response) { double 'http_response', code: 205 }
21
+ it { should be false }
22
+ end
23
+ end
24
+
25
+ describe "#object" do
26
+ let(:http_response) { double 'http_response', body: { bar: 'foo' }.to_json }
27
+
28
+ it "parse body response" do
29
+ response = Signable::Query::Response.new http_response
30
+ expect(response.object).to be_eql({ 'bar' => 'foo' })
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,8 @@
1
+ require 'rspec'
2
+ require "signable"
3
+
4
+ Dir.glob("#{File.dirname(__FILE__)}/support/**/*.rb").each { |f| require f }
5
+
6
+ RSpec.configure do |c|
7
+ c.mock_with :rspec
8
+ end
@@ -0,0 +1,40 @@
1
+ shared_examples 'Column' do
2
+
3
+ before do
4
+ described_class.instance_variable_set(:@columns, [])
5
+ end
6
+
7
+ describe "#required_column" do
8
+ it "return required column only" do
9
+ described_class.column :required, presence: true
10
+ described_class.column :non_required
11
+
12
+ object = described_class.new
13
+ expect(object.required_column.length).to be 1
14
+ expect(object.required_column.first.name).to be :required
15
+ end
16
+ end
17
+
18
+ describe "#find_column" do
19
+ it "return first column which match the name" do
20
+ described_class.column :match
21
+ described_class.column :non_match
22
+
23
+ object = described_class.new
24
+ expect(object.find_column('match').name).to be :match
25
+ end
26
+ end
27
+
28
+ describe ".column" do
29
+ it "add a new column to the list of columns" do
30
+ described_class.column :foo
31
+ expect(described_class.columns.last.name).to be :foo
32
+ end
33
+
34
+ it "automatically add the prefix" do
35
+ described_class.column :foo
36
+
37
+ expect(described_class.columns.last.prefix).to be_eql described_class.name.demodulize.underscore
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,24 @@
1
+ shared_examples 'Embed' do
2
+ describe "#find_embed" do
3
+ it "return first embed which match the name" do
4
+ described_class.embed :match
5
+ described_class.embed :non_match
6
+
7
+ object = described_class.new
8
+ expect(object.find_embed('match').name).to be :match
9
+ end
10
+ end
11
+
12
+ describe ".embed" do
13
+ it "add a new embed to the list of embeds" do
14
+ described_class.embed :foo
15
+ expect(described_class.embeds.last.name).to be :foo
16
+ end
17
+
18
+ it "automatically add the prefix" do
19
+ described_class.embed :foo
20
+
21
+ expect(described_class.embeds.last.prefix).to be_eql described_class.name.demodulize.underscore
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,80 @@
1
+ Signable::Embedded = Struct.new(:arg) do
2
+
3
+ def form_data
4
+ "embedded"
5
+ end
6
+
7
+ end
8
+
9
+ shared_examples 'Model' do
10
+
11
+ it_behaves_like 'Column'
12
+ it_behaves_like 'Embed'
13
+
14
+ before do
15
+ described_class.instance_variable_set(:@columns, [])
16
+ end
17
+
18
+ describe "#attributes" do
19
+ it "set attributes specified by column" do
20
+ described_class.column :foo
21
+ object = described_class.new foo: 'bar'
22
+ expect(object.foo).to be_eql 'bar'
23
+ end
24
+
25
+ it "set object specified by embed" do
26
+ described_class.embed :embeddeds
27
+ object = described_class.new embeddeds: ['bar']
28
+ expect(object.embeddeds.first.arg).to be_eql 'bar'
29
+ end
30
+ end
31
+
32
+ describe '#form_data' do
33
+ subject { described.form_data }
34
+
35
+ context 'when attribute is a column' do
36
+ let(:described) { described_class.new foo: 'bar' }
37
+
38
+ before do
39
+ described_class.column :foo
40
+ end
41
+
42
+ it { should be_eql({ "base_foo" => "bar" }) }
43
+ end
44
+
45
+ context 'when attribute is an embed' do
46
+ let(:described) { described_class.new embeddeds: ['bar'] }
47
+
48
+ before do
49
+ described_class.embed :embeddeds
50
+ end
51
+
52
+ it { should be_eql({ "base_embeddeds" => ["embedded"] }) }
53
+ end
54
+ end
55
+
56
+ describe "#valid?" do
57
+ subject { described.valid? }
58
+
59
+ before do
60
+ described_class.column :required, presence: true
61
+ end
62
+
63
+ context "when all required fields are present" do
64
+ let (:described) { described_class.new required: 'test' }
65
+
66
+ it { should be true }
67
+ end
68
+
69
+ context "when all required fields are not present" do
70
+ let (:described) { described_class.new }
71
+ it { should be false }
72
+ end
73
+ end
74
+
75
+ describe ".prefix" do
76
+ subject { described_class.prefix }
77
+
78
+ it { should be_eql described_class.name.demodulize.underscore }
79
+ end
80
+ end
@@ -0,0 +1,43 @@
1
+ shared_examples 'Prefix' do
2
+
3
+ let(:described) { described_class.new 'test', { prefix: 'prefix' } }
4
+
5
+ describe "#match?" do
6
+ subject { described.match?(name) }
7
+ context "when name match name with prefix" do
8
+ let(:name) { 'prefix_test'}
9
+ it { should be true }
10
+ end
11
+
12
+ context "when name match name without prefix" do
13
+ let(:name) { 'test'}
14
+ it { should be true }
15
+ end
16
+
17
+ context "when name do not match" do
18
+ let(:name) { 'something'}
19
+ it { should be false }
20
+ end
21
+ end
22
+
23
+ describe "#name_with_prefix" do
24
+ subject { described.name_with_prefix }
25
+
26
+ it { should be_eql 'prefix_test' }
27
+ end
28
+
29
+ describe "#prefix" do
30
+ subject { described.prefix }
31
+
32
+ it { should be_eql 'prefix' }
33
+ end
34
+
35
+ describe "#name_without_prefix" do
36
+ let(:described) { described_class.new 'prefix_test', { prefix: 'prefix' } }
37
+
38
+ subject { described.name_without_prefix }
39
+
40
+ it { should be_eql 'test' }
41
+ end
42
+
43
+ end
@@ -0,0 +1,70 @@
1
+ shared_examples 'Query' do
2
+
3
+ before do
4
+ described_class.instance_variable_set(:@columns, [])
5
+ described_class.column :id
6
+ end
7
+
8
+ let(:response) { double 'response', ok?: false }
9
+
10
+ describe "#save" do
11
+ context "when persisted" do
12
+ let(:described) { described_class.new id: 1 }
13
+
14
+ it "call client update" do
15
+ expect(described_class.client).to receive(:update).with(described_class.entry_point, 1, described).and_return response
16
+ described.save
17
+ end
18
+ end
19
+
20
+ context "#when not persisted" do
21
+ let(:described) { described_class.new }
22
+
23
+ it "call client create" do
24
+ expect(described_class.client).to receive(:create).with(described_class.entry_point, described).and_return response
25
+ described.save
26
+ end
27
+ end
28
+ end
29
+
30
+ describe "#delete" do
31
+ let(:described) { described_class.new id: 1 }
32
+
33
+ it "call client delete" do
34
+ expect(described_class.client).to receive(:delete).with(described_class.entry_point, described.id).and_return response
35
+ described.delete
36
+ end
37
+ end
38
+
39
+ describe "#persisted?" do
40
+ let(:described) { described_class.new }
41
+
42
+ subject { described.persisted?}
43
+
44
+ context "when id is nil" do
45
+ it { should be false }
46
+ end
47
+
48
+ context "when id is present" do
49
+ before do
50
+ described.id = 1
51
+ end
52
+ it { should be true }
53
+ end
54
+ end
55
+
56
+ describe ".all" do
57
+ it "call client all with default value for offet and limit" do
58
+ expect(described_class.client).to receive(:all).with(described_class.entry_point, 0, 10).and_return response
59
+ described_class.all
60
+ end
61
+ end
62
+
63
+ describe ".find" do
64
+ it "call client find" do
65
+ expect(described_class.client).to receive(:find).with(described_class.entry_point, 1).and_return response
66
+ described_class.find 1
67
+ end
68
+ end
69
+
70
+ end
metadata ADDED
@@ -0,0 +1,163 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: signable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Anthony Laibe
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.4'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.2'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activesupport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '4.2'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '4.2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: httparty
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.13'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.13'
83
+ description: The signable client provides a simple Ruby interface to the Signable
84
+ API.
85
+ email:
86
+ - anthony@laibe.cc
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - Gemfile
93
+ - LICENSE.txt
94
+ - README.md
95
+ - Rakefile
96
+ - lib/signable.rb
97
+ - lib/signable/base.rb
98
+ - lib/signable/concerns/column.rb
99
+ - lib/signable/concerns/embed.rb
100
+ - lib/signable/concerns/model.rb
101
+ - lib/signable/concerns/prefix.rb
102
+ - lib/signable/concerns/query.rb
103
+ - lib/signable/configuration.rb
104
+ - lib/signable/contact.rb
105
+ - lib/signable/document.rb
106
+ - lib/signable/envelope.rb
107
+ - lib/signable/list.rb
108
+ - lib/signable/merge_field.rb
109
+ - lib/signable/model/column.rb
110
+ - lib/signable/model/embed.rb
111
+ - lib/signable/party.rb
112
+ - lib/signable/query/client.rb
113
+ - lib/signable/query/response.rb
114
+ - lib/signable/template.rb
115
+ - lib/signable/version.rb
116
+ - signable.gemspec
117
+ - spec/signable/base_spec.rb
118
+ - spec/signable/list_spec.rb
119
+ - spec/signable/model/column_spec.rb
120
+ - spec/signable/model/embed_spec.rb
121
+ - spec/signable/query/response_spec.rb
122
+ - spec/spec_helper.rb
123
+ - spec/support/concerns/column.rb
124
+ - spec/support/concerns/embed.rb
125
+ - spec/support/concerns/model.rb
126
+ - spec/support/concerns/prefix.rb
127
+ - spec/support/concerns/query.rb
128
+ homepage: https://github.com/smartpension/signable
129
+ licenses:
130
+ - MIT
131
+ metadata: {}
132
+ post_install_message:
133
+ rdoc_options: []
134
+ require_paths:
135
+ - lib
136
+ required_ruby_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ requirements: []
147
+ rubyforge_project:
148
+ rubygems_version: 2.2.2
149
+ signing_key:
150
+ specification_version: 4
151
+ summary: The signable client provides a simple Ruby interface to the Signable API.
152
+ test_files:
153
+ - spec/signable/base_spec.rb
154
+ - spec/signable/list_spec.rb
155
+ - spec/signable/model/column_spec.rb
156
+ - spec/signable/model/embed_spec.rb
157
+ - spec/signable/query/response_spec.rb
158
+ - spec/spec_helper.rb
159
+ - spec/support/concerns/column.rb
160
+ - spec/support/concerns/embed.rb
161
+ - spec/support/concerns/model.rb
162
+ - spec/support/concerns/prefix.rb
163
+ - spec/support/concerns/query.rb