pipeline_dealers 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +64 -0
- data/Rakefile +1 -0
- data/examples/companies_create_and_destroy.rb +6 -0
- data/examples/companies_list_all.rb +9 -0
- data/examples/company_details.rb +19 -0
- data/examples/company_notes.rb +17 -0
- data/examples/company_people.rb +15 -0
- data/examples/config.rb +54 -0
- data/examples/find_person.rb +9 -0
- data/examples/list_custom_fields.rb +19 -0
- data/examples/people_create_and_destroy.rb +6 -0
- data/examples/people_list_all.rb +9 -0
- data/lib/pipeline_dealers/backend/base/backend.rb +13 -0
- data/lib/pipeline_dealers/backend/base/collection.rb +111 -0
- data/lib/pipeline_dealers/backend/base.rb +2 -0
- data/lib/pipeline_dealers/backend/http/backend.rb +64 -0
- data/lib/pipeline_dealers/backend/http/collection.rb +32 -0
- data/lib/pipeline_dealers/backend/http/connection.rb +69 -0
- data/lib/pipeline_dealers/backend/http/fetcher.rb +78 -0
- data/lib/pipeline_dealers/backend/http.rb +5 -0
- data/lib/pipeline_dealers/backend/test/backend.rb +34 -0
- data/lib/pipeline_dealers/backend/test/collection.rb +34 -0
- data/lib/pipeline_dealers/backend/test.rb +3 -0
- data/lib/pipeline_dealers/client.rb +23 -0
- data/lib/pipeline_dealers/delegator.rb +61 -0
- data/lib/pipeline_dealers/error/connection.rb +17 -0
- data/lib/pipeline_dealers/error/custom_field.rb +12 -0
- data/lib/pipeline_dealers/error/invalid_attribute.rb +29 -0
- data/lib/pipeline_dealers/error.rb +12 -0
- data/lib/pipeline_dealers/limits.rb +7 -0
- data/lib/pipeline_dealers/model/company/custom_field.rb +9 -0
- data/lib/pipeline_dealers/model/company.rb +46 -0
- data/lib/pipeline_dealers/model/custom_field.rb +94 -0
- data/lib/pipeline_dealers/model/has_custom_fields.rb +62 -0
- data/lib/pipeline_dealers/model/note.rb +37 -0
- data/lib/pipeline_dealers/model/person/custom_field.rb +9 -0
- data/lib/pipeline_dealers/model/person.rb +63 -0
- data/lib/pipeline_dealers/model.rb +158 -0
- data/lib/pipeline_dealers/test.rb +10 -0
- data/lib/pipeline_dealers/version.rb +3 -0
- data/lib/pipeline_dealers.rb +24 -0
- data/pipeline_dealers.gemspec +39 -0
- data/spec/acceptance/companies/creation_spec.rb +30 -0
- data/spec/acceptance/companies/custom_fields_spec.rb +8 -0
- data/spec/acceptance/companies/updating_spec.rb +36 -0
- data/spec/acceptance/people/creation_spec.rb +20 -0
- data/spec/pipeline_dealers/backend/http/backend_spec.rb +48 -0
- data/spec/pipeline_dealers/backend/http/collection_spec.rb +158 -0
- data/spec/pipeline_dealers/model/custom_field_spec.rb +129 -0
- data/spec/pipeline_dealers/model/has_custom_fields_spec.rb +115 -0
- data/spec/pipeline_dealers/model_spec.rb +33 -0
- data/spec/pipeline_dealers/test_client_spec.rb +80 -0
- data/spec/support/test_model.rb +6 -0
- data/todo.md +13 -0
- metadata +291 -0
@@ -0,0 +1,158 @@
|
|
1
|
+
require "json"
|
2
|
+
require "active_support/hash_with_indifferent_access"
|
3
|
+
|
4
|
+
module PipelineDealers
|
5
|
+
class Model
|
6
|
+
class << self
|
7
|
+
attr_accessor :collection_url
|
8
|
+
attr_accessor :attribute_name
|
9
|
+
attr_reader :attributes
|
10
|
+
|
11
|
+
def attrs *attrs
|
12
|
+
if attrs.last.kind_of?(Hash)
|
13
|
+
options = attrs.pop
|
14
|
+
else
|
15
|
+
options = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
attrs.each do |attr|
|
19
|
+
attr attr, options
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def attr name, options = {}
|
24
|
+
@attributes ||= {}
|
25
|
+
@attributes[name] = options
|
26
|
+
|
27
|
+
# Getter
|
28
|
+
define_method name do
|
29
|
+
@attributes[name.to_s]
|
30
|
+
end
|
31
|
+
|
32
|
+
# Setter, only if not read only
|
33
|
+
if options[:read_only] != true
|
34
|
+
define_method "#{name}=".to_sym do |value|
|
35
|
+
@attributes[name.to_s] = value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def inherited(klass)
|
41
|
+
(@attributes || []).each do |name, options|
|
42
|
+
klass.attr(name, options)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
attr_accessor :attributes
|
48
|
+
attr_reader :id
|
49
|
+
|
50
|
+
def initialize(options = {})
|
51
|
+
@options = options
|
52
|
+
@persisted = options.delete(:persisted) == true
|
53
|
+
@client = options.delete(:client)
|
54
|
+
@collection = options.delete(:collection)
|
55
|
+
|
56
|
+
import_attributes! options.delete(:attributes)
|
57
|
+
end
|
58
|
+
|
59
|
+
def ==(other)
|
60
|
+
if other.kind_of?(self.class)
|
61
|
+
other.id == self.id && other.attributes == self.attributes
|
62
|
+
else
|
63
|
+
super(other)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def persisted?
|
68
|
+
@persisted == true
|
69
|
+
end
|
70
|
+
|
71
|
+
def new_record?
|
72
|
+
@persisted == false
|
73
|
+
end
|
74
|
+
|
75
|
+
def save
|
76
|
+
@collection.save(self)
|
77
|
+
self
|
78
|
+
end
|
79
|
+
|
80
|
+
def destroy
|
81
|
+
@collection.destroy(self)
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
85
|
+
IGNORE_ATTRIBUTES_WHEN_SAVING = [:updated_at, :created_at]
|
86
|
+
def save_attrs
|
87
|
+
# Ignore some attributes
|
88
|
+
save_attrs = @attributes.reject { |k, v| IGNORE_ATTRIBUTES_WHEN_SAVING.member?(k) }
|
89
|
+
|
90
|
+
# And allow a model class to modify / edit attributes even further
|
91
|
+
if respond_to?(:attributes_for_saving)
|
92
|
+
save_attrs = attributes_for_saving(save_attrs)
|
93
|
+
else
|
94
|
+
save_attrs
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def to_s
|
99
|
+
"<#{self.class}:#{self.object_id} @attibutes=#{@attributes.inspect}>"
|
100
|
+
end
|
101
|
+
|
102
|
+
protected
|
103
|
+
|
104
|
+
def import_attributes! attributes
|
105
|
+
@attributes = stringify_keys(attributes || {})
|
106
|
+
@id = @attributes.delete(:id)
|
107
|
+
|
108
|
+
# Give subclasses the opportunity to hook in here.
|
109
|
+
process_attributes if respond_to?(:process_attributes)
|
110
|
+
|
111
|
+
check_for_non_existent_attributes!
|
112
|
+
end
|
113
|
+
|
114
|
+
def check_for_non_existent_attributes!
|
115
|
+
attribute_keys = @attributes.keys.collect(&:to_sym)
|
116
|
+
|
117
|
+
invalid_attributes = attribute_keys - valid_attribute_names
|
118
|
+
|
119
|
+
if invalid_attributes.any?
|
120
|
+
raise Error::InvalidAttributeName.new(self.class, invalid_attributes.first)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Recursively converts a hash structure with symbol keys to a hash
|
125
|
+
# with indifferent keys
|
126
|
+
def stringify_keys original
|
127
|
+
result = HashWithIndifferentAccess.new
|
128
|
+
|
129
|
+
original.each do |key, value|
|
130
|
+
result[key] = stringify_value(value)
|
131
|
+
end
|
132
|
+
|
133
|
+
result
|
134
|
+
end
|
135
|
+
|
136
|
+
def valid_attribute_names
|
137
|
+
attrs = self.class.instance_variable_get(:@attributes)
|
138
|
+
if attrs.nil?
|
139
|
+
[]
|
140
|
+
else
|
141
|
+
attrs.keys
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def stringify_value value
|
146
|
+
case value
|
147
|
+
when String, Fixnum, NilClass, FalseClass, TrueClass
|
148
|
+
return value
|
149
|
+
when Hash, HashWithIndifferentAccess
|
150
|
+
return stringify_keys(value)
|
151
|
+
when Array
|
152
|
+
return value.collect { |item| stringify_value(item) }
|
153
|
+
else
|
154
|
+
raise "Unkown type: #{value.class}"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "pipeline_dealers/version"
|
2
|
+
|
3
|
+
module PipelineDealers
|
4
|
+
require "pipeline_dealers/delegator"
|
5
|
+
|
6
|
+
require "pipeline_dealers/limits"
|
7
|
+
require "pipeline_dealers/error"
|
8
|
+
require "pipeline_dealers/client"
|
9
|
+
|
10
|
+
# Base model
|
11
|
+
require "pipeline_dealers/model"
|
12
|
+
require "pipeline_dealers/model/custom_field"
|
13
|
+
require "pipeline_dealers/model/has_custom_fields"
|
14
|
+
|
15
|
+
# Models
|
16
|
+
require "pipeline_dealers/model/company"
|
17
|
+
require "pipeline_dealers/model/company/custom_field"
|
18
|
+
require "pipeline_dealers/model/person"
|
19
|
+
require "pipeline_dealers/model/person/custom_field"
|
20
|
+
require "pipeline_dealers/model/note"
|
21
|
+
|
22
|
+
require "pipeline_dealers/backend/base"
|
23
|
+
require "pipeline_dealers/backend/http"
|
24
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'pipeline_dealers/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "pipeline_dealers"
|
8
|
+
gem.version = PipelineDealers::VERSION
|
9
|
+
gem.authors = ["Maarten Hoogendoorn"]
|
10
|
+
gem.email = ["maarten@springest.com"]
|
11
|
+
gem.description = %q{API client for PipelineDeals}
|
12
|
+
gem.summary = gem.description
|
13
|
+
gem.homepage = "https://github.com/Springest/pipeline_dealers"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_dependency "faraday", "~> 0.8.0"
|
21
|
+
gem.add_dependency "faraday_middleware", "~> 0.9.0"
|
22
|
+
gem.add_dependency "multi_json", "~> 1.0"
|
23
|
+
|
24
|
+
gem.add_development_dependency "rspec", ">2"
|
25
|
+
gem.add_development_dependency "guard-rspec"
|
26
|
+
gem.add_development_dependency "reek"
|
27
|
+
gem.add_development_dependency "activesupport", "> 3.0.0"
|
28
|
+
gem.add_development_dependency "simplecov"
|
29
|
+
gem.add_development_dependency "debugger"
|
30
|
+
gem.add_development_dependency "rake"
|
31
|
+
|
32
|
+
|
33
|
+
if RUBY_PLATFORM.include? "linux"
|
34
|
+
gem.add_development_dependency "rb-inotify", "~> 0.8.8"
|
35
|
+
elsif RUBY_PLATFORM.include? "darwin"
|
36
|
+
gem.add_development_dependency "growl"
|
37
|
+
gem.add_development_dependency "rb-fsevent"
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
__END__
|
2
|
+
describe "Company", :acceptance do
|
3
|
+
describe "creation" do
|
4
|
+
include AcceptanceHelper
|
5
|
+
|
6
|
+
context "using client.companies.new" do
|
7
|
+
let(:company) { client.companies.new(name: "Meh") }
|
8
|
+
|
9
|
+
context "with a valid model" do
|
10
|
+
before { company.name = "Meh" }
|
11
|
+
|
12
|
+
context "when saved" do
|
13
|
+
it "returns a model" do
|
14
|
+
company.save.should be_kind_of PLD::Model::Base
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "with an invalid model" do
|
20
|
+
before { company.name = nil }
|
21
|
+
|
22
|
+
context "when saved" do
|
23
|
+
it "raises an error" do
|
24
|
+
expect { company.save}.to raise_error PipeLineDealer::Error::Connection::Unprocessable
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
__END__
|
2
|
+
require "helper"
|
3
|
+
|
4
|
+
describe "Company", :acceptance do
|
5
|
+
describe "updating" do
|
6
|
+
include AcceptanceHelper
|
7
|
+
let(:company) { client.companies.create(name: "Old") }
|
8
|
+
|
9
|
+
context "using client.companies.new" do
|
10
|
+
context "with a valid model" do
|
11
|
+
before { company.name = "new" }
|
12
|
+
|
13
|
+
context "when saved" do
|
14
|
+
it "returns a model" do
|
15
|
+
company.save.should be_kind_of PLD::Model::Base
|
16
|
+
end
|
17
|
+
|
18
|
+
it "has the new name" do
|
19
|
+
company.save
|
20
|
+
client.companies.find(company.id).name.should == "new"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "with an invalid model" do
|
26
|
+
before { company.name = nil }
|
27
|
+
|
28
|
+
context "when saved" do
|
29
|
+
it "raises an error" do
|
30
|
+
expect { company.save }.to raise_error PipeLineDealer::Error::Connection::Unprocessable
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
__END__
|
2
|
+
require "helper"
|
3
|
+
|
4
|
+
describe "Person", :acceptance do
|
5
|
+
describe "creation" do
|
6
|
+
include AcceptanceHelper
|
7
|
+
|
8
|
+
context "using client.people.new" do
|
9
|
+
let(:person) { client.people.new(first_name: "Maarten", last_name: "Hoogendoorn") }
|
10
|
+
|
11
|
+
before { person.first_name = "MoreTea" }
|
12
|
+
|
13
|
+
context "when saved" do
|
14
|
+
it "returns a model" do
|
15
|
+
person.save.should be_kind_of PLD::Model::Base
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "pipeline_dealers"
|
2
|
+
require "support/test_model"
|
3
|
+
|
4
|
+
module PipelineDealers::Backend
|
5
|
+
describe Http do
|
6
|
+
let(:backend) { described_class.new(api_key: "zekret") }
|
7
|
+
let(:collection) { Http::Collection.new(backend, client: double("Client"), model_klass: TestModel) }
|
8
|
+
let(:connection) { subject.connection }
|
9
|
+
|
10
|
+
subject { backend }
|
11
|
+
|
12
|
+
describe "saving a model" do
|
13
|
+
context "that is new" do
|
14
|
+
let(:model) { collection.new(name: "Springest") }
|
15
|
+
after(:each) { model.save }
|
16
|
+
|
17
|
+
it "uses the POST method" do
|
18
|
+
connection.should_receive(:post).and_return([200, {}])
|
19
|
+
end
|
20
|
+
|
21
|
+
it "posts to the correct address" do
|
22
|
+
connection.should_receive(:post).with("test_models.json", anything).and_return([200, {}])
|
23
|
+
end
|
24
|
+
|
25
|
+
it "posts the correct attributes" do
|
26
|
+
connection.should_receive(:post).with(anything, "moeha" => { "name" => "Springest" }).and_return([200, {}])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "that has been persisted" do
|
31
|
+
let(:model) { TestModel.new(collection: collection, persisted: true, attributes: { "id" => 123, name: "Springest"}) }
|
32
|
+
after(:each) { model.save }
|
33
|
+
|
34
|
+
it "uses the PUT method" do
|
35
|
+
connection.should_receive(:put).and_return([200, {}])
|
36
|
+
end
|
37
|
+
|
38
|
+
it "posts to the correct address" do
|
39
|
+
connection.should_receive(:put).with("test_models/123.json", anything).and_return([200, {}])
|
40
|
+
end
|
41
|
+
|
42
|
+
it "posts the correct attributes" do
|
43
|
+
connection.should_receive(:put).with(anything, "moeha" => { "name" => "Springest" }).and_return([200, {}])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require "pipeline_dealers"
|
2
|
+
require "support/test_model"
|
3
|
+
|
4
|
+
describe PipelineDealers::Backend::Http::Collection do
|
5
|
+
let(:connection) { double("Connection") }
|
6
|
+
let(:backend) { double("Backend").tap { |b| b.stub(:connection).and_return(connection) } }
|
7
|
+
let(:collection) { described_class.new(backend, client: double("Client"), model_klass: TestModel) }
|
8
|
+
|
9
|
+
subject { collection }
|
10
|
+
|
11
|
+
context "transparant pagination" do
|
12
|
+
let(:expected_params_a) { ["test_models.json", { page: 1, per_page: 200 } ] }
|
13
|
+
let(:expected_params_b) { ["test_models.json", { page: 2, per_page: 200 } ] }
|
14
|
+
|
15
|
+
let(:response_a) do
|
16
|
+
[
|
17
|
+
200, # Status code
|
18
|
+
{ # 'JSON' body
|
19
|
+
"pagination" => {
|
20
|
+
"page" => 1,
|
21
|
+
"pages" => 2,
|
22
|
+
"per_page" => 1,
|
23
|
+
"total" => 2,
|
24
|
+
"url" => '/resource',
|
25
|
+
},
|
26
|
+
"entries" => [model_a.attributes]
|
27
|
+
}
|
28
|
+
]
|
29
|
+
end
|
30
|
+
|
31
|
+
let(:response_b) do
|
32
|
+
[
|
33
|
+
200, # Status code
|
34
|
+
{ # 'JSON' body
|
35
|
+
"pagination" => {
|
36
|
+
"page" => 2,
|
37
|
+
"pages" => 2,
|
38
|
+
"per_page" => 1,
|
39
|
+
"total" => 2,
|
40
|
+
"url" => '/resource',
|
41
|
+
},
|
42
|
+
"entries" => [model_b.attributes]
|
43
|
+
}
|
44
|
+
]
|
45
|
+
end
|
46
|
+
|
47
|
+
let(:model_a) { TestModel.new(collection: subject, attributes: { name: "Maarten" }) }
|
48
|
+
let(:model_b) { TestModel.new(collection: subject, attributes: { name: "Hoogendoorn" }) }
|
49
|
+
|
50
|
+
it "fetches the correct models" do
|
51
|
+
connection.should_receive(:get).ordered.once.with(*expected_params_a).and_return(response_a)
|
52
|
+
connection.should_receive(:get).ordered.once.with(*expected_params_b).and_return(response_b)
|
53
|
+
|
54
|
+
subject.all.to_a.should =~ [model_a, model_b]
|
55
|
+
end
|
56
|
+
|
57
|
+
it "returns records that are not new" do
|
58
|
+
connection.should_receive(:get).ordered.once.with(*expected_params_a).and_return(response_a)
|
59
|
+
connection.should_receive(:get).ordered.once.with(*expected_params_b).and_return(response_b)
|
60
|
+
|
61
|
+
a, b = subject.all.to_a
|
62
|
+
|
63
|
+
a.new_record?.should == false
|
64
|
+
b.new_record?.should == false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "limit fetching" do
|
69
|
+
let(:expected_params) { ["test_models.json", { page:1, per_page: 1} ] }
|
70
|
+
|
71
|
+
let(:response) do
|
72
|
+
[
|
73
|
+
200, # Status code
|
74
|
+
{ # 'JSON' body
|
75
|
+
"pagination" => {
|
76
|
+
"page" => 1,
|
77
|
+
"pages" => 2,
|
78
|
+
"per_page" => 1,
|
79
|
+
"total" => 2,
|
80
|
+
"url" => '/resource',
|
81
|
+
},
|
82
|
+
"entries" => [model_a.attributes]
|
83
|
+
}
|
84
|
+
]
|
85
|
+
end
|
86
|
+
|
87
|
+
let(:model_a) { TestModel.new(collection: subject, attributes: { name: "Maarten"}) }
|
88
|
+
|
89
|
+
it "fetches only the resouces before the limit" do
|
90
|
+
connection.should_receive(:get).once.with(*expected_params).and_return(response)
|
91
|
+
subject.first.should == model_a
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "cacheing" do
|
96
|
+
let(:response) do
|
97
|
+
[
|
98
|
+
200, # Status code
|
99
|
+
{
|
100
|
+
"pagination" => {
|
101
|
+
"page" => 1,
|
102
|
+
"pages" => 1,
|
103
|
+
"per_page" => 1,
|
104
|
+
"total" => 1,
|
105
|
+
"url" => '/resource',
|
106
|
+
},
|
107
|
+
"entries" => [{}]
|
108
|
+
}
|
109
|
+
]
|
110
|
+
end
|
111
|
+
|
112
|
+
before do
|
113
|
+
connection.stub(:get).and_return(response)
|
114
|
+
end
|
115
|
+
|
116
|
+
context "not cached" do
|
117
|
+
subject { described_class.new(backend, client: double("Client"), model_klass: TestModel, cached: false) }
|
118
|
+
|
119
|
+
it "doesn't try to cache the result" do
|
120
|
+
connection.should_not_receive(:cache)
|
121
|
+
subject.all.to_a
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "cached" do
|
126
|
+
subject { described_class.new(backend, client: double("Client"), model_klass: TestModel, cached: true) }
|
127
|
+
|
128
|
+
it "caches the request" do
|
129
|
+
backend.should_receive(:cache)
|
130
|
+
subject.all
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "building new objects" do
|
136
|
+
context "with no initial attributes" do
|
137
|
+
subject { collection.new }
|
138
|
+
it { should be_kind_of TestModel }
|
139
|
+
its(:persisted?) { should == false}
|
140
|
+
end
|
141
|
+
|
142
|
+
context "with initial attributes" do
|
143
|
+
context "valid attributes" do
|
144
|
+
subject { collection.new(name: "Springest") }
|
145
|
+
|
146
|
+
its(:name) { should == "Springest" }
|
147
|
+
end
|
148
|
+
|
149
|
+
context "invalid attributes" do
|
150
|
+
context "invalid name" do
|
151
|
+
it "raises an exception" do
|
152
|
+
expect { subject.new(no_such_name: "Springest") }.to raise_error(PipelineDealers::Error::InvalidAttributeName)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require "pipeline_dealers"
|
2
|
+
|
3
|
+
module PipelineDealers
|
4
|
+
class Model
|
5
|
+
describe CustomField do
|
6
|
+
let(:model) { nil }
|
7
|
+
|
8
|
+
describe "decode" do
|
9
|
+
context "numeric" do
|
10
|
+
before { subject.field_type = "numeric" }
|
11
|
+
|
12
|
+
it "decodes correctly" do
|
13
|
+
subject.decode(model, 123).should == 123
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "text" do
|
18
|
+
before { subject.field_type = "text" }
|
19
|
+
|
20
|
+
it "decodes correctly" do
|
21
|
+
subject.decode(model, "Moehaha").should == "Moehaha"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "currency" do
|
26
|
+
before { subject.field_type = "currency" }
|
27
|
+
|
28
|
+
it "decodes correctly" do
|
29
|
+
subject.decode(model, 42).should == 42
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "dropdown" do
|
34
|
+
subject do
|
35
|
+
CustomField.new(attributes: {
|
36
|
+
"field_type" => "dropdown",
|
37
|
+
"custom_field_label_dropdown_entries" => [{"id" => 123, "value" => "My Item"}]
|
38
|
+
})
|
39
|
+
end
|
40
|
+
|
41
|
+
it "decodes correctly" do
|
42
|
+
subject.decode(model, 123).should == "My Item"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "multi_select" do
|
47
|
+
subject do
|
48
|
+
CustomField.new(attributes: {
|
49
|
+
"field_type" => "multi_select",
|
50
|
+
"custom_field_label_dropdown_entries" => [{"id" => 123, "value" => "My Item"}]
|
51
|
+
})
|
52
|
+
end
|
53
|
+
|
54
|
+
it "decodes correctly" do
|
55
|
+
subject.decode(model, [123]).should == ["My Item"]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "Unkown type" do
|
60
|
+
before { subject.field_type = "not-known" }
|
61
|
+
|
62
|
+
it "throws an exception" do
|
63
|
+
expect { subject.decode(model, 42) }.to raise_error
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "encode" do
|
69
|
+
context "numeric" do
|
70
|
+
before { subject.field_type = "numeric" }
|
71
|
+
|
72
|
+
it "encodes correctly" do
|
73
|
+
subject.encode(model, 123).should == 123
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "text" do
|
78
|
+
before { subject.field_type = "text" }
|
79
|
+
|
80
|
+
it "encodes correctly" do
|
81
|
+
subject.encode(model, "Moehaha").should == "Moehaha"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "currency" do
|
86
|
+
before { subject.field_type = "currency" }
|
87
|
+
|
88
|
+
it "encodes correctly" do
|
89
|
+
subject.encode(model, 42).should == 42
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "dropdown" do
|
94
|
+
subject do
|
95
|
+
CustomField.new(attributes: {
|
96
|
+
"field_type" => "dropdown",
|
97
|
+
"custom_field_label_dropdown_entries" => [{"id" => 123, "value" => "My Item"}]
|
98
|
+
})
|
99
|
+
end
|
100
|
+
|
101
|
+
it "encodes correctly" do
|
102
|
+
subject.encode(model, "My Item").should == 123
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "multi_select" do
|
107
|
+
subject do
|
108
|
+
CustomField.new(attributes: {
|
109
|
+
"field_type" => "multi_select",
|
110
|
+
"custom_field_label_dropdown_entries" => [{"id" => 123, "value" => "My Item"}]
|
111
|
+
})
|
112
|
+
end
|
113
|
+
|
114
|
+
it "encodes correctly" do
|
115
|
+
subject.encode(model, ["My Item"]).should == [123]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context "Unkown type" do
|
120
|
+
before { subject.field_type = "not-known" }
|
121
|
+
|
122
|
+
it "throws an exception" do
|
123
|
+
expect { subject.encode(model, 42) }.to raise_error
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|