Ruby-对当前类的作用域方法调用



在我们正在构建的当前Rails应用程序上,用户可以有公司范围的偏好、用户特定的偏好或项目特定的偏好。当用户创建采购订单时,我需要聚合所有这些首选项,并在订单上设置相应的属性。我从"项目首选项"开始,一直向上遍历层次结构,直到收集到以下所有属性。

  class Preferences 
    def initialize(project, user)
      @preferences = Preferences.new
      @project = project
      @user = user
    end
    def stage
    end
    def set_preferences
      set_department
    end
  End

  class UserPreferences < Preferences
    def initialize(project, user)
     super(project, user)
     @user_preferences = nil
    end
    def stage
     @user_preferences = @user.preferences
     set_preferences if @user_preferences.present?
     super unless @preferences.valid?
    end 

    def set_department
     @preferences ||= @user_preferences.dept
    end
  end
  class ProjectPreferences < UserPreferences
    def initialize(project, user)
     super(project, user)
     @project_preferences = nil
    end
    def stage
     @project_preferences = @project.preferences
     set_preferences if @project_preferences.present?
     super unless @preferences.valid?
    end 
    def set_department
      @preferences.dept ||= @project_preferences.dept
    end
  end
  def StagePreferences < ProjectPreferences
    def initialize(project, user)
     super(project, user)
    end
   def stage
     super
     @preferences
   end
  end

该方法的调用方式如下

StagePreferences.new(project, current_user).stage

我遇到了一个问题,当我从UserPreferences类调用set_preferences方法时(因为没有为此项目设置首选项),会调用UserPreferences的set_department,返回如下错误?

NoMethodError: undefined method `dept' for nil:NilClass
from /home/rails/tools/ss/lib/preferences/project_preferences.rb:27:in `set_department'
from /home/rails/tools/ss/lib/preferences/preferences.rb:26:in `set_preferences'
from /home/rails/tools/ss/lib/preferences/user_preferences.rb:17:in `stage'
from /home/rails/tools/ss/lib/preferences/stage_preferences.rb:23:in `stage'
from /home/rails/tools/ss/lib/preferences/project_preferences.rb:17:in `stage'
from /home/rails/tools/ss/lib/preferences/stage_preferences.rb:8:in `stage'
from (irb):8
from /home/rails/.rvm/gems/ruby-2.2.1/gems/railties-4.0.13/lib/rails/commands/console.rb:90:in `start'
from /home/rails/.rvm/gems/ruby-2.2.1/gems/railties-4.0.13/lib/rails/commands/console.rb:9:in `start'
from /home/rails/.rvm/gems/ruby-2.2.1/gems/railties-4.0.13/lib/rails/commands.rb:62:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'

Ruby的动态调度使用了对接收器上的方法的"深度优先"搜索,这意味着你的ProjectPreferences#set_department方法将始终被调用,而你的"UserPreferences#set_department"方法永远不会被调用(仅供参考,看起来你在这个方法中有拼写错误?)。

可以在当前层次结构中使用Ruby的instance_method方法通过:调用此方法

UserPreferences.instance_method(:set_department).bind(self).call

这允许你在self上调用这个"不可访问"的方法,就好像ProjectPreferences没有覆盖它一样

然而,我会质疑拥有这么多Preference子类的要求,正如这个问题所强调的那样,类层次结构中的调试问题变得越来越复杂。

相关内容

  • 没有找到相关文章

最新更新