Permalink
Browse files

Skip stripping of blob columns in the string_stripper plugin (Fixes #593

)

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...
1 parent 8b670b0 commit 86458c35bfb66647d3beb912b4b1dbaa6d72ed78 @jeremyevans committed Dec 13, 2012
Showing with 99 additions and 5 deletions.
  1. +2 −0 CHANGELOG
  2. +53 −3 lib/sequel/plugins/string_stripper.rb
  3. +44 −2 spec/extensions/string_stripper_spec.rb
View
2 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)
View
56 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:
#
@@ -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
View
46 spec/extensions/string_stripper_spec.rb
@@ -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
@@ -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.