pipe_line_dealer 0.1.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.
Files changed (51) hide show
  1. data/.gitignore +3 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +3 -0
  5. data/Guardfile +5 -0
  6. data/LICENCE +7 -0
  7. data/README.md +19 -0
  8. data/api_remarks.txt +5 -0
  9. data/lib/pipe_line_dealer/client/connection.rb +71 -0
  10. data/lib/pipe_line_dealer/client.rb +27 -0
  11. data/lib/pipe_line_dealer/collection/concerns/create_and_update.rb +25 -0
  12. data/lib/pipe_line_dealer/collection/concerns/fetching.rb +64 -0
  13. data/lib/pipe_line_dealer/collection/concerns/results_fetcher.rb +64 -0
  14. data/lib/pipe_line_dealer/collection/concerns.rb +6 -0
  15. data/lib/pipe_line_dealer/collection.rb +24 -0
  16. data/lib/pipe_line_dealer/custom_field/collection.rb +18 -0
  17. data/lib/pipe_line_dealer/custom_fields.rb +59 -0
  18. data/lib/pipe_line_dealer/error/connection.rb +17 -0
  19. data/lib/pipe_line_dealer/error/invalid_attribute.rb +29 -0
  20. data/lib/pipe_line_dealer/error/no_such_custom_field.rb +12 -0
  21. data/lib/pipe_line_dealer/error.rb +9 -0
  22. data/lib/pipe_line_dealer/limits.rb +7 -0
  23. data/lib/pipe_line_dealer/model/base/concern/persistance.rb +69 -0
  24. data/lib/pipe_line_dealer/model/base.rb +133 -0
  25. data/lib/pipe_line_dealer/model/company/custom_field.rb +7 -0
  26. data/lib/pipe_line_dealer/model/company.rb +37 -0
  27. data/lib/pipe_line_dealer/model/custom_field.rb +73 -0
  28. data/lib/pipe_line_dealer/model/note.rb +32 -0
  29. data/lib/pipe_line_dealer/model/person/custom_field.rb +7 -0
  30. data/lib/pipe_line_dealer/model/person.rb +36 -0
  31. data/lib/pipe_line_dealer/version.rb +10 -0
  32. data/lib/pipe_line_dealer.rb +44 -0
  33. data/pipe_line_dealer.gemspec +45 -0
  34. data/spec/acceptance/companies/creation_spec.rb +31 -0
  35. data/spec/acceptance/companies/custom_fields_spec.rb +7 -0
  36. data/spec/acceptance/companies/updating_spec.rb +35 -0
  37. data/spec/acceptance/people/creation_spec.rb +19 -0
  38. data/spec/collection_spec.rb +166 -0
  39. data/spec/custom_fields_spec.rb +114 -0
  40. data/spec/helper.rb +32 -0
  41. data/spec/models/base/concern/persistance_spec.rb +55 -0
  42. data/spec/models/base_spec.rb +32 -0
  43. data/spec/models/custom_field_spec.rb +127 -0
  44. data/spec/smell_spec.rb +6 -0
  45. data/spec/support/acceptance_helper.rb +39 -0
  46. data/spec/support/collection_helper.rb +8 -0
  47. data/spec/support/connection_helper.rb +9 -0
  48. data/spec/support/pld_cleaner.rb +16 -0
  49. data/spec/support/test_model.rb +6 -0
  50. data/todo.txt +6 -0
  51. metadata +320 -0
