sobjectmodel 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/sobject_model/adapter/base.rb +34 -0
- data/lib/sobject_model/adapter/rest.rb +53 -0
- data/lib/sobject_model/adapter/sf.rb +52 -0
- data/lib/sobject_model/base_methods.rb +57 -0
- data/lib/sobject_model/class_definition.rb +100 -0
- data/lib/sobject_model/dml_methods.rb +37 -0
- data/lib/sobject_model/generator.rb +45 -0
- data/lib/sobject_model/query_condition.rb +189 -0
- data/lib/sobject_model/query_methods.rb +78 -0
- data/lib/sobject_model/rest/client.rb +60 -0
- data/lib/sobject_model/rest/errors.rb +19 -0
- data/lib/sobject_model/rest/http.rb +61 -0
- data/lib/sobject_model/rest/query_result.rb +66 -0
- data/lib/sobject_model/schema.rb +553 -0
- data/lib/sobject_model/support/console.rb +63 -0
- data/lib/sobject_model.rb +29 -0
- metadata +60 -0
    
        checksums.yaml
    ADDED
    
    | @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            SHA256:
         | 
| 3 | 
            +
              metadata.gz: 593a275d93ff933f9e7d9be260194f2da06f4b55285424589b739db5b80e4b8d
         | 
| 4 | 
            +
              data.tar.gz: d8723a40b412a472ba84d56658046cde7b320ed617e22c92264d93b8649d5aaa
         | 
| 5 | 
            +
            SHA512:
         | 
| 6 | 
            +
              metadata.gz: 6dda884fe46731a0c8e25b372792908b3e4e43eb1d1a7693e97658cba06eeb6dadbff42ceedc7e04525072fe67b7027de372172ce637e567547b90b879bc799b
         | 
| 7 | 
            +
              data.tar.gz: 0cb40fb055300eaef7f198878c12f03652a7d79c70a0bef09ddb9d4b9ac949a92e231912be6ac0ee18d0142e446bbc8a713266d6ef9eaf817af4d2fdaf40815c
         | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            module SObjectModel
         | 
| 2 | 
            +
              module Adapter
         | 
| 3 | 
            +
                class Base
         | 
| 4 | 
            +
                  def exec_query(soql, model_class: nil)
         | 
| 5 | 
            +
                    raise 'this method is not implemented'
         | 
| 6 | 
            +
                  end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  def find(object_type, id, klass)
         | 
| 9 | 
            +
                    raise 'this method is not implemented'
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def create(object_type, values, klass = nil)
         | 
| 13 | 
            +
                    raise 'this method is not implemented'
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def update(object_type, id, values)
         | 
| 17 | 
            +
                    raise 'this method is not implemented'
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  def delete(object_type, id) 
         | 
| 21 | 
            +
                    raise 'this method is not implemented'
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  def query(soql, klass)
         | 
| 25 | 
            +
                    raise 'this method is not implemented'
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def describe(object_type)
         | 
| 29 | 
            +
                    raise 'this method is not implemented'
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
            end 
         | 
| 34 | 
            +
              
         | 
| @@ -0,0 +1,53 @@ | |
| 1 | 
            +
            require_relative 'base'
         | 
| 2 | 
            +
            require_relative '../rest/client'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module SObjectModel
         | 
| 5 | 
            +
              module Adapter
         | 
| 6 | 
            +
                class Rest < Base
         | 
| 7 | 
            +
                  def initialize(rest_client)
         | 
| 8 | 
            +
                    @client = rest_client
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  def exec_query(soql, model_class: nil)
         | 
| 12 | 
            +
                    result = client.query(soql)
         | 
| 13 | 
            +
                    result.to_records(model_class: model_class)
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def describe(object_type)
         | 
| 17 | 
            +
                    client.describe(object_type)
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  def find(object_type, id, klass)
         | 
| 21 | 
            +
                    attributes = client.find(object_type, id)
         | 
| 22 | 
            +
                    klass.new(**attributes)
         | 
| 23 | 
            +
                  rescue ::SObjectModel::Rest::RecordNotFoundError
         | 
