Strange behaviour when returning an array from class_eval'ed method
With Ruby 1.9.2, I'm using class_eval to extend a class.
def slugged(fields)
# assign string to variable only for easier debugging
method = <<-EOS
def slug_fields
#{ fields.is_a?(Array) ? fields.inspect : ":#{ fields }" }
end
EOS
class_eval method
end
This works fine as long as fields is a symbol (e.g. after slugged :name
, slug_fields
returns :name
).
However, calling slugged
with an array makes slug_fields
returns nil
(e.g. after slugged [:kicker, :headline]
, slug_fields
returns nil
).
Strangely, when debugging slugged
, the string containing the to-be-created method looks exactly the way you would expect them to:
" def slug_fields\n [:kicker, :headline]\n end\n"
" def slug_fields\n :name\n end\n"开发者_如何学Python
edit: as requested, a more complete version of what breaks for me:
module Extensions
module Slugged
extend ActiveSupport::Concern
included do
before_validation { |record| record.slug ||= record.sluggerize }
end
module ClassMethods
def slugged(fields)
# assign string to variable only for easier debugging
method = <<-EOS
def slug_fields
#{ fields.is_a?(Array) ? fields.inspect : ":#{ fields }" }
end
EOS
class_eval method
end
end
module InstanceMethods
def sluggerize
fields = slug_fields
slug_string = case
when fields.is_a?(Array)
fields.map { |f| self.send(f) }.join('-')
else
self.send fields
end
slug_string.parameterize
end
end
end
end
class Article < ActiveRecord::Base
include Extensions::Slugged
slugged [:kicker, :headline]
end
class Station < ActiveRecord::Base
include Extensions::Slugged
slugged :name
end
a = Article.new :headline => "this is a great headline!", :kicker => "attention-drawing kicker"
a.save # works, slug is set
s = Station.new :name => "Great Music"
s.save # TypeError: nil is not a symbol (in sluggerize where "self.send fields" is called)
Your code works fine for me under 1.9.2:
class Foo
class << self
def slugged(fields)
method = <<-EOS
def slug_fields
#{ fields.is_a?(Array) ? fields.inspect : ":#{ fields }" }
end
EOS
class_eval method
end
end
end
Foo.slugged :a
p Foo.new.slug_fields
#=> :a
Foo.slugged [:a,:b]
p Foo.new.slug_fields
#=> [:a, :b]
p RUBY_DESCRIPTION
#=> "ruby 1.9.2p180 (2011-02-18) [i386-mingw32]"
Can you please provide a complete, runnable, standalone test case that breaks for you?
精彩评论