Ruby,Rails和别名 - 堆栈太深的问题

时间:2011-07-24 15:03:38

标签: ruby-on-rails ruby rspec factory-bot aliasing

我的问题是在测试环境中调用旧的别名方法。可能只有工厂女孩

应用程序/模型/ user.rb

class User < ActiveRecord::Base
  ...
  include Authentication
  include Authentication::ByPassword
  ...

  attr_accessor :skip_password_validations

  alias old_password_required? password_required?
  # alias_method :old_password_required?, :password_required?
  def password_required?
    return false if !!skip_password_validations
    old_password_required?
  end

  # def password_required_with_skip_validations?
  #   return false if !!skip_password_validations
  #   password_required_without_skip_validations?
  # end
  # alias_method_chain :password_required?, :skip_validations  
end

供应商/插件/../ by_password.rb

module Authentication
  module ByPassword
    # Stuff directives into including module
    def self.included(recipient)
      recipient.class_eval do
        include ModelInstanceMethods
        attr_accessor :password
        validates_presence_of :password, :if => :password_required?
      end
    end # #included directives

    module ModelInstanceMethods 
      def password_required?
        crypted_password.blank? || !password.blank?
      end
    end # instance methods
  end
end

规格/模型/ user_spec.rb

describe User do
    it 'test' do
      @user = Factory(:user)
      @user.should be_valid
    end
 end

规格/工厂/ user_factories.rb

FactoryGirl.define do
  factory :user do |u|
    u.sequence(:email) { |n| "login#{n}@example.com" }
    u.password 'qwertz123'
    u.password_confirmation 'qwertz123'
  end
end

结果是

1) User test
     Failure/Error: Unable to find matching line from backtrace
     SystemStackError:
       stack level too deep
     # /Users/schovi/.rvm/gems/ruby-1.9.2-p180/gems/activerecord-3.1.0.rc4/lib/active_record/connection_adapters/abstract/database_statements.rb:197

当我使用调试器gem调试它时,我发现方法old_password_required?指向password_required?中的新方法user.rb而不是vendor/plugins/../by_password.rb

使用alias, alias_method or alias_method_chain

获得相同的结果

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

我的观点是:在Ruby中使用alias通常是痛苦的屁股。那么如何将password_required?移动到自己的模块中并在其中调用super,从password_required?调用Authentication::ByPassword::ModelInstanceMethods,如下所示:

class User < ActiveRecord::Base
  module PasswordRequired
    def password_required?
      return false if !!skip_password_validations
      super # Is going to call Authentication's password_required?
    end
  end

  include Authentication
  include Authentication::ByPassword
  include PasswordRequired

  ...

end