multicolor 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: faa681abadf3aefc66674b7ade04ec7f848704d8
4
+ data.tar.gz: 6574464e78742045a2ed80f96d2c4928d3f2b01e
5
+ SHA512:
6
+ metadata.gz: 8de82e40093c6a0f0a0a978b8f014fb8f211f152968a9a7f5251e4433545c0cd122c27d002e1aa33f3469940d2dc2ccc905cb58d425f6f291db1017ca0692168
7
+ data.tar.gz: afeb3c2e3650a7ee13d16e641beac41daea7a7b73c248ee16f47d666215c91815a8dc687e2fc2b491f8c61ad045c687641d70138408e8bb54124e2de2b8bd951
@@ -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,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in multicolor.gemspec
4
+ gemspec
@@ -0,0 +1,24 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
+ watch('config/routes.rb') { "spec/routing" }
15
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
+
17
+ # Capybara features specs
18
+ watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
19
+
20
+ # Turnip features and steps
21
+ watch(%r{^spec/acceptance/(.+)\.feature$})
22
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
23
+ end
24
+
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Apartment Therapy LLC
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.
@@ -0,0 +1,130 @@
1
+ # Multicolor
2
+
3
+ An opinionated library to ease usage of TinEye's fabulous MulticolorEngine
4
+ http://services.tineye.com/MulticolorEngine.
5
+
6
+ Full API documentation available at http://multicolorengine.tineye.com/docs/
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'multicolor'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install multicolor
21
+
22
+ ## Usage Examples
23
+
24
+ ### Instantiating a client
25
+
26
+ ```ruby
27
+ client = Multicolor::REST::Client.new do |client|
28
+ client.config.company = "<api-company>"
29
+ client.config.username = "<api-username>"
30
+ client.config.password = "<password>"
31
+ end
32
+ ```
33
+
34
+ ### Adding or deleting items
35
+
36
+ ```ruby
37
+ data = [
38
+ {
39
+ url: "http://url-to-image",
40
+ filepath: "/path/to/image",
41
+ metadata: {
42
+ ...
43
+ }
44
+ },
45
+ {
46
+ url: "http://url-to-other-image",
47
+ filepath: "/path/to/another/image",
48
+ metadata: {
49
+ ...
50
+ }
51
+ },
52
+ ]
53
+
54
+ client.add(data) # add the image to the collection
55
+
56
+ client.delete(["/path/to/image", another_"/path/to/image"] ) # delete images
57
+ client.delete("/path/to/image") # pass a single filepath to delete a single image
58
+ ```
59
+
60
+ ### searching the index
61
+
62
+ ```ruby
63
+ # searching for similar colors
64
+ params = {
65
+ colors: [
66
+ {
67
+ color: #rgb or hex
68
+ width: 1-100
69
+ }...
70
+ ],
71
+ min_score: 0-11
72
+ offset: integer
73
+ ...
74
+ }
75
+
76
+ # Multicolor::REST::SearchBuilder is a convenience method
77
+ # that formats params to format required by
78
+ # the MulticolorEngine, eg: color[0], color[1]....
79
+ search_options = Multicolor::REST::SearchBuilder.new(params).request
80
+
81
+ response = client.color_search(search_options)
82
+ response.body # returns API response
83
+ ```
84
+
85
+ ### Metadata
86
+
87
+ ```ruby
88
+
89
+ # extract colors for n images identified by filepath
90
+ options = {
91
+ filepaths: ["/path/to/image", "/path/to/another/image"]
92
+ limit: 20
93
+ }
94
+ client.extract_collection_colors(options)
95
+
96
+ # extract metadata for n images
97
+ client.get_metadata(filepaths: ["/path/to/image"])
98
+
99
+ # count collection colors
100
+
101
+ options = {
102
+ count_colors: ["233,233,233","23,33,91"]
103
+ filepaths: ["/path/to/image", "/path/to/other/image"]
104
+ ...
105
+ }
106
+
107
+ client.count_collection_colors(options)
108
+
109
+ ```
110
+
111
+ ### Info
112
+
113
+ ```ruby
114
+ # counting items in the collection/index
115
+ client.count
116
+
117
+ # List the images present in your API.
118
+ client.list
119
+
120
+ # pinging the API to see if the Piximilar search server is running.
121
+ client.ping
122
+ ```
123
+
124
+ ## Contributing
125
+
126
+ 1. Fork it
127
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
128
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
129
+ 4. Push to the branch (`git push origin my-new-feature`)
130
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,19 @@
1
+ require 'active_support/core_ext'
2
+ require 'faraday'
3
+ require 'faraday_middleware'
4
+
5
+ require 'multicolor/configuration'
6
+ require 'multicolor/util'
7
+ require 'multicolor/version'
8
+ require 'multicolor/errors/bad_response'
9
+ require 'multicolor/errors/company_not_set'
10
+ require 'multicolor/rest'
11
+ require 'multicolor/rest/client'
12
+ require 'multicolor/rest/search_builder'
13
+ require 'multicolor/rest/endpoints'
14
+ require 'multicolor/rest/endpoints/filepath'
15
+ require 'multicolor/rest/endpoints/indexing'
16
+ require 'multicolor/rest/endpoints/metadata'
17
+
18
+ module Multicolor
19
+ end
@@ -0,0 +1,22 @@
1
+ module Multicolor
2
+ class Configuration
3
+ attr_accessor :timeout, :open_timeout, :username, :password, :company
4
+
5
+ def valid?
6
+ # TODO
7
+ # are username, company, password set?
8
+ end
9
+
10
+ def authenticate?
11
+ true
12
+ end
13
+
14
+ def timeout
15
+ @timeout || 40
16
+ end
17
+
18
+ def open_timeout
19
+ @open_timeout || 40
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,5 @@
1
+ module Multicolor
2
+ module Errors
3
+ class BadResponse < StandardError; end
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Multicolor
2
+ module Errors
3
+ class CompanyNotSet < StandardError; end
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module Multicolor
2
+ module REST
3
+ end
4
+ end
@@ -0,0 +1,26 @@
1
+ require 'multicolor/rest/transport'
2
+
3
+ module Multicolor
4
+ module REST
5
+ class Client
6
+ delegate :get_search_metadata, :get_return_metadata,
7
+ :count, :list, :ping, :add, :delete, :get_metadata,
8
+ :update_metadata, :color_search,
9
+ :extract_collection_colors, to: :transport
10
+
11
+ def initialize(options = {})
12
+ yield(self) if block_given?
13
+ end
14
+
15
+ def config
16
+ @configuration ||= Multicolor::Configuration.new
17
+ end
18
+
19
+ private
20
+
21
+ def transport
22
+ @transport ||= Multicolor::REST::Transport.new(config)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,6 @@
1
+ module Multicolor
2
+ module REST
3
+ module Endpoints
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,25 @@
1
+ module Multicolor
2
+ module REST
3
+ module Endpoints
4
+ module Filepath
5
+ def color_search(options)
6
+ post(:color_search, options)
7
+ end
8
+
9
+ def extract_collection_colors(options)
10
+ filepaths = options.delete(:filepaths)
11
+ get(:extract_collection_colors, Multicolor::Util.filepaths(filepaths).merge(options))
12
+ end
13
+
14
+ def get_metadata(options)
15
+ filepaths = options.delete(:filepaths)
16
+ get(:get_metadata, Multicolor::Util.filepaths(filepaths).merge(options))
17
+ end
18
+
19
+ def update_metadata(payload)
20
+ post(:update_metadata, Multicolor::Util.payload_builder(payload))
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,15 @@
1
+ module Multicolor
2
+ module REST
3
+ module Endpoints
4
+ module Indexing
5
+ def add(payload)
6
+ post(:add, Multicolor::Util.payload_builder(payload))
7
+ end
8
+
9
+ def delete(filepaths)
10
+ post(:delete, Multicolor::Util.filepaths(filepaths))
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,54 @@
1
+ module Multicolor
2
+ module REST
3
+ module Endpoints
4
+ module Metadata
5
+ # {
6
+ # count_colors: ["122,233,433", "343,433,333"]
7
+ # filepaths: ["/one/image", "/another/image"]
8
+ # metadata: {
9
+ # ...
10
+ # }
11
+ # }
12
+ def count_collection_colors(options)
13
+ keys = [:count_colors, :weights, :filepaths]
14
+ formatted_options = extract_and_format_options(options, keys)
15
+ get(:count_collection_colors, formatted_options)
16
+ end
17
+
18
+ def count_metadata(options)
19
+ keys = [:colors, :count_metadata, :weights, :filepaths]
20
+ formatted_options = extract_and_format_options(options, keys)
21
+ get(:count_metadata, formatted_options)
22
+ end
23
+
24
+ def get_search_metadata
25
+ get(:get_search_metadata)
26
+ end
27
+
28
+ def get_return_metadata
29
+ get(:get_return_metadata)
30
+ end
31
+
32
+ def count
33
+ get(:count)
34
+ end
35
+
36
+ def list(options = {})
37
+ get(:list, options)
38
+ end
39
+
40
+ def ping
41
+ get(:ping)
42
+ end
43
+
44
+ private
45
+
46
+ def extract_and_format_options(options, keys)
47
+ payload = Multicolor::Util.payload_builder(options.delete(:colors))
48
+ options = Multicolor::Util::modify_options_for_keys(options, keys)
49
+ options.merge(payload)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,40 @@
1
+ module Multicolor
2
+ module REST
3
+ class SearchBuilder
4
+ attr_reader :keys, :params
5
+
6
+ def initialize(params, *keys)
7
+ @params = params
8
+ @keys = keys.any? ? allowed_params & keys : allowed_params
9
+ end
10
+
11
+ def request
12
+ built
13
+ .merge(Multicolor::Util.build_colors(built.delete(:colors)))
14
+ .merge(return_metadata: built.delete(:return_metadata).to_json) # son of a bitch
15
+ .delete_if{ |k,v| v.nil? }
16
+ end
17
+
18
+ private
19
+
20
+ def built
21
+ @built ||= params.slice(*keys)
22
+ end
23
+
24
+ def allowed_params
25
+ [
26
+ :filepath,
27
+ :colors,
28
+ :weights,
29
+ :ignore_background,
30
+ :ignore_interior_background,
31
+ :return_metadata,
32
+ :metadata,
33
+ :min_score,
34
+ :offset,
35
+ :limit
36
+ ]
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,54 @@
1
+ require 'multicolor/rest/endpoints/filepath'
2
+ require 'multicolor/rest/endpoints/indexing'
3
+ require 'multicolor/rest/endpoints/metadata'
4
+
5
+ module Multicolor
6
+ module REST
7
+ class Transport
8
+ include Multicolor::REST::Endpoints::Filepath
9
+ include Multicolor::REST::Endpoints::Indexing
10
+ include Multicolor::REST::Endpoints::Metadata
11
+
12
+ attr_reader :client, :config
13
+
14
+ delegate :company, to: :config
15
+
16
+ def initialize(config)
17
+ @config = config
18
+
19
+ @client = Faraday.new(url: url) do |conn|
20
+ conn.request :multipart
21
+ conn.request :url_encoded
22
+ conn.response :json
23
+ conn.adapter :net_http
24
+
25
+ conn.use Faraday::Response::RaiseError
26
+
27
+ conn.options[:timeout] = config.timeout
28
+ conn.options[:open_timeout] = config.open_timeout
29
+
30
+ conn.basic_auth(config.username, config.password) if config.authenticate?
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def get(endpoint, params = {}, &block)
37
+ client.get(api_path(endpoint), params, &block)
38
+ end
39
+
40
+ def post(endpoint, params = {}, &block)
41
+ client.post(api_path(endpoint), params, &block)
42
+ end
43
+
44
+ def url
45
+ "http://multicolorengine.tineye.com"
46
+ end
47
+
48
+ def api_path(endpoint)
49
+ raise Multicolor::Errors::CompanyNotSet if company.nil?
50
+ "#{company}/rest/#{endpoint}"
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,54 @@
1
+ module Multicolor
2
+ module Util
3
+ class << self
4
+ def param_builder(params)
5
+ new_params = {}
6
+ new_params.merge!(filepaths(params[:filepaths]))
7
+ new_params
8
+ end
9
+
10
+ def filepaths(filename)
11
+ Array.wrap(filename).inject({}) do |data, item|
12
+ data["filepaths[#{data.keys.count}]"] = item
13
+ data
14
+ end
15
+ end
16
+
17
+ def build_colors(params)
18
+ payload_builder(flatten_colors(params))
19
+ end
20
+
21
+ def flatten_colors(params)
22
+ params.is_a?(Hash) ? params.values : params
23
+ end
24
+
25
+ def payload_builder(payload)
26
+ processed = 0
27
+ data = {}
28
+ (payload || {}).each do |entry|
29
+ entry.keys.each do |key|
30
+ value = entry[key]
31
+ data["#{key.to_s.pluralize}[#{processed}]"] = value.is_a?(Hash) ? value.to_json : value
32
+ end
33
+ processed += 1
34
+ end
35
+ data
36
+ end
37
+
38
+ def modify_options_for_keys(options, keys)
39
+ options.symbolize_keys!
40
+ subset = options.slice(*keys)
41
+ subset.each do |key, value|
42
+ data = {}
43
+ Array.wrap(value).each do |val|
44
+ data["#{key.to_s.pluralize}[#{data.keys.length}]"] = val
45
+ end
46
+ options.merge!(data)
47
+ end
48
+
49
+ keys.each{ |key| options.delete(key) }
50
+ options
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,3 @@
1
+ module Multicolor
2
+ VERSION = "0.1.1"
3
+ end
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'multicolor/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "multicolor"
8
+ spec.version = Multicolor::VERSION
9
+ spec.authors = ["ramin keene"]
10
+ spec.email = ["raminkeene@gmail.com"]
11
+ spec.description = %q{ ruby api client for TinEye Multicolor API}
12
+ spec.summary = %q{ ruby api client for easy interaction with TinEye Multicolor API}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
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_dependency "faraday", "~> 0.8.9"
22
+ spec.add_dependency "faraday_middleware"
23
+ spec.add_dependency "activesupport"
24
+ spec.add_dependency "json", ">= 1.8.1"
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.3"
27
+ spec.add_development_dependency "codeclimate-test-reporter"
28
+ spec.add_development_dependency "guard-rspec"
29
+ spec.add_development_dependency "rake"
30
+ spec.add_development_dependency "rspec"
31
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Multicolor::Configuration do
4
+ describe '#timeout' do
5
+ it 'defaults to 40' do
6
+ expect(subject.timeout).to eq(40)
7
+ end
8
+
9
+ it 'sets timeout' do
10
+ subject.timeout = 20
11
+ expect(subject.timeout).to eq(20)
12
+ end
13
+ end
14
+
15
+ describe '#authenticate?' do
16
+ it 'is true' do
17
+ expect(subject.authenticate?).to eq(true)
18
+ end
19
+ end
20
+
21
+ describe '#open_timeout' do
22
+ it 'defaults to 40' do
23
+ expect(subject.open_timeout).to eq(40)
24
+ end
25
+
26
+ it 'sets open_timeout' do
27
+ subject.open_timeout = 20
28
+ expect(subject.open_timeout).to eq(20)
29
+ end
30
+ end
31
+ end
File without changes
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe Multicolor::REST::Client do
4
+ context 'delegation to transport' do
5
+ describe '.delegate' do
6
+ let(:delegated) {
7
+ [:get_search_metadata, :get_return_metadata,
8
+ :count, :list, :ping, :add, :delete, :get_metadata,
9
+ :update_metadata, :color_search,
10
+ :extract_collection_colors
11
+ ]
12
+ }
13
+
14
+ let(:transport) { double('Transport') }
15
+
16
+ before do
17
+ allow(Multicolor::REST::Transport).to receive(:new).and_return(transport)
18
+ end
19
+
20
+ it 'delegates' do
21
+ delegated.each do |method|
22
+ expect(transport).to receive(method)
23
+ expect(subject.respond_to?(:method)).to eq(true)
24
+ subject.send(method)
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ describe '#initialize' do
31
+ it 'yields self if block_given?' do
32
+ expect{ |block| Multicolor::REST::Client.new(&block) }.to yield_control
33
+ end
34
+ end
35
+
36
+ describe '#transport' do
37
+ it 'should initialize a transport object' do
38
+ expect(Multicolor::REST::Transport).to receive(:new)
39
+ subject.send(:transport)
40
+ end
41
+ end
42
+
43
+ describe '#config' do
44
+ it 'should initialize a configuration object' do
45
+ expect(Multicolor::Configuration).to receive(:new)
46
+ subject.config
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe Multicolor::REST::Endpoints::Filepath do
4
+ before do
5
+ class TransportClass
6
+ include Multicolor::REST::Endpoints::Filepath
7
+ end
8
+ end
9
+
10
+ subject{ TransportClass.new }
11
+
12
+ describe '#color_search' do
13
+ it 'makes a post request' do
14
+ expect(subject)
15
+ .to receive(:post)
16
+ .with(:color_search, {})
17
+ subject.send(:color_search, {})
18
+ end
19
+ end
20
+
21
+ describe '#extract_collection_colors' do
22
+ it 'makes a post request' do
23
+ expect(subject)
24
+ .to receive(:get)
25
+ .with(:extract_collection_colors, {})
26
+
27
+ subject.send(:extract_collection_colors, {})
28
+ end
29
+ end
30
+
31
+ describe '#get_metadata' do
32
+ it 'makes a get request' do
33
+ expect(subject)
34
+ .to receive(:get)
35
+ .with(:get_metadata, { "filepaths[0]" => "huh" })
36
+ subject.send(:get_metadata, { filepaths: ["huh"] })
37
+ end
38
+ end
39
+
40
+ describe '#update_metadata' do
41
+ it 'makes a post request' do
42
+ expect(subject)
43
+ .to receive(:post)
44
+ .with(:update_metadata, { })
45
+
46
+ subject.send(:update_metadata, [])
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Multicolor::REST::Endpoints::Indexing do
4
+ before do
5
+ class IndexingTransportClass
6
+ include Multicolor::REST::Endpoints::Indexing
7
+ end
8
+ end
9
+
10
+ subject{ IndexingTransportClass.new }
11
+
12
+ describe '#color_search' do
13
+ it 'makes a post request' do
14
+ expect(subject)
15
+ .to receive(:post)
16
+ .with(:add, {})
17
+
18
+ expect(Multicolor::Util)
19
+ .to receive(:payload_builder)
20
+ .with({})
21
+ .and_return({})
22
+
23
+ subject.send(:add, {})
24
+ end
25
+ end
26
+
27
+ describe '#extract_collection_colors' do
28
+ it 'makes a post request' do
29
+ expect(subject)
30
+ .to receive(:post)
31
+ .with(:delete, {})
32
+
33
+ expect(Multicolor::Util)
34
+ .to receive(:filepaths)
35
+ .with({})
36
+ .and_return({})
37
+
38
+ subject.send(:delete, {})
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ describe Multicolor::REST::Endpoints::Filepath do
4
+ before do
5
+ class TransportMetadataClass
6
+ include Multicolor::REST::Endpoints::Metadata
7
+ end
8
+ end
9
+
10
+ subject{ TransportMetadataClass.new }
11
+
12
+ describe '#count_collection_colors' do
13
+
14
+ let(:params) do
15
+ {
16
+ count_colors: [ "red", "green", "blue"],
17
+ colors: [
18
+ {
19
+ color: "huh",
20
+ weight: "20"
21
+ },
22
+ {
23
+ color: "nope",
24
+ weight: "30"
25
+ },
26
+ ]
27
+ }
28
+ end
29
+
30
+ it 'makes a get request' do
31
+ expect(subject)
32
+ .to receive(:get)
33
+ .with(:count_collection_colors, {})
34
+ subject.send(:count_collection_colors, {})
35
+ end
36
+ end
37
+
38
+ describe '#get_search_metadata' do
39
+ it 'makes a get request' do
40
+ expect(subject)
41
+ .to receive(:get)
42
+ .with(:get_search_metadata)
43
+ subject.send(:get_search_metadata)
44
+ end
45
+ end
46
+
47
+ describe '#get_return_metadata' do
48
+ it 'makes a get request' do
49
+ expect(subject)
50
+ .to receive(:get)
51
+ .with(:get_return_metadata)
52
+ subject.send(:get_return_metadata)
53
+ end
54
+ end
55
+
56
+ describe '#count' do
57
+ it 'makes a get request' do
58
+ expect(subject)
59
+ .to receive(:get)
60
+ .with(:count)
61
+ subject.send(:count)
62
+ end
63
+ end
64
+
65
+ describe '#list' do
66
+ it 'makes a get request' do
67
+ expect(subject)
68
+ .to receive(:get)
69
+ .with(:list, {})
70
+ subject.send(:list)
71
+ end
72
+ end
73
+
74
+ describe '#ping' do
75
+ it 'makes a get request' do
76
+ expect(subject)
77
+ .to receive(:get)
78
+ .with(:ping)
79
+ subject.send(:ping)
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ describe Multicolor::REST::SearchBuilder do
4
+ let(:keys) { [] }
5
+ let(:params) { {} }
6
+
7
+ let(:colors) {
8
+ [
9
+ {
10
+ color: "red",
11
+ weight: 50,
12
+ },
13
+ {
14
+ color: "blue",
15
+ },
16
+ {
17
+ color: "green",
18
+ weight: 70,
19
+ }
20
+ ]
21
+ }
22
+
23
+ subject { Multicolor::REST::SearchBuilder.new(params.with_indifferent_access, *keys) }
24
+ let(:request) { subject.request }
25
+
26
+ context 'filepath' do
27
+ let(:params) {
28
+ { filepath: "poop" }
29
+ }
30
+
31
+ it 'keeps filepath intact' do
32
+ expect(request["filepath"]).to eq("poop")
33
+ end
34
+ end
35
+
36
+ context 'param whitelist' do
37
+ let(:params) {
38
+ {
39
+ limit: 10,
40
+ offset: 20,
41
+ min_score: 100,
42
+ wu_tang: :killah_bees
43
+ }
44
+ }
45
+
46
+ it 'keeps whitelisted params and strips rest' do
47
+ expect(request.keys.count).to eq(4)
48
+ expect(request["wu_tang"]).to eq(nil)
49
+ end
50
+ end
51
+
52
+ context 'colors' do
53
+ let(:params) {
54
+ { colors: colors }.stringify_keys
55
+ }
56
+
57
+ it 'formats colors into array indexes colors and weight' do
58
+ expect(request["colors[0]"]).to eq("red")
59
+ expect(request["colors[1]"]).to eq("blue")
60
+ expect(request["colors[2]"]).to eq("green")
61
+ end
62
+
63
+ it 'formats colors into array indexes colors and weight' do
64
+ expect(request["weights[0]"]).to eq(50)
65
+ expect(request["weights[1]"]).to eq(nil)
66
+ expect(request["weights[2]"]).to eq(70)
67
+ end
68
+
69
+ it 'skips adding a weight for the second color' do
70
+ expect(request.keys.count).to eq(6)
71
+ expect(request["weights[1]"]).to eq(nil)
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe Multicolor::REST::Transport do
4
+ let(:config) { Multicolor::Configuration.new }
5
+ subject { Multicolor::REST::Transport.new(config) }
6
+
7
+ context 'request helpers' do
8
+ let(:client) { double("Client") }
9
+
10
+ before do
11
+ allow(Faraday).to receive(:new).and_return(client)
12
+ expect(subject).to receive(:api_path).and_return("/something")
13
+ end
14
+
15
+ describe '#get' do
16
+ it 'should proxy get to the initialized Faraday client' do
17
+ expect(client).to receive(:get).with("/something", {})
18
+ subject.send(:get, "/something", {})
19
+ end
20
+ end
21
+
22
+ describe '#post' do
23
+ it 'should proxy get to the initialized Faraday client' do
24
+ expect(client).to receive(:post).with("/something", {})
25
+ subject.send(:post, "/something", {})
26
+ end
27
+ end
28
+ end
29
+
30
+ describe '#api_path' do
31
+ context 'when no company has been configured' do
32
+ it 'should raise an error' do
33
+ expect{ subject.send(:api_path, "poop") }
34
+ .to raise_error(Multicolor::Errors::CompanyNotSet)
35
+ end
36
+ end
37
+ end
38
+
39
+ it 'sets the url to point at tineye multicolor' do
40
+ expect(subject.send(:url)).to eq("http://multicolorengine.tineye.com")
41
+ end
42
+ end
@@ -0,0 +1,128 @@
1
+ require 'spec_helper'
2
+
3
+ describe Multicolor::Util do
4
+ subject { Multicolor::Util }
5
+
6
+ let(:params) do
7
+ { poop: "haha", filepaths: [:first, :second, :third] }
8
+ end
9
+
10
+ let(:output) {
11
+ {
12
+ "filepaths[0]" => :first,
13
+ "filepaths[1]" => :second,
14
+ "filepaths[2]" => :third
15
+ }
16
+ }
17
+
18
+ describe '.param_builder' do
19
+ it 'builds filepath params' do
20
+ expect(subject.param_builder(params)).to eq(output)
21
+ end
22
+ end
23
+
24
+ describe '.filepaths' do
25
+ it 'formats a single filepath' do
26
+ expect(subject.filepaths("whatever")).to eq({ "filepaths[0]" => "whatever" })
27
+ end
28
+
29
+ it 'formats an list (array) of filepaths' do
30
+ expect(subject.filepaths(params[:filepaths])).to eq(output)
31
+ end
32
+ end
33
+
34
+ context 'colors via ajax' do
35
+ let(:data) {
36
+ {
37
+ "0" => {
38
+ "color" => "red",
39
+ "weight" => "23"
40
+ }
41
+ }
42
+ }
43
+
44
+ describe '.flatten_colors' do
45
+ it 'should turn a ajax encoded colors hash back to an array' do
46
+ expect(subject.flatten_colors(data)).to eq([ { "color" => "red", "weight" => "23" } ])
47
+ end
48
+
49
+ it 'leaves properly formatted data alone' do
50
+ safe_data = [{ "color" => "red" }]
51
+ expect(subject.flatten_colors(safe_data)).to eq(safe_data)
52
+ end
53
+ end
54
+
55
+ describe '.build_colors' do
56
+ let(:output) { { "colors[0]" => "red", "weights[0]" => "23" } }
57
+
58
+ it 'flattens the processed hash and encodes as API params' do
59
+ expect(subject.build_colors(data)).to eq(output)
60
+ end
61
+ end
62
+ end
63
+
64
+ context 'payload builder' do
65
+ let(:entry) {
66
+ {
67
+ "filepath" => "poop",
68
+ "url" => "http://url.com",
69
+ "metadata" => {
70
+ "keywords" => [:huh, :hee],
71
+ "post_id" => { "action" => "return", "type" => "uint", "" => rand(0..45) }
72
+ }
73
+ }
74
+ }
75
+
76
+ let(:payload) { [entry, entry, entry] }
77
+
78
+ describe '.payload_builder' do
79
+ it 'transforms an array of hashes into array indexed param parts' do
80
+ output = subject.payload_builder(payload)
81
+
82
+ expect(output.keys.count).to eq(9)
83
+
84
+ expect(output["filepaths[0]"]).to_not eq(nil)
85
+ expect(output["filepaths[1]"]).to_not eq(nil)
86
+ expect(output["filepaths[2]"]).to_not eq(nil)
87
+
88
+ expect(output["urls[0]"]).to_not eq(nil)
89
+ expect(output["urls[1]"]).to_not eq(nil)
90
+ expect(output["urls[2]"]).to_not eq(nil)
91
+
92
+ expect(output["metadata[0]"]).to_not eq(nil)
93
+ expect(output["metadata[1]"]).to_not eq(nil)
94
+ expect(output["metadata[2]"]).to_not eq(nil)
95
+ end
96
+ end
97
+
98
+ describe '.modify_options_for_keys' do
99
+ let(:data) do
100
+ {
101
+ other: [1, 4],
102
+ things: [1, 2],
103
+ cant_touch: :this,
104
+ please_hammer: :dont_hurt_em,
105
+ colors: [
106
+ {
107
+ color: "huh",
108
+ weight: "20"
109
+ },
110
+ {
111
+ color: "nope",
112
+ weight: "30"
113
+ },
114
+ ]
115
+ }
116
+ end
117
+
118
+ let(:modifiable_keys) { [:other, :things, :colors] }
119
+
120
+ it 'transforms a hash of arrays into array indexed param parts for specified keys' do
121
+ transformed = subject.modify_options_for_keys(data, modifiable_keys)
122
+ expect((transformed.keys & modifiable_keys).count).to eq(0)
123
+ expect((transformed.keys & ["things[0]", "things[1]"]).count).to eq(2)
124
+ expect((transformed.keys & ["others[0]", "others[1]"]).count).to eq(2)
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,10 @@
1
+ require "codeclimate-test-reporter"
2
+ CodeClimate::TestReporter.start
3
+
4
+ require 'active_support'
5
+ require 'multicolor'
6
+
7
+ RSpec.configure do |config|
8
+ config.mock_with :rspec
9
+ config.color = true
10
+ end
metadata ADDED
@@ -0,0 +1,211 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: multicolor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - ramin keene
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.8.9
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.8.9
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday_middleware
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: json
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 1.8.1
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 1.8.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.3'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: codeclimate-test-reporter
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: guard-rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: " ruby api client for TinEye Multicolor API"
140
+ email:
141
+ - raminkeene@gmail.com
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ".gitignore"
147
+ - Gemfile
148
+ - Guardfile
149
+ - LICENSE.txt
150
+ - README.md
151
+ - Rakefile
152
+ - lib/multicolor.rb
153
+ - lib/multicolor/configuration.rb
154
+ - lib/multicolor/errors/bad_response.rb
155
+ - lib/multicolor/errors/company_not_set.rb
156
+ - lib/multicolor/rest.rb
157
+ - lib/multicolor/rest/client.rb
158
+ - lib/multicolor/rest/endpoints.rb
159
+ - lib/multicolor/rest/endpoints/filepath.rb
160
+ - lib/multicolor/rest/endpoints/indexing.rb
161
+ - lib/multicolor/rest/endpoints/metadata.rb
162
+ - lib/multicolor/rest/search_builder.rb
163
+ - lib/multicolor/rest/transport.rb
164
+ - lib/multicolor/util.rb
165
+ - lib/multicolor/version.rb
166
+ - multicolor.gemspec
167
+ - spec/multicolor/configuration_spec.rb
168
+ - spec/multicolor/errors_spec.rb
169
+ - spec/multicolor/rest/client_spec.rb
170
+ - spec/multicolor/rest/endpoints/filepath_spec.rb
171
+ - spec/multicolor/rest/endpoints/indexing_spec.rb
172
+ - spec/multicolor/rest/endpoints/metadata_spec.rb
173
+ - spec/multicolor/rest/search_builder_spec.rb
174
+ - spec/multicolor/rest/transport_spec.rb
175
+ - spec/multicolor/util_spec.rb
176
+ - spec/spec_helper.rb
177
+ homepage: ''
178
+ licenses:
179
+ - MIT
180
+ metadata: {}
181
+ post_install_message:
182
+ rdoc_options: []
183
+ require_paths:
184
+ - lib
185
+ required_ruby_version: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - ">="
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ required_rubygems_version: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ requirements: []
196
+ rubyforge_project:
197
+ rubygems_version: 2.2.2
198
+ signing_key:
199
+ specification_version: 4
200
+ summary: ruby api client for easy interaction with TinEye Multicolor API
201
+ test_files:
202
+ - spec/multicolor/configuration_spec.rb
203
+ - spec/multicolor/errors_spec.rb
204
+ - spec/multicolor/rest/client_spec.rb
205
+ - spec/multicolor/rest/endpoints/filepath_spec.rb
206
+ - spec/multicolor/rest/endpoints/indexing_spec.rb
207
+ - spec/multicolor/rest/endpoints/metadata_spec.rb
208
+ - spec/multicolor/rest/search_builder_spec.rb
209
+ - spec/multicolor/rest/transport_spec.rb
210
+ - spec/multicolor/util_spec.rb
211
+ - spec/spec_helper.rb