类方法链接和继承

时间:2016-02-11 10:09:20

标签: ruby chaining method-chaining chain

我正在尝试创建一个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方式,即直接在我的模型上调用ORM(@user = User.find())并获取此模型@user.inspect # => #<User:0x007fc5bc8a64a0 @id=1, @gender="male" >的实例?

1 个答案:

答案 0 :(得分:0)

为了能够链接你的查询函数,比如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

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