Skip to content

Commit

Permalink
Skip stripping of blob columns in the string_stripper plugin (Fixes #593
Browse files Browse the repository at this point in the history
)

In addition to handling blob columns/values, this also allows
you to arbitrarily skip stripping of certain columns via
Model.skip_string_stripping.
  • Loading branch information
jeremyevans committed Dec 13, 2012
1 parent 8b670b0 commit 86458c3
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG
@@ -1,5 +1,7 @@
=== HEAD

* Skip stripping of blob columns in the string_stripper plugin (jeremyevans) (#593)

* Allow Database#get to take an array to return multiple values, similar to map/select_map (jeremyevans)

* Default :prefetch_rows to 100 in the Oracle adapter (andrewhr) (#592)
Expand Down
56 changes: 53 additions & 3 deletions lib/sequel/plugins/string_stripper.rb
@@ -1,10 +1,18 @@
module Sequel
module Plugins
# StringStripper is a very simple plugin that strips all input strings
# StringStripper is a plugin that strips all input strings
# when assigning to the model's values. Example:
#
# album = Album.new(:name=>' A ')
# album.name # => 'A'
#
# SQL::Blob instances and all non-strings are not modified by
# this plugin. Additionally, strings passed to a blob column
# setter are also not modified. You can explicitly set
# other columns to skip the stripping:
#
# Album.skip_string_stripping :foo
# Album.new(:foo=>' A ').foo # => ' A '
#
# Usage:
#
Expand All @@ -14,11 +22,53 @@ module Plugins
# # Make the Album class strip strings
# Album.plugin :string_stripper
module StringStripper
# Set blob columns as skipping stripping when plugin is loaded.
def self.configure(model)
model.instance_variable_set(:@skipped_string_stripping_columns, [])
model.send(:set_skipped_string_stripping_columns)
end

module ClassMethods
# Copy skipped stripping columns from superclass into subclass.
def inherited(subclass)
subclass.instance_variable_set(:@skipped_string_stripping_columns, @skipped_string_stripping_columns.dup)
super
end

# Set blob columns as skipping stripping when plugin is loaded.
def set_dataset(*)
super
set_skipped_string_stripping_columns
end

# Skip stripping for the given columns.
def skip_string_stripping(*columns)
@skipped_string_stripping_columns.concat(columns).uniq!
end

# Return true if the column should not have values stripped.
def skip_string_stripping?(column)
@skipped_string_stripping_columns.include?(column)
end

private

# Automatically skip stripping of blob columns
def set_skipped_string_stripping_columns
if @db_schema
blob_columns = @db_schema.map{|k,v| k if v[:type] == :blob}.compact
skip_string_stripping(*blob_columns)
end
end
end

module InstanceMethods
# Strip value if it is a string, before attempting to assign
# Strip value if it is a non-blob string and the model hasn't been set
# to skip stripping for the column, before attempting to assign
# it to the model's values.
def []=(k, v)
v.is_a?(String) ? super(k, v.strip) : super
v = v.strip if v.is_a?(String) && !v.is_a?(SQL::Blob) && !model.skip_string_stripping?(k)
super(k, v)
end
end
end
Expand Down
46 changes: 44 additions & 2 deletions spec/extensions/string_stripper_spec.rb
Expand Up @@ -3,9 +3,10 @@
describe "Sequel::Plugins::StringStripper" do
before do
@db = Sequel::Database.new
@c = Class.new(Sequel::Model(@db))
@c = Class.new(Sequel::Model(@db[:test]))
@c.columns :name, :b
@c.db_schema[:b][:type] = :blob
@c.plugin :string_stripper
@c.columns :name
@o = @c.new
end

Expand All @@ -20,4 +21,45 @@
@o.name = Date.today
@o.name.should == Date.today
end

it "should not strip strings for blob arguments" do
v = Sequel.blob(' name ')
@o.name = v
@o.name.should equal(v)
end

it "should not strip strings for blob columns" do
@o.b = ' name '
@o.b.should be_a_kind_of(Sequel::SQL::Blob)
@o.b.should == Sequel.blob(' name ')
end

it "should allow skipping of columns using Model.skip_string_stripping" do
@c.skip_string_stripping :name
v = ' name '
@o.name = v
@o.name.should equal(v)
end

it "should work correctly in subclasses" do
o = Class.new(@c).new
o.name = ' name '
o.name.should == 'name'
o.b = ' name '
o.b.should be_a_kind_of(Sequel::SQL::Blob)
o.b.should == Sequel.blob(' name ')
end

it "should work correctly for dataset changes" do
c = Class.new(Sequel::Model(@db[:test]))
c.plugin :string_stripper
def @db.schema(*) [[:name, {}], [:b, {:type=>:blob}]] end
c.set_dataset(@db[:test2])
o = c.new
o.name = ' name '
o.name.should == 'name'
o.b = ' name '
o.b.should be_a_kind_of(Sequel::SQL::Blob)
o.b.should == Sequel.blob(' name ')
end
end

0 comments on commit 86458c3

Please sign in to comment.