【问题标题】:Strange behaviour when returning an array from class_eval'ed method从 class_eval 方法返回数组时的奇怪行为
【发布时间】:2011-09-30 15:08:13
【问题描述】:

在 Ruby 1.9.2 中,我使用 class_eval 来扩展一个类。

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 :name 之后,slug_fields 返回:name)。

但是,使用数组调用slugged 会使slug_fields 返回nil(例如,在slugged [:kicker, :headline] 之后,slug_fields 返回nil)。

奇怪的是,在调试 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)

【问题讨论】:

标签: ruby-on-rails ruby activerecord


【解决方案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]"

您能否提供一个完整的、可运行的、独立的测试用例,对您不利?

【讨论】:

  • 谢谢你,你的版本也适用于我,这让我更加想知道我在哪里做了 Rails 不喜欢的事情。我更新了原始问题,但恐怕我无法提供可运行的独立测试用例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-12
  • 2019-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多