| 24 | 
            +
                    nil
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  def create(object_type, values, klass = nil)
         | 
| 28 | 
            +
                    id = client.create(object_type, values)
         | 
| 29 | 
            +
                    return id if klass.nil?
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    find(object_type, id, klass)
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  def update(object_type, id, values)
         | 
| 35 | 
            +
                    client.update(object_type, id, values)
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  def delete(object_type, id)
         | 
| 39 | 
            +
                    client.delete(object_type, id)
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  def query(soql, klass)
         | 
| 43 | 
            +
                    exec_query(soql, model_class: klass)
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  private
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  def client
         | 
| 49 | 
            +
                    @client
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
            end
         | 
| @@ -0,0 +1,52 @@ | |
| 1 | 
            +
            require_relative 'base'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module SObjectModel
         | 
| 4 | 
            +
              module Adapter
         | 
| 5 | 
            +
                class Sf < Base
         | 
| 6 | 
            +
                  attr_reader :target_org
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  def initialize(sf_main, target_org:)
         | 
| 9 | 
            +
                    @sf = sf_main
         | 
| 10 | 
            +
                    @target_org = target_org
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  def exec_query(soql, format: nil, bulk: false, wait: nil, model_class: nil)
         | 
| 14 | 
            +
                    sf.data.query(soql, target_org: target_org, format: format, bulk: bulk, wait: wait, model_class: model_class)
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def find(object_type, id, klass)
         | 
| 18 | 
            +
                    sf.data.get_record object_type, record_id: id, target_org: target_org, model_class: klass
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def create(object_type, values, klass = nil)
         | 
| 22 | 
            +
                    id = sf.data.create_record object_type, values: values, target_org: target_org
         | 
| 23 | 
            +
                    return id if klass.nil?
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    find(object_type, id, klass)
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def update(object_type, id, values)
         | 
| 29 | 
            +
                    sf.data.update_record object_type, record_id: id, where: nil, values: values, target_org: target_org
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  def delete(object_type, id)
         | 
| 33 | 
            +
                    sf.data.delete_record object_type, record_id: id, where: nil, target_org: target_org
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  def query(soql, klass, format = nil)
         | 
| 37 | 
            +
                    sf.data.query soql, target_org: target_org, format: format, model_class: klass
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def describe(object_type)
         | 
| 41 | 
            +
                    schema = sf.sobject.describe(object_type, target_org: target_org)
         | 
| 42 | 
            +
                    schema.to_h # convert to raw command response
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  private
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  def sf
         | 
| 48 | 
            +
                    @sf
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
            end
         | 
| @@ -0,0 +1,57 @@ | |
| 1 | 
            +
            module SObjectModel
         | 
| 2 | 
            +
              module BaseMethods
         | 
| 3 | 
            +
                def self.included(c)
         | 
| 4 | 
            +
                  c.extend ClassMethods
         | 
| 5 | 
            +
                end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                module ClassMethods
         | 
| 8 | 
            +
                  def connection
         | 
| 9 | 
            +
                    @connection
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def connection=(conn)
         | 
| 13 | 
            +
                    @connection = conn
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def describe
         | 
| 17 | 
            +
                    Schema.new(connection.describe(name.to_sym))
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def initialize(attributes = {})
         | 
| 22 | 
            +
                  @original_attributes = {}
         | 
| 23 | 
            +
                  @current_attributes = {}
         | 
| 24 | 
            +
                  @updated_attributes = {}
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  attributes.each do |k, v|
         | 
| 27 | 
            +
                    field_name = k.to_sym
         | 
| 28 | 
            +
                    if self.class.field_names.include?(field_name)
         | 
| 29 | 
            +
                      @original_attributes[field_name] = v
         | 
| 30 | 
            +
                      __send__ (field_name.to_s + '='), v
         | 
| 31 | 
            +
                    elsif self.class.parent_relations.find{|r| r[:name] == field_name}
         | 
| 32 | 
            +
                      __send__ (field_name.to_s + '='), v
         | 
| 33 | 
            +
                    elsif self.class.child_relations.find{|r| r[:name] == field_name}
         | 
