pipeline_dealers 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|