ruby-on-rails - 如何将Rails模型记录与代码关联?

标签 ruby-on-rails ruby models

如果我有一个类似任务(比如在游戏中)的 Rails 模型,我会有名称、描述等属性。但我还需要一些与每个任务相关的代码来确定玩家是否满足完成任务的要求。

将某些代码与模型中的记录关联起来的最佳方法是什么?当我创建新任务时,是否应该在模型中创建 quest_function 属性并为 models/quest.rb 文件中的每条记录编写一个函数?这看起来很笨重并且容易出错。

在 Rails 中应该如何完成这样的事情?

最佳答案

嗯,你有几个选择。

正如您所说,第一个是将方法/函数名称存储在您的记录中,然后在您需要评估该记录的任务是否已完成时调用该方法。粗略代码:

class Quest < ActiveRecord::Base
    attr_accessible :name, :quest_method

    def completed?
      self.send(quest_method)
    end

    def end_quest
       Monster.find_by_name('FINAL BOSS').dead?
    end
end

Quest.create name: 'End Quest', quest_method: 'end_quest'

这并不像你想象的那么糟糕。这本质上就是single table inheritance有效,但不是存储方法名称,而是将类名称存储在 type 列中。

class Quest < ActiveRecord::Base

    def finished?
        # default value, or throw an error
        false
    end

end

class EndQuest < Quest

    def finished?
        Monster.find_by_name('END BOSS').dead?
    end
end

EndQuest.create # have to do this for all quests

无论哪种情况,您都将行为编写为代码,并且仅在记录中存储对所需行为的引用。您确实必须使用正确的类型或方法名称手动创建所有记录,并确保所有内容保持同步。但至少通过单表继承,ActiveRecord 可以解决其中的一些问题。

但是,没有什么可以阻止您将代码本身存储到数据库中。

class Quest < ActiveRecord::Base

    attr_accessible :name, :completed_expr

    def completed?
        eval(completed_expr)
    end

end

Quest.create name: 'END QUEST', 
  completed_expr: "Monster.find_by_name('BIG BOSS').dead?"

这当然有潜在的危险并且容易出错,除非您确切地知道自己在做什么,但它确实为您提供了在运行时重写任务完成标准的完全灵活性。

最后,如果您想要最复杂的功能,您可能需要考虑使用规则引擎(或者通过 DSL 推出您自己的完整规则)来包含您的业务(游戏世界)规则并存储它。

class Quest < ActiveRecord::Base
    attr_accessible :name, :completion_rule

    def completed?
        RulesEngine.evaluate(completion_rule)
    end
end

Quest.create name: 'END QUEST', 
  completion_rule: "Monster(name: 'BIG BOSS', state: 'dead')"

主要优点是通过将特定于任务的行为或规则存储在 DSL(这不是原始 Ruby 代码)中,您可以获得一定程度的安全性 - 您不会意外评估恶意或错误代码并导致整个系统瘫痪。

如果您的生产规则以这样的方式建模,您可以使用类似 Rete algorithm 的方式,那么您还可以获得一些效率。来评估它们。

关于ruby-on-rails - 如何将Rails模型记录与代码关联?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14495955/

相关文章:

python - Django 时间字段格式

qt - Qt5 和 Qt 4.8 中的模型和角色

ruby-on-rails - 使用自定义 cache_path 使操作缓存过期

ruby - 如何使用 Trollop 制作用于命令行解析的 Ruby 脚本?

ruby - ruby 中的打印功能

ruby - 访问ruby gem中的文本文件

Django 用户代理模型快速访问

ruby-on-rails - rspec 测试方法的输入是否具有特定结构

ruby-on-rails - 获取 Stripe 的美分价格

mysql - 将主键定义转储到 schema.rb 中