diff --git a/lib/cloudinary/api.rb b/lib/cloudinary/api.rb index 03122d83..93c06ea9 100644 --- a/lib/cloudinary/api.rb +++ b/lib/cloudinary/api.rb @@ -207,6 +207,19 @@ def self.resources_by_asset_folder(asset_folder, options={}) call_api(:get, uri, params, options) end + # Find images based on their visual content. + # + # @param [Hash] options The optional parameters. + # + # @return [Cloudinary::Api::Response] + # + # @raise [Cloudinary::Api::Error] + def self.visual_search(options = {}) + uri = "resources/visual_search" + params = only(options, :image_url, :image_asset_id, :text) + call_api(:get, uri, params, options) + end + # Returns the details of the specified asset and all its derived assets. # # Note that if you only need details about the original asset, diff --git a/lib/cloudinary/uploader.rb b/lib/cloudinary/uploader.rb index a11407d3..047b00cd 100644 --- a/lib/cloudinary/uploader.rb +++ b/lib/cloudinary/uploader.rb @@ -63,6 +63,7 @@ def self.build_upload_params(options) :responsive_breakpoints => Cloudinary::Utils.generate_responsive_breakpoints_string(options[:responsive_breakpoints]), :return_delete_token => Cloudinary::Utils.as_safe_bool(options[:return_delete_token]), :similarity_search => options[:similarity_search], + :visual_search => Cloudinary::Utils.as_safe_bool(options[:visual_search]), :tags => options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(","), :timestamp => (options[:timestamp] || Time.now.to_i), :transformation => Cloudinary::Utils.generate_transformation_string(options.clone), diff --git a/spec/api_spec.rb b/spec/api_spec.rb index 5e7a27a7..c3c07d74 100644 --- a/spec/api_spec.rb +++ b/spec/api_spec.rb @@ -151,6 +151,16 @@ @api.resources(:type=>"upload", :start_at=>start_at, :direction => "asc") end + it "should allow visual search" do + expected = { + :url => /.*\/resources\/visual_search$/, + :method => :get, + :payload => { :image_url => TEST_IMAGE_URL, :image_asset_id => test_asset_id, :text => "sample image" }, + } + expect(RestClient::Request).to receive(:execute).with(deep_hash_value(expected)) + @api.visual_search({ "image_url" => TEST_IMAGE_URL, "image_asset_id" => test_asset_id, "text" => "sample image" }) + end + describe "structured metadata" do matcher :have_metadata do match do |expected| diff --git a/spec/utils_spec.rb b/spec/utils_spec.rb index 3c85a26d..1da9a978 100644 --- a/spec/utils_spec.rb +++ b/spec/utils_spec.rb @@ -807,7 +807,9 @@ it "build_upload_params canonize booleans" do options = { :backup => true, :use_filename => false, :colors => :true, - :image_metadata => :false, :media_metadata => true, :invalidate => 1 } + :image_metadata => :false, :media_metadata => true, :invalidate => 1, + :visual_search => true, + } params = Cloudinary::Uploader.build_upload_params(options) expect(Cloudinary::Api.only(params, *options.keys)) .to eq(:backup => 1, @@ -815,7 +817,8 @@ :colors => 1, :image_metadata => 0, :media_metadata => 1, - :invalidate => 1 + :invalidate => 1, + :visual_search => 1, ) options = { :colors => "true", :exif => "false", :eager_async => "1", :media_metadata => true } params = Cloudinary::Uploader.build_upload_params(options)