| 34 | 
            +
                      __send__ (field_name.to_s + '='), (v.nil? ? [] : v)
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def to_h(keys: nil)
         | 
| 40 | 
            +
                  self.class.field_names.each_with_object({}) do |name, hash|
         | 
| 41 | 
            +
                    if keys&.instance_of?(Array)
         | 
| 42 | 
            +
                      hash[name] = __send__(name) if keys.include?(name)
         | 
| 43 | 
            +
                    else
         | 
| 44 | 
            +
                      hash[name] = __send__(name)
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                def new_record?
         | 
| 50 | 
            +
                  self.Id.nil?
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                def persisted?
         | 
| 54 | 
            +
                  new_record? == false
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
            end
         | 
| @@ -0,0 +1,100 @@ | |
| 1 | 
            +
            require_relative './schema'
         | 
| 2 | 
            +
            require_relative './base_methods'
         | 
| 3 | 
            +
            require_relative './dml_methods'
         | 
| 4 | 
            +
            require_relative './query_methods'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module SObjectModel
         | 
| 7 | 
            +
              class ClassDefinition
         | 
| 8 | 
            +
                attr_reader :schema
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def initialize(schema)
         | 
| 11 | 
            +
                  @schema = Schema.new(schema)
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def to_s
         | 
| 15 | 
            +
                  <<~Klass
         | 
| 16 | 
            +
                    Class.new do
         | 
| 17 | 
            +
                      include ::SObjectModel::BaseMethods
         | 
| 18 | 
            +
                      include ::SObjectModel::DmlMethods
         | 
| 19 | 
            +
                      include ::SObjectModel::QueryMethods
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                      attr_reader :original_attributes, :current_attributes, :updated_attributes
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                      #{ class_methods }
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                      #{ field_attribute_methods }
         | 
| 26 | 
            +
                      #{ parent_relation_methods }
         | 
| 27 | 
            +
                      #{ child_relation_methods }
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
                  Klass
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def class_methods
         | 
| 33 | 
            +
                  <<~EOS
         | 
| 34 | 
            +
                    class << self
         | 
| 35 | 
            +
                      def field_names
         | 
| 36 | 
            +
                        @field_names ||= #{ schema.field_names }
         | 
| 37 | 
            +
                      end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                      def parent_relations
         | 
| 40 | 
            +
                        @parent_relations ||= #{ schema.parent_relations }
         | 
| 41 | 
            +
                      end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                      def child_relations
         | 
| 44 | 
            +
                        @child_relations ||= #{ schema.child_relations }
         | 
| 45 | 
            +
                      end
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
                  EOS
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                def field_attribute_methods
         | 
| 51 | 
            +
                  schema.field_names.each_with_object('') do |name, s|
         | 
| 52 | 
            +
                    s << <<~EOS
         | 
| 53 | 
            +
                      def #{name}
         | 
| 54 | 
            +
                        @#{name}
         | 
| 55 | 
            +
                      end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                      def #{name}=(value)
         | 
| 58 | 
            +
                        @#{name} = value
         | 
