【问题标题】:Class method chaining and inheritance类方法链接和继承
【发布时间】:2016-02-11 10:09:20
【问题描述】:

我正在尝试创建一个 ORM 来包装 DynamoDB (NoSQL) 查询。此 ORM 由存储在 DynamoDB 中的模型继承。实际上是ActiveRecord的风格:

class User < ActiveRecord::Base; end

变成

class User < DynamOrm; end
require 'aws-sdk'

class DynamOrm

    CLIENT = Aws::DynamoDB::Client.new

    def find(key, options = {})
        query = CLIENT.get_item({
            table_name: 'my_table',
            key: key,
            consistent_read: true,
            return_consumed_capacity: "INDEXES"
        }.merge(options))

        if query.item.nil?
            raise 'NO ITEM FOUND'
        else
            self.new(query.item)
        end
    end

end

完成后,我不用担心通过我的 ORM 查询我的 DynamoDB 数据库。

User.find({ id: 52 }) # => #<User:0x007fc5bc8a64a0>

它返回我的User 的一个实例。我想链接一个名为filter 的方法。像这样:

User.find({ id: 52 }).filter({ gender: 'male' })

为此,我没有在find 方法中返回实例,而是将实例存储在一个变量中,然后返回Class。在我的filter 类方法中,我返回User 实例。

class DynamOrm

    # [...]

    def self.find(key, options = {})

        # [...]

        if query.item.nil?
            raise 'NO ITEM FOUND'
        else
            @result = self.new(query.item)
            self
        end
    end

    def self.filter(filters)
        #
        # APPLY MY FILTERS ON `@result`
        #
        return @result
    end

end

我有时必须使用filter,但有时不用。与ActiveRecord 一样,有时我将不得不使用orderlimit,但并非总是如此。所以,当我只想使用find 时,它会返回一个类而不是一个实例。一个简单的User.find({ id: 1 }) 将返回类User

如何重现 AR 方式,即直接在我的模型 (@user = User.find()) 上调用 ORM 并获取此模型的实例 @user.inspect # =&gt; #&lt;User:0x007fc5bc8a64a0 @id=1, @gender="male" &gt;

【问题讨论】:

  • 我很困惑,为什么你使用find方法从数据库中获取1条记录,然后你想按性别过滤呢?过滤器仅在对多条记录调用时才有意义,例如在来自where 方法的结果上
  • 无论如何,在我关于 DynamoDB 约束的用例中,这是有充分理由的。但是您可以将find 转置为where,这不会改变我的需求:-)
  • 然后你可以做出类似 AR 的行为,当在 AR 中调用 where 时,你会返回 ActiveRecord::Relation,然后你可以调用 ordersortgroup_by ans so在。它不返回 User 实例或 User
  • 谢谢 Nermin。我可以问你一个例子吗?
  • 这很相关@AndreyDeineko

标签: ruby chaining method-chaining chain


【解决方案1】:

为了能够像 ActiveRecord 这样链接您的查询函数,您应该有一个模仿 ActiveRecord::Relation 类的类,它存储您想要发出但实际上不会查询的请求片段直到您执行聚合(如计数、总和或最大值)或直到您尝试访问结果

为了更简单,你可以在每个函数中存储你需要的操作,并在最后调用另一个函数来执行完整的查询。

我想是这样的:

class DynamOrm

    #Array used to store the request items before the actual request is performed
    attr_accessor :request_items

    def find(key, options = {})
        #Stores the "find" operation with its arguments in request_items
        return self
    end

    def filter(filters)
        #Stores the "filter" operation with its arguments in request_items
        return self
    end

    def perform_query
        #Actually performs the query by combining all the stored request_items
    end

end

你可以像这样使用它: my_results = DynamOrn.new().find(my_id).filter(my_filter).perform_query

它可能不是你所需要的,但想法就在这里:存储查询参数,然后在最后查询。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-04
    • 2012-11-14
    • 2014-04-18
    • 1970-01-01
    • 2011-03-03
    • 1970-01-01
    • 2014-04-27
    • 1970-01-01
    相关资源
    最近更新 更多