Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/mutations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
require 'mutations/model_filter'
require 'mutations/array_filter'
require 'mutations/hash_filter'
require 'mutations/uri_filter'
require 'mutations/outcome'
require 'mutations/command'

Expand Down
45 changes: 45 additions & 0 deletions lib/mutations/uri_filter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
require 'uri'

module Mutations
class UriFilter < AdditionalFilter
@default_options = {
:nils => false, # true allows an explicit nil to be valid. Overrides any other options
:scheme => nil, # restrict the URI to a specific scheme, i.e. 'https'
}

def filter(data)
if data.nil?
return [nil, nil] if options[:nils]
return [nil, :nils]
end

case data
when URI # we're good!
when String then
return [nil, :blank] if blank?(data)
begin
data = URI.parse(data)
rescue StandardError => e
return [nil, e.message]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@estraph The filter operation always starts from the HashFilter and from there it will filter the nested input. The results of the nested filter will always flow back to HashFilter.

What I can see is all basic filter like StringFilter, FloatFilter and etc always return Array<Object, Symbol> in #filter. Are you sure returning e.message here will be handled gracefully by the error handler?

I think you might see the issue if you write a rspec with a Mutation::Commands that will trigger error on this filter.

end
else return [nil, :invalid]
end

if !options[:scheme].nil?
return [nil, :scheme] if blank?(data.scheme)
return [nil, :scheme] if data.scheme.to_sym != options[:scheme]
end

[data, nil]
end

private

def blank?(value)
return true if value.nil?
value = value.strip if value.is_a?(String)
return value.empty? if value.respond_to?(:empty?)
return false
end
end
end
153 changes: 153 additions & 0 deletions spec/uri_filter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
require 'spec_helper'

describe Mutations::UriFilter do
let(:options){ {} }
let(:outcome){ Mutations::UriFilter.new(options).filter(input) }
let(:result){ outcome[0] }
let(:errors){ outcome[1] }

describe "#blank" do
subject{ Mutations::UriFilter.new.send(:blank?, value) }

describe "nil" do
let(:value){ nil }
it{ assert(subject) }
end

describe "empty string" do
let(:value){ "" }
it{ assert(subject) }
end

describe "whitespace" do
let(:value){ " " }
it{ assert(subject) }
end

describe "some text" do
let(:value){ "abc" }
it{ assert(!subject) }
end
end

describe 'invalid type input' do
let(:input){ true }

it{ assert_nil(result) }
it{ assert_equal(errors, :invalid) }
end

describe 'string input' do
let(:input){ 'http://www.altavista.com' }

describe 'is blank' do
let(:input){ '' }

it{ assert_nil(result) }
it{ assert_equal(errors, :blank) }
end

describe 'invalid uri' do
let(:input){ 'oops' }

it "returns the error" do
URI.stub :parse, lambda {|x| raise 'invalid URI'} do
assert_nil(result)
assert_equal(errors, 'invalid URI')
end
end
end

describe 'with scheme constraint' do

describe 'matching constraint' do
let(:options){ { scheme: :http } }

it{ assert_equal(result, URI.parse(input)) }
it{ assert_nil(errors) }
end

describe 'not matching constraint' do
let(:options){ { scheme: :https} }

it{ assert_nil(result) }
it{ assert_equal(errors, :scheme) }
end

describe 'and blank url scheme' do
let(:options){ { scheme: :http} }
let(:input){ 'altavista.com' }

it{ assert_nil(result) }
it{ assert_equal(errors, :scheme) }
end
end

describe 'without scheme constraint' do
describe 'and blank url scheme' do
let(:input){ 'altavista.com' }

it{ assert_equal(result, URI.parse(input)) }
it{ assert_nil(errors) }
end
end

end

describe 'uri input' do
let(:input){ URI.parse('http://www.altavista.com') }

describe 'with scheme constraint' do
describe 'matching constraint' do
let(:options){ { scheme: :http } }

it{ assert_equal(result, input) }
it{ assert_nil(errors) }
end

describe 'not matching constraint' do
let(:options){ { scheme: :https} }

it{ assert_nil(result) }
it{ assert_equal(errors, :scheme) }
end

describe 'and blank url scheme' do
let(:options){ { scheme: :http} }
let(:input){ URI.parse('altavista.com') }

it{ assert_nil(result) }
it{ assert_equal(errors, :scheme) }
end
end

describe 'without scheme constraint' do
describe 'and blank url scheme' do
let(:input){ URI.parse('altavista.com') }

it{ assert_equal(result, input) }
it{ assert_nil(errors) }
end
end

end

describe 'nil input' do
let(:input){ nil }

describe 'nils allowed' do
let(:options){ { nils: true } }

it{ assert_nil(result) }
it{ assert_nil(errors) }
end

describe 'nils not allowed' do
let(:options){ { nils: false } }

it{ assert_nil(result) }
it{ assert_equal(errors, :nils) }
end

end
end