| 59 | 
            +
                        return if %i[Id LastModifiedDate IsDeleted SystemModstamp CreatedById CreatedDate LastModifiedById].include?(:#{name})
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                        current_attributes[:#{name}] = value
         | 
| 62 | 
            +
                        if current_attributes[:#{name}] == original_attributes[:#{name}]
         | 
| 63 | 
            +
                          updated_attributes[:#{name}] = nil
         | 
| 64 | 
            +
                        else
         | 
| 65 | 
            +
                          updated_attributes[:#{name}] = (value.nil? ? :null : value)
         | 
| 66 | 
            +
                        end
         | 
| 67 | 
            +
                      end
         | 
| 68 | 
            +
                    EOS
         | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                def parent_relation_methods
         | 
| 73 | 
            +
                  schema.parent_relations.each_with_object('') do |r, s|
         | 
| 74 | 
            +
                    s << <<~EOS
         | 
| 75 | 
            +
                      def #{r[:name]}
         | 
| 76 | 
            +
                        @#{r[:name]}
         | 
| 77 | 
            +
                      end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                      def #{r[:name]}=(attributes)
         | 
| 80 | 
            +
                        @#{r[:name]} = attributes.nil? ? nil : #{r[:class_name]}.new(attributes)
         | 
| 81 | 
            +
                      end
         | 
| 82 | 
            +
                    EOS
         | 
| 83 | 
            +
                  end
         | 
| 84 | 
            +
                end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                def child_relation_methods
         | 
| 87 | 
            +
                  schema.child_relations.each_with_object('') do |r, s|
         | 
| 88 | 
            +
                    s << <<~EOS
         | 
| 89 | 
            +
                      def #{r[:name]}
         | 
| 90 | 
            +
                        @#{r[:name]}
         | 
| 91 | 
            +
                      end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                      def #{r[:name]}=(records)
         | 
| 94 | 
            +
                        @#{r[:name]} = records.map{|attributes| #{r[:class_name]}.new(attributes)}
         | 
| 95 | 
            +
                      end
         | 
| 96 | 
            +
                    EOS
         | 
| 97 | 
            +
                  end
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
              end
         | 
| 100 | 
            +
            end
         | 
| @@ -0,0 +1,37 @@ | |
| 1 | 
            +
            module SObjectModel
         | 
| 2 | 
            +
              module DmlMethods
         | 
| 3 | 
            +
                def self.included(c)
         | 
| 4 | 
            +
                  c.extend ClassMethods
         | 
| 5 | 
            +
                end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def save
         | 
| 8 | 
            +
                  if new_record?
         | 
| 9 | 
            +
                    self.Id = self.class.connection.create(self.class.name.to_sym, current_attributes.reject{|_,v| v.nil?})
         | 
| 10 | 
            +
                  else
         | 
| 11 | 
            +
                    _updated_attributes =
         | 
| 12 | 
            +
                      updated_attributes
         | 
| 13 | 
            +
                        .reject{|_,v| v.nil?}
         | 
| 14 | 
            +
                        .each_with_object({}){ |(k,v),h| h[k] = (v == :null) ? nil : v }
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                    self.class.connection.update(self.class.name.to_sym, self.Id, _updated_attributes)
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  @original_attributes = current_attributes.dup
         | 
| 20 | 
            +
                  @updated_attributes = {}
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  self.Id
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def delete
         | 
| 26 | 
            +
                  return if self.Id.nil?
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  self.class.connection.delete(self.class.name.to_sym, self.Id)
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                module ClassMethods
         | 
| 32 | 
            +
                  def create(values = {})
         | 
| 33 | 
            +
                    connection.create(name.to_sym, values, Object.const_get(name.to_sym))
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
            end
         | 
| @@ -0,0 +1,45 @@ | |
| 1 | 
            +
            require_relative './class_definition'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module SObjectModel
         | 
| 4 | 
            +
              class Generator
         | 
| 5 | 
            +
                attr_reader :connection
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def initialize(connection)
         | 
| 8 | 
            +
                  @connection = connection
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def connected?
         | 
| 12 | 
            +
                  connection.nil? == false
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def generate(*object_types)
         | 
| 16 | 
            +
                  generated_types = []
         | 
| 17 | 
            +
                  object_types.each do |object_type|
         | 
| 18 | 
            +
                    next if generated? object_type
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    schema = describe(object_type)
         | 
| 21 | 
            +
                    class_definition = ClassDefinition.new(schema)
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    instance_eval "::#{object_type} = #{class_definition}"
         | 
| 24 | 
            +
                    klass = Object.const_get object_type.to_sym
         | 
| 25 | 
            +
                    klass.connection = connection
         | 
| 26 | 
            +
                    generated_types << object_type
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  generated_types
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                private
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def describe(object_type)
         | 
| 35 | 
            +
                  connection.describe object_type
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                def generated?(object_type)
         | 
| 39 | 
            +
                  Object.const_get object_type.to_sym
         | 
| 40 | 
            +
                  true
         | 
| 41 | 
            +
                rescue NameError
         | 
| 42 | 
            +
                  false
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
            end
         | 
| @@ -0,0 +1,189 @@ | |
| 1 | 
            +
            require 'date'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module SObjectModel
         | 
| 4 | 
            +
              module QueryMethods
         | 
| 5 | 
            +
                class QueryCondition
         | 
| 6 | 
            +
                  attr_reader :connection,
         | 
| 7 | 
            +
                              :object_name,
         | 
| 8 | 
            +
                              :all_field_names,
         | 
| 9 | 
            +
                              :fields,
         | 
| 10 | 
            +
                              :conditions,
         | 
| 11 | 
            +
                              :limit_num,
         | 
| 12 | 
            +
                              :row_order,
         | 
| 13 | 
            +
                              :count_select,
         | 
| 14 | 
            +
                              :max_select_field,
         | 
| 15 | 
            +
                              :min_select_field
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def initialize(connection, object_name, field_names)
         | 
| 18 | 
            +
                    @object_name = object_name
         | 
| 19 | 
            +
                    @all_field_names = field_names 
         | 
| 20 | 
            +
                    @connection = connection
         | 
| 21 | 
            +
                    @fields = []
         | 
| 22 | 
            +
                    @conditions = [] 
         | 
| 23 | 
            +
                    @limit_num = nil
         | 
| 24 | 
            +
                    @row_order = nil
         | 
| 25 | 
            +
                    @count_select = false
         | 
| 26 | 
            +
                    @max_select_field = nil
         | 
| 27 | 
            +
                    @min_select_field = nil
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  def where(*expr)
         | 
| 31 | 
            +
                    return self unless valid_expr?(expr)
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    conditions.append to_string_expr(expr)
         | 
| 34 | 
            +
                    self
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  def not(*expr)
         | 
| 38 | 
            +
                    return self unless valid_expr?(expr)
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    conditions.append %|(NOT(#{to_string_expr(expr)}))|
         | 
| 41 | 
            +
                    self
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  def select(*expr)
         | 
| 45 | 
            +
                    return self if expr&.empty?
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                    if expr.size > 1
         | 
| 48 | 
            +
                      @fields = self.fields + expr
         | 
| 49 | 
            +
                    else
         | 
| 50 | 
            +
                      self.fields << expr.first
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
                    return self
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                  def limit(num)
         | 
| 56 | 
            +
                    @limit_num = num
         | 
| 57 | 
            +
                    return self
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                  def order(*_fields)
         | 
| 61 | 
            +
                    return self if _fields&.empty?
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                    @row_order = _fields
         | 
| 64 | 
            +
                    return self
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  def to_soql
         | 
| 68 | 
            +
                    base   = 'SELECT %{select} FROM %{object}' % {select: select_fields, object: object_name}
         | 
| 69 | 
            +
                    where  = conditions.size.zero?  ? nil : 'WHERE %{where}'    % {where: conditions.flatten.join(' AND ')}
         | 
| 70 | 
            +
                    _order = row_order.nil?         ? nil : 'ORDER BY %{order}' % {order: row_order.join(', ')}
         | 
| 71 | 
            +
                    limit  = limit_num.nil?         ? nil : 'LIMIT %{limit}'    % {limit: limit_num} 
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                    [base, where, _order, limit].compact.join(' ')
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  def all
         | 
| 77 | 
            +
                    connection.query(to_soql, Object.const_get(object_name.to_sym))
         | 
| 78 | 
            +
                  end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                  def pluck(field_name)
         | 
| 81 | 
            +
                    connection.query(to_soql, nil).map{|record| record[field_name.to_s]}
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                  def take
         | 
| 85 | 
            +
                    limit(1).all.first
         | 
| 86 | 
            +
                  end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                  def count
         | 
| 89 | 
            +
                    @count_select = true
         | 
| 90 | 
            +
                    connection.query(to_soql, nil).first['expr0']
         | 
| 91 | 
            +
                  end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                  def max(field_name)
         | 
| 94 | 
            +
                    @max_select_field = field_name
         | 
| 95 | 
            +
                    connection.query(to_soql, nil).first['expr0']
         | 
| 96 | 
            +
                  end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                  def min(field_name)
         | 
| 99 | 
            +
                    @min_select_field = field_name
         | 
| 100 | 
            +
                    connection.query(to_soql, nil).first['expr0']
         | 
| 101 | 
            +
                  end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                  private
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                  def select_fields
         | 
| 106 | 
            +
                    return 'COUNT(Id)'                if count_select
         | 
| 107 | 
            +
                    return "MAX(#{max_select_field})" if max_select_field
         | 
| 108 | 
            +
                    return "MIN(#{min_select_field})" if min_select_field
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                    (fields.empty? ? all_field_names : fields.push(:Id).uniq).join(', ')
         | 
| 111 | 
            +
                  end 
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                  def to_string_expr(expr)
         | 
| 114 | 
            +
                    return str_by_ternary_expr(expr) if expr.size > 1
         | 
| 115 | 
            +
                    return expr[0] if expr[0].instance_of? String
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                    strs_by_hash_expr(expr)
         | 
| 118 | 
            +
                  end
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                  def str_by_ternary_expr(expr)
         | 
| 121 | 
            +
                    return self if expr.size < 3
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                    value = case expr[2].class.name.to_sym
         | 
| 124 | 
            +
                            when :String
         | 
| 125 | 
            +
                              %|'#{expr[2]}'|
         | 
| 126 | 
            +
                            when :Time
         | 
| 127 | 
            +
                              expr[2].to_datetime
         | 
| 128 | 
            +
                            when :NilClass
         | 
| 129 | 
            +
                              :null
         | 
| 130 | 
            +
                            when :Array
         | 
| 131 | 
            +
                              candidates = expr[2].map do |o|
         | 
| 132 | 
            +
                                  case o.class.name.to_sym
         | 
| 133 | 
            +
                                  when :String
         | 
| 134 | 
            +
                                    %|'#{o}'|
         | 
| 135 | 
            +
                                  when :Time
         | 
| 136 | 
            +
                                    o.to_datetime
         | 
| 137 | 
            +
                                  when :NilClass
         | 
| 138 | 
            +
                                    :null
         | 
| 139 | 
            +
                                  else
         | 
| 140 | 
            +
                                    o
         | 
| 141 | 
            +
                                  end
         | 
| 142 | 
            +
                                end
         | 
| 143 | 
            +
                              %|(#{candidates.join(', ')})|
         | 
| 144 | 
            +
                            else
         | 
| 145 | 
            +
                              expr[2]
         | 
| 146 | 
            +
                            end
         | 
| 147 | 
            +
                    %|#{expr[0]} #{expr[1]} #{value}|
         | 
| 148 | 
            +
                  end
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                  def valid_expr?(expr)
         | 
| 151 | 
            +
                    return false if expr&.empty?
         | 
| 152 | 
            +
                    return false if expr.map{|o| (o == '' || o == {} || o == []) ? nil : o}.compact.size.zero?
         | 
| 153 | 
            +
                    return false unless [Hash, Symbol, String].any?{|klass| expr.first.instance_of? klass}
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                    true
         | 
| 156 | 
            +
                  end
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                  def strs_by_hash_expr(expr)
         | 
| 159 | 
            +
                    expr[0].map do |k,v|
         | 
| 160 | 
            +
                      case v.class.name.to_sym
         | 
| 161 | 
            +
                      when :String
         | 
| 162 | 
            +
                        %|#{k} = '#{v}'|
         | 
| 163 | 
            +
                      when :Time
         | 
| 164 | 
            +
                        %|#{k} = #{v.to_datetime}|
         | 
| 165 | 
            +
                      when :NilClass
         | 
| 166 | 
            +
                        %|#{k} = null|
         | 
| 167 | 
            +
                      when :Array
         | 
| 168 | 
            +
                        candidates = v.map do |o|
         | 
| 169 | 
            +
                            case o.class.name.to_sym
         | 
| 170 | 
            +
                            when :String
         | 
| 171 | 
            +
                              %|'#{o}'|
         | 
| 172 | 
            +
                            when :Time
         | 
| 173 | 
            +
                              %|#{o.to_datetime}|
         | 
| 174 | 
            +
                            when :NilClass
         | 
| 175 | 
            +
                              :null
         | 
| 176 | 
            +
                            else
         | 
| 177 | 
            +
                              o
         | 
| 178 | 
            +
                            end
         | 
| 179 | 
            +
                          end
         | 
| 180 | 
            +
                        %|#{k} IN (#{candidates.join(', ')})|
         | 
| 181 | 
            +
                      else
         | 
| 182 | 
            +
                        "#{k} = #{v}"
         | 
| 183 | 
            +
                      end
         | 
| 184 | 
            +
                    end
         | 
| 185 | 
            +
                    .join(' AND ')
         | 
| 186 | 
            +
                  end
         | 
| 187 | 
            +
                end
         | 
| 188 | 
            +
              end
         | 
| 189 | 
            +
            end
         | 
| @@ -0,0 +1,78 @@ | |
| 1 | 
            +
            require_relative './query_condition'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module SObjectModel
         | 
| 4 | 
            +
              module QueryMethods
         | 
| 5 | 
            +
                def self.included(c)
         | 
| 6 | 
            +
                  c.extend ClassMethods
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                module ClassMethods
         | 
| 10 | 
            +
                  def where(*expr)
         | 
| 11 | 
            +
                    qc = QueryCondition.new(connection, self.name, self.field_names)
         | 
| 12 | 
            +
                    qc.where(*expr)
         | 
| 13 | 
            +
                    return qc
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def select(*fields)
         | 
| 17 | 
            +
                    qc = QueryCondition.new(connection, self.name, self.field_names)
         | 
| 18 | 
            +
                    qc.select(*fields)
         | 
| 19 | 
            +
                    return qc
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  def limit(num)
         | 
| 23 | 
            +
                    qc = QueryCondition.new(connection, self.name, self.field_names)
         | 
| 24 | 
            +
                    qc.limit(num)
         | 
| 25 | 
            +
                    qc
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def order(*field_names)
         | 
| 29 | 
            +
                    qc = QueryCondition.new(connection, self.name, self.field_names)
         | 
| 30 | 
            +
                    qc.order(*field_names)
         | 
| 31 | 
            +
                    qc
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
                  def find(id)
         | 
| 34 | 
            +
                    connection.find(name.to_sym, id, Object.const_get(name.to_sym))
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  def find_by(*find_condition)
         | 
| 38 | 
            +
                    qc = QueryCondition.new(connection, self.name, self.field_names)
         | 
| 39 | 
            +
                    qc.where(*find_condition).take
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  def all
         | 
| 43 | 
            +
                    qc = QueryCondition.new(connection, self.name, self.field_names)
         | 
| 44 | 
            +
                    qc.all
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  def to_csv
         | 
| 48 | 
            +
                    qc = QueryCondition.new(connection, self.name, self.field_names)
         | 
| 49 | 
            +
                    qc.to_csv
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  def pluck(field_name)
         | 
| 53 | 
            +
                    qc = QueryCondition.new(connection, self.name, self.field_names)
         | 
| 54 | 
            +
                    qc.pluck(field_name)
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  def take
         | 
| 58 | 
            +
                    qc = QueryCondition.new(connection, self.name, self.field_names)
         | 
| 59 | 
            +
                    qc.take
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                  def count
         | 
| 63 | 
            +
                    qc = QueryCondition.new(connection, self.name, self.field_names)
         | 
| 64 | 
            +
                    qc.count
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  def max(field_name)
         | 
| 68 | 
            +
                    qc = QueryCondition.new(connection, self.name, self.field_names)
         | 
| 69 | 
            +
                    qc.max(field_name)
         | 
| 70 | 
            +
                  end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                  def min(field_name)
         | 
| 73 | 
            +
                    qc = QueryCondition.new(connection, self.name, self.field_names)
         | 
| 74 | 
            +
                    qc.min(field_name)
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
              end
         | 
| 78 | 
            +
            end
         |