代码之家  ›  专栏  ›  技术社区  ›  dav

愚蠢的Rails问题:类声明中的未定义方法

  •  3
  • dav  · 技术社区  · 15 年前

    我有一个用户类,在那里我试图附加一个由工厂创建的配置文件。这是课程:

    class User < ActiveRecord::Base
      acts_as_authentic
      has_one :profile
    
      after_create {self.profile = ProfileFactory.create_profile(self.role)}
    
    end
    

    工厂看起来像这样

    class ProfileFactory
        def self.create_profile(role)
          String s = "#{role}#{"Profile"}"
          Object.const_get(s).new
        end
    end
    

    出于某种原因,它无法将自己识别为用户。这是我在进行profileFactory.create_profile调用时遇到的错误。

    未定义的方法“role” #<Class:0x2304218>

    用户对象在其迁移中声明了一个role:string。

    感谢您的帮助。

    3 回复  |  直到 15 年前
        1
  •  1
  •   Duncan Beevers    15 年前

    这个 User 将有问题的对象传递给 after_create 块作为参数。

    class User < ActiveRecord::Base
      after_create do |user|
        user.profile = ProfileFactory.create_profile(user.role)
        user.save
      end
    end
    
        2
  •  6
  •   EmFi    15 年前

    邓肯用你的工厂作回拨得到了正确的答案。但这可能有助于你了解出了什么问题。

    类方法将类作为自身接收,实例方法将实例作为自身接收。当您向任何方法提供块时,调用方法的作用域将用于该块。

    创建后是一个类方法,它将回调添加到提供的块或作为参数列出的方法中。提供给回调的块(创建后、保存前等)在类方法的上下文中解释。所以self不是指正在创建的对象,而是指正在创建的对象的类。

    在这段代码中:

      after_create {self.profile = ProfileFactory.create_profile(self.role)}
    

    self是用户类,不是您所期望的用户类的实例。

    与Matt暗示的更传统的after-create语法相比,后者将实例方法添加到回调链中。在此上下文中,self引用实例。

    class User < ActiveRecord::Base
      has_one :profile
      after_create :add_profile
    
      protected
    
        def add_profile
          self.profile = ProfileFactory.create_profile(role)
        end
    end
    

    EMFI,这很有道理。所以 只是为了澄清,当调用方法时 在课堂上 回调方法,但实际不在 回调方法之一,允许我们 绕过这个类方法 问题,是否使用当前实例?

    是的,但不是因为你想的原因。回调只在传递符号时查找实例方法。

    相反,您找到了一种解决实例方法问题的方法。不能给回调一个类方法,但可以给它提供一个在其中调用方法的块。我想您也可以定义一个调用类方法的实例方法,但这似乎有点倒退。

        3
  •  1
  •   Matt Darby    15 年前

    为什么不做一些更简单的事情呢?类似:

    class User < ActiveRecord::Base
      has_one :profile
      after_create :add_profile
    
      protected
    
        def add_profile
          self.create_profile(:role => self.role)
        end
    end
    
    class Profile < ActiveRecord::Base
      belongs_to :user
    
    end
    

    你来自Java后台吗?