@@ -0,0 +1,114 @@
1
+ require "helper"
2
+
3
+ describe PipeLineDealer::CustomFields do
4
+ before { pending "TODO" }
5
+ include ConnectionHelper
6
+
7
+ class ModelWithCustomFields < PLD::Model::Base
8
+ @collection_url = "models"
9
+ @model_attribute_name = "model"
10
+ @custom_field_client_method = :model_custom_fields
11
+
12
+ attrs :name
13
+
14
+ include PLD::CustomFields
15
+ end
16
+
17
+ class CustomModelField < PipeLineDealer::CustomField
18
+ @collection_url = "admin/model_custom_field_labels"
19
+ end
20
+
21
+ let(:collection) { PLD::Collection.new(client, klass: ModelWithCustomFields) }
22
+
23
+ let(:custom_attributes) { {
24
+ "custom_label_90" => 42,
25
+ "custom_label_91" => "Yeah"
26
+ } }
27
+
28
+ let(:custom_field_labels) { {
29
+ "entries"=>[
30
+ {
31
+ "id"=>90,
32
+ "name"=>"TheAnswerForEverything",
33
+ "is_required"=>false,
34
+ "field_type"=>"numeric"
35
+ },
36
+ {
37
+ "id"=>91,
38
+ "name"=>"Really?",
39
+ "is_required"=>false,
40
+ "field_type"=>"text"
41
+ }
42
+ ],
43
+ "pagination" => {"page" => 1, "pages" => 1, "per_page" => 2, "total" => 2}
44
+ }
45
+ }
46
+
47
+ subject { ModelWithCustomFields.new(collection: collection, persisted: true, attributes: { "id" => 123, name: "Springest", custom_fields: custom_attributes} ) }
48
+
49
+ context "reading custom fields" do
50
+ before { client.stub(:model_custom_fields).and_return { PLD::CustomField::Collection.new(client, klass: CustomModelField, cache_key: :custom_field_cache_key) } }
51
+
52
+ let(:custom_field_models) do
53
+ custom_field_labels.collect { |label| CustomModelField.new(collection: model_custom_fields, persisted: true, attributes: label) }
54
+ end
55
+
56
+ it "fetches the translation map" do
57
+ pending
58
+ # connection.should_receive(:get).once.with("admin/model_custom_field_labels.json", anything()).and_return(custom_field_labels)
59
+ connection.should_receive(:cache).once.with(:custom_field_cache_key).and_return(custom_field_labels)
60
+ subject.custom_fields
61
+ end
62
+
63
+ it "translates the custom fields to recognizable labels" do
64
+ connection.should_receive(:get).once.with("admin/model_custom_field_labels.json", anything()).and_return(custom_field_labels)
65
+
66
+ subject.custom_fields.should == {
67
+ "TheAnswerForEverything" => 42,
68
+ "Really?" => "Yeah"
69
+ }
70
+ end
71
+ end
72
+
73
+ context "storing" do
74
+ before { client.stub(:model_custom_fields).and_return { PLD::CustomField::Collection.new(client, klass: CustomModelField) } }
75
+
76
+ it "reposts the correct attributes" do
77
+ expected_attributes = {
78
+ "model" => {
79
+ "name" => "Springest",
80
+ "custom_fields" => custom_attributes
81
+ }
82
+ }
83
+
84
+ # TODO: should do this only once!
85
+ connection.should_receive(:get).exactly(4).times.with("admin/model_custom_field_labels.json", anything()).and_return(custom_field_labels)
86
+ connection.should_receive(:put).once.with("models/123.json", expected_attributes)
87
+
88
+ subject.save
89
+ end
90
+
91
+ let(:updated_custom_attributes) { {
92
+ "custom_label_90" => 43,
93
+ "custom_label_91" => "Whoo"
94
+ } }
95
+
96
+ it "posts the correct change" do
97
+ expected_attributes = {
98
+ "model" => {
99
+ "name" => "Springest",
100
+ "custom_fields" => updated_custom_attributes
101
+ }
102
+ }
103
+
104
+ # TODO: should do this only once!
105
+ connection.should_receive(:get).exactly(4).times.with("admin/model_custom_field_labels.json", anything()).and_return(custom_field_labels)
106
+ connection.should_receive(:put).once.with("models/123.json", expected_attributes)
107
+
108
+
109
+ subject.custom_fields["TheAnswerForEverything"] = 43
110
+ subject.custom_fields["Really?"] = "Whoo"
111
+ subject.save
112
+ end
113
+ end
114
+ end
data/spec/helper.rb ADDED
@@ -0,0 +1,32 @@
1
+ Bundler.setup
2
+
3
+ unless ENV["NO_COVERAGE"]
4
+ require "simplecov"
5
+ SimpleCov.start do
6
+ add_filter "spec"
7
+ end
8
+ end
9
+
10
+ require "pipe_line_dealer"
11
+ require "webmock/rspec"
12
+ require "reek/spec"
13
+
14
+ # Load support files
15
+ Dir[File.expand_path("../support/**/*.rb", __FILE__)].each { |f| require f }
16
+
17
+ RSpec.configure do |config|
18
+ config.filter_run focus: true
19
+
20
+ # Do not run the acceptance tests by default.
21
+ if ENV["ACCEPTANCE"] == "true"
22
+ puts "Running acceptance specs!"
23
+ AcceptanceHelper.check_api_key!
24
+ else
25
+ puts "Skipping acceptance specs"
26
+ config.filter_run_excluding acceptance: true
27
+ end
28
+
29
+ config.treat_symbols_as_metadata_keys_with_true_values = true
30
+ config.run_all_when_everything_filtered = true
31
+ config.include Reek::Spec
32
+ end
@@ -0,0 +1,55 @@
1
+ require "helper"
2
+
3
+ describe PipeLineDealer::Model::Base::Concern::Persistance do
4
+ include CollectionHelper
5
+
6
+ context "routing (url&method)" do
7
+ context "non persisted models" do
8
+ context "build by collection" do
9
+ subject { collection.new }
10
+
11
+ it "builds a non persisted model" do
12
+ subject.persisted?.should == false
13
+ end
14
+
15
+ it "builds a non persisted model" do
16
+ subject.persisted?.should == false
17
+ end
18
+ end
19
+
20
+ context "when saved" do
21
+ subject { collection.new(name: "Springest") }
22
+ after(:each) { subject.save }
23
+
24
+ it "uses the POST method" do
25
+ connection.should_receive(:post).and_return([200, {}])
26
+ end
27
+
28
+ it "posts to the correct address" do
29
+ connection.should_receive(:post).with("test_models.json", anything).and_return([200, {}])
30
+ end
31
+
32
+ it "posts the correct attributes" do
33
+ connection.should_receive(:post).with(anything, "moeha" => { "name" => "Springest" }).and_return([200, {}])
34
+ end
35
+ end
36
+ end
37
+
38
+ context "persisted models" do
39
+ subject { TestModel.new(collection: collection, persisted: true, attributes: { "id" => 123, name: "Springest"} ) }
40
+ after(:each) { subject.save }
41
+
42
+ it "uses the PUT method" do
43
+ connection.should_receive(:put).and_return([200, {}])
44
+ end
45
+
46
+ it "posts to the correct address" do
47
+ connection.should_receive(:put).with("test_models/123.json", anything).and_return([200, {}])
48
+ end
49
+
50
+ it "posts the correct attributes" do
51
+ connection.should_receive(:put).with(anything, "moeha" => { "name" => "Springest" }).and_return([200, {}])
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,32 @@
1
+ require "helper"
2
+
3
+ describe PLD::Model::Base do
4
+ subject { TestModel }
5
+
6
+ context "initialization" do
7
+ let(:model) { subject.new(attributes: {name: "Springest"}) }
8
+
9
+ it "can access the name by the name method" do
10
+ model.name.should == "Springest"
11
+ end
12
+
13
+ it "can access the name by via attributes['name']" do
14
+ model.attributes['name'].should == "Springest"
15
+ end
16
+
17
+ it "can access the name by via attributes[:name]" do
18
+ model.attributes[:name].should == "Springest"
19
+ end
20
+ end
21
+
22
+ context "setting attributes" do
23
+ let(:model) { subject.new() }
24
+ context "name is set using accessor" do
25
+ before { model.name = "Springest" }
26
+
27
+ it "is readable via the accessor" do
28
+ model.name.should == "Springest"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,127 @@
1
+ require "helper"
2
+
3
+ module PipeLineDealer
4
+ describe CustomField do
5
+ let(:model) { nil }
6
+
7
+ describe "decode" do
8
+ context "numeric" do
9
+ before { subject.field_type = "numeric" }
10
+
11
+ it "decodes correctly" do
12
+ subject.decode(model, 123).should == 123
13
+ end
14
+ end
15
+
16
+ context "text" do
17
+ before { subject.field_type = "text" }
18
+
19
+ it "decodes correctly" do
20
+ subject.decode(model, "Moehaha").should == "Moehaha"
21
+ end
22
+ end
23
+
24
+ context "currency" do
25
+ before { subject.field_type = "currency" }
26
+
27
+ it "decodes correctly" do
28
+ subject.decode(model, 42).should == 42
29
+ end
30
+ end
31
+
32
+ context "dropdown" do
33
+ subject do
34
+ CustomField.new(attributes: {
35
+ "field_type" => "dropdown",
36
+ "custom_field_label_dropdown_entries" => [{"id" => 123, "value" => "My Item"}]
37
+ })
38
+ end
39
+
40
+ it "decodes correctly" do
41
+ subject.decode(model, 123).should == "My Item"
42
+ end
43
+ end
44
+
45
+ context "multi_select" do
46
+ subject do
47
+ CustomField.new(attributes: {
48
+ "field_type" => "multi_select",
49
+ "custom_field_label_dropdown_entries" => [{"id" => 123, "value" => "My Item"}]
50
+ })
51
+ end
52
+
53
+ it "decodes correctly" do
54
+ subject.decode(model, [123]).should == ["My Item"]
55
+ end
56
+ end
57
+
58
+ context "Unkown type" do
59
+ before { subject.field_type = "not-known" }
60
+
61
+ it "throws an exception" do
62
+ expect { subject.decode(model, 42) }.to raise_error
63
+ end
64
+ end
65
+ end
66
+
67
+ describe "encode" do
68
+ context "numeric" do
69
+ before { subject.field_type = "numeric" }
70
+
71
+ it "encodes correctly" do
72
+ subject.encode(model, 123).should == 123
73
+ end
74
+ end
75
+
76
+ context "text" do
77
+ before { subject.field_type = "text" }
78
+
79
+ it "encodes correctly" do
80
+ subject.encode(model, "Moehaha").should == "Moehaha"
81
+ end
82
+ end
83
+
84
+ context "currency" do
85
+ before { subject.field_type = "currency" }
86
+
87
+ it "encodes correctly" do
88
+ subject.encode(model, 42).should == 42
89
+ end
90
+ end
91
+
92
+ context "dropdown" do
93
+ subject do
94
+ CustomField.new(attributes: {
95
+ "field_type" => "dropdown",
96
+ "custom_field_label_dropdown_entries" => [{"id" => 123, "value" => "My Item"}]
97
+ })
98
+ end
99
+
100
+ it "encodes correctly" do
101
+ subject.encode(model, "My Item").should == 123
102
+ end
103
+ end
104
+
105
+ context "multi_select" do
106
+ subject do
107
+ CustomField.new(attributes: {
108
+ "field_type" => "multi_select",
109
+ "custom_field_label_dropdown_entries" => [{"id" => 123, "value" => "My Item"}]
110
+ })
111
+ end
112
+
113
+ it "encodes correctly" do
114
+ subject.encode(model, ["My Item"]).should == [123]
115
+ end
116
+ end
117
+
118
+ context "Unkown type" do
119
+ before { subject.field_type = "not-known" }
120
+
121
+ it "throws an exception" do
122
+ expect { subject.encode(model, 42) }.to raise_error
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,6 @@
1
+ describe "The source of this gem" do
2
+ it "contains no code smells" do
3
+ pending "Will move there, but not yet."
4
+ Dir["lib/**/*.rb"].should_not reek
5
+ end
6
+ end
@@ -0,0 +1,39 @@
1
+ module AcceptanceHelper extend ActiveSupport::Concern
2
+
3
+ class << self
4
+ KEY_FILE = File.expand_path("../../api.key", __FILE__)
5
+
6
+ def check_api_key!
7
+ if not find_api_key
8
+ puts
9
+ $stderr.puts "No API key found to run the acceptance tests!"
10
+ puts "To specify a API key, either:"
11
+ puts " 1) use the API_KEY environmental variable!"
12
+ puts " 2) create a 'spec/api.key' file which contains the API key."
13
+ puts
14
+ exit(1)
15
+ end
16
+ end
17
+
18
+ def find_api_key
19
+ ENV["API_KEY"] || File.exists?(KEY_FILE) && File.read(KEY_FILE).chomp.strip
20
+ end
21
+ end
22
+
23
+ included do
24
+ let(:api_key) { AcceptanceHelper.find_api_key }
25
+ let(:client) { PLD::Client.new(AcceptanceHelper.find_api_key) }
26
+
27
+ around do |example|
28
+ if example.metadata.has_key? :acceptance
29
+ WebMock.allow_net_connect!
30
+
31
+ PLDCleaner.clean!(client)
32
+ end
33
+
34
+ example.run
35
+
36
+ WebMock.disable_net_connect! if example.metadata.has_key? :acceptance
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,8 @@
1
+ module CollectionHelper
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ include ConnectionHelper
6
+ let(:collection) { PLD::Collection.new(client, klass: TestModel) }
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ module ConnectionHelper
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ let(:connection) { double("Connection") }
6
+ let(:client) { double("Client") }
7
+ before { client.stub(:connection).and_return(connection) }
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ module PLDCleaner
2
+ extend self
3
+
4
+ COLLECTION_NAMES = [:companies, :people]
5
+
6
+ def clean!(client)
7
+ COLLECTION_NAMES.each do |collection_name|
8
+ collection = client.send(collection_name)
9
+
10
+ collection.each do |model|
11
+ #CRITICAL
12
+ model.destroy || raise("Could not remove #{model.inspect}")
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,6 @@
1
+ class TestModel < PLD::Model::Base
2
+ @collection_url = "test_models"
3
+ @model_attribute_name = "moeha"
4
+
5
+ attrs :name
6
+ end
data/todo.txt ADDED
@@ -0,0 +1,6 @@
1
+ - test coverage to 100%
2
+ - specs for not saving some attributes
3
+ - implement other models
4
+
5
+ WRITE SPECS FOR:
6
+ - lib/pipe_line_dealer/model/custom_field.rb