2011-09-30 70 views
0

对于Ruby 1.9.2,我使用class_eval来扩展类。从class_eval'ed方法返回数组时出现的奇怪行为

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 

此只要能正常工作作为字段是符号(例如后slugged :nameslug_fields:name返回)。

但是,调用slugged以与阵列使得slug_fieldsnil返回(例如后slugged [:kicker, :headline]slug_fieldsnil返回)。

奇怪的是,调试slugged时,含待创建方法的字符串看起来完全相同的方式,你会期望他们:

"   def slug_fields\n   [:kicker, :headline]\n   end\n" 
"   def slug_fields\n   :name\n   end\n" 

编辑:根据要求,对什么打破了更完整版我:

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) 
+0

确实很奇怪。你有尝试过使用'class_exec'吗? http://ruby-doc.org/core-1.8.7/classes/Module.html#M000187 –

回答

1

您的代码工作正常,我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]" 

你能否提供一个完整的,可运行的,独立的测试用例,为你打破?

+0

谢谢,您的版本也适用于我,这让我更想知道我在哪里做了些什么Rails不喜欢的事情。 我更新了原始问题,但恐怕我无法提供可运行的独立测试用例。 –