active_house 0.4.0 → 0.5.0
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 +4 -4
- data/.rubocop.yml +9 -0
- data/active_house.gemspec +1 -0
- data/lib/active_house.rb +1 -1
- data/lib/active_house/connection.rb +3 -3
- data/lib/active_house/exceptions.rb +9 -0
- data/lib/active_house/{logger.rb → logging.rb} +1 -1
- data/lib/active_house/model.rb +14 -12
- data/lib/active_house/modeling/attributes.rb +102 -0
- data/lib/active_house/modeling/connection.rb +38 -0
- data/lib/active_house/modeling/query.rb +29 -0
- data/lib/active_house/modeling/scope.rb +42 -0
- data/lib/active_house/prepared_statement.rb +34 -2
- data/lib/active_house/query_builder.rb +38 -0
- data/lib/active_house/querying/array_join.rb +42 -0
- data/lib/active_house/querying/collect.rb +80 -0
- data/lib/active_house/querying/from.rb +30 -0
- data/lib/active_house/querying/group_by.rb +30 -0
- data/lib/active_house/querying/having.rb +41 -0
- data/lib/active_house/querying/limit.rb +35 -0
- data/lib/active_house/querying/order_by.rb +58 -0
- data/lib/active_house/querying/scope.rb +45 -0
- data/lib/active_house/querying/select.rb +35 -0
- data/lib/active_house/querying/union.rb +67 -0
- data/lib/active_house/querying/where.rb +50 -0
- data/lib/active_house/version.rb +1 -1
- metadata +34 -22
- data/lib/active_house/array_joinable.rb +0 -31
- data/lib/active_house/chainable.rb +0 -151
- data/lib/active_house/collectable.rb +0 -44
- data/lib/active_house/connecting.rb +0 -36
- data/lib/active_house/connection_error.rb +0 -6
- data/lib/active_house/error.rb +0 -4
- data/lib/active_house/fromable.rb +0 -29
- data/lib/active_house/groupable.rb +0 -23
- data/lib/active_house/havingable.rb +0 -50
- data/lib/active_house/limitable.rb +0 -27
- data/lib/active_house/modeling.rb +0 -100
- data/lib/active_house/orderable.rb +0 -45
- data/lib/active_house/query.rb +0 -22
- data/lib/active_house/querying.rb +0 -21
- data/lib/active_house/scopeable.rb +0 -42
- data/lib/active_house/scoping.rb +0 -37
- data/lib/active_house/selectable.rb +0 -35
- data/lib/active_house/unionable.rb +0 -43
- data/lib/active_house/whereable.rb +0 -57
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 460006ab1e148781921648c680e33a79790e35cd
|
4
|
+
data.tar.gz: eb9ee437906deca34b1c6bb3bb172dc4bfcdab7b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 190813fb7b150e48c7c75c1a53ef12e5dc589ab60b109cf65463644ba3e4c17dd0c94b6fd927e778811dd1e631c0163ec5e6ef7fa5b72425aa34fd68eaca89fc
|
7
|
+
data.tar.gz: 16fdecaf5792d2641aca7cd2b3e777d195894cbabe593b2ef1719ad16f83313fc547b3863829bcf764896b75b6721e77f90a08a420574f6d5ca46eb8d7c757f7
|
data/.rubocop.yml
CHANGED
data/active_house.gemspec
CHANGED
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_dependency 'activemodel'
|
26
26
|
spec.add_dependency 'activesupport'
|
27
27
|
spec.add_dependency 'clickhouse', '~> 0.1.10'
|
28
|
+
spec.add_dependency 'plain_model', '~> 0.2'
|
28
29
|
|
29
30
|
spec.add_development_dependency 'bundler', '~> 1.16'
|
30
31
|
spec.add_development_dependency 'minitest', '~> 5.0'
|
data/lib/active_house.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require_relative 'connection_error'
|
2
|
-
require_relative 'prepared_statement'
|
3
1
|
require 'clickhouse/cluster'
|
4
2
|
require 'clickhouse/connection'
|
3
|
+
require_relative 'exceptions'
|
4
|
+
require_relative 'prepared_statement'
|
5
5
|
|
6
6
|
module ActiveHouse
|
7
7
|
class Connection
|
@@ -72,7 +72,7 @@ module ActiveHouse
|
|
72
72
|
|
73
73
|
def ensure_connected!
|
74
74
|
@connection = establish_connection unless connection_alive?
|
75
|
-
raise ActiveHouse::ConnectionError unless connection_alive?
|
75
|
+
raise ActiveHouse::Exceptions::ConnectionError unless connection_alive?
|
76
76
|
end
|
77
77
|
|
78
78
|
def establish_connection
|
data/lib/active_house/model.rb
CHANGED
@@ -1,20 +1,22 @@
|
|
1
|
-
require_relative 'scoping'
|
2
|
-
require_relative 'querying'
|
3
|
-
require_relative 'modeling'
|
4
|
-
require_relative 'connecting'
|
5
|
-
require_relative 'logger'
|
6
1
|
require 'active_model/conversion'
|
7
2
|
require 'active_model/naming'
|
3
|
+
require 'plain_model/modeling/base'
|
4
|
+
require 'plain_model/modeling/queryable'
|
5
|
+
require_relative 'modeling/scope'
|
6
|
+
require_relative 'modeling/query'
|
7
|
+
require_relative 'modeling/attributes'
|
8
|
+
require_relative 'modeling/connection'
|
9
|
+
require_relative 'logging'
|
8
10
|
|
9
11
|
module ActiveHouse
|
10
12
|
class Model
|
11
|
-
|
12
|
-
include
|
13
|
-
include ActiveHouse::Modeling
|
14
|
-
include ActiveHouse::
|
15
|
-
include ActiveHouse::
|
16
|
-
include
|
17
|
-
|
13
|
+
extend PlainModel::Modeling::Queryable
|
14
|
+
include PlainModel::Modeling::Base
|
15
|
+
include ActiveHouse::Modeling::Scope
|
16
|
+
include ActiveHouse::Modeling::Query
|
17
|
+
include ActiveHouse::Modeling::Attributes
|
18
|
+
include ActiveHouse::Modeling::Connection
|
19
|
+
include ActiveHouse::Logging
|
18
20
|
|
19
21
|
class_attribute :_table_name, instance_accessor: false
|
20
22
|
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module ActiveHouse
|
4
|
+
module Modeling
|
5
|
+
module Attributes
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
class_attribute :_attribute_opts, instance_writer: false
|
10
|
+
self._attribute_opts = {}
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def parse_attribute_method_name(method_name)
|
15
|
+
name, is_setter = method_name.to_s.match(/\A(.+)?(=)?\z/).captures
|
16
|
+
name = name.to_sym
|
17
|
+
is_setter = !is_setter.nil?
|
18
|
+
[name, is_setter]
|
19
|
+
end
|
20
|
+
|
21
|
+
def attribute_method?(name, is_setter, *args)
|
22
|
+
(_attribute_opts.key?(name) || @_attributes.key?(name)) && (is_setter ? args.size == 1 : true)
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_attribute(name)
|
26
|
+
@_attributes[name]
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_attribute(name, value)
|
30
|
+
opts = _attribute_opts.fetch(name, {})
|
31
|
+
value = opts[:cast].call(value) if opts[:cast]
|
32
|
+
@_attributes[name] = value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class_methods do
|
37
|
+
def attribute(name, options = {})
|
38
|
+
name = name.to_sym
|
39
|
+
self._attribute_opts = _attribute_opts.merge(name => options)
|
40
|
+
define_method(name) do
|
41
|
+
get_attribute(name)
|
42
|
+
end
|
43
|
+
define_method("#{name}=") do |value|
|
44
|
+
set_attribute(name, value)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def attributes(*names)
|
49
|
+
options = names.extract_options!
|
50
|
+
names.each { |name| attribute(name, options.dup) }
|
51
|
+
end
|
52
|
+
|
53
|
+
def load!(params)
|
54
|
+
new.tap do |model|
|
55
|
+
params.each { |name, value| model[name] = value }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def initialize(params = {})
|
61
|
+
@_attributes = {}
|
62
|
+
assign_attributes(params) unless params.nil?
|
63
|
+
end
|
64
|
+
|
65
|
+
def as_json(*_args)
|
66
|
+
to_h
|
67
|
+
end
|
68
|
+
|
69
|
+
def to_h
|
70
|
+
@_attributes.dup
|
71
|
+
end
|
72
|
+
|
73
|
+
def [](key)
|
74
|
+
get_attribute(key.to_sym)
|
75
|
+
end
|
76
|
+
|
77
|
+
def []=(key, value)
|
78
|
+
set_attribute(key.to_sym, value)
|
79
|
+
end
|
80
|
+
|
81
|
+
def assign_attributes(params)
|
82
|
+
params.each do |key, val|
|
83
|
+
public_send("#{key}=", val)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def respond_to_missing?(method_name, *args)
|
88
|
+
name, is_setter = parse_attribute_method_name(method_name)
|
89
|
+
attribute_method?(name, is_setter, *args)
|
90
|
+
end
|
91
|
+
|
92
|
+
def method_missing(method_name, *args, &block)
|
93
|
+
name, is_setter = parse_attribute_method_name(method_name)
|
94
|
+
if attribute_method?(name, is_setter, *args)
|
95
|
+
is_setter ? set_attribute(name, args.first) : get_attribute(name)
|
96
|
+
else
|
97
|
+
super
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'active_support/core_ext/class/attribute'
|
2
|
+
require 'active_support/concern'
|
3
|
+
require_relative '../connection'
|
4
|
+
require_relative '../configuration'
|
5
|
+
|
6
|
+
module ActiveHouse
|
7
|
+
module Modeling
|
8
|
+
module Connection
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
included do
|
12
|
+
class_attribute :_connection_class, instance_accessor: false
|
13
|
+
class_attribute :_connection, instance_accessor: false
|
14
|
+
self._connection_class = ActiveHouse::Connection
|
15
|
+
end
|
16
|
+
|
17
|
+
class_methods do
|
18
|
+
def ensure_connection
|
19
|
+
establish_connection if _connection.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
def establish_connection(name_or_config = nil)
|
23
|
+
config = if name_or_config.is_a?(Hash)
|
24
|
+
name_or_config.symbolize_keys
|
25
|
+
else
|
26
|
+
ActiveHouse.configuration.connection_config_for(name_or_config)
|
27
|
+
end
|
28
|
+
self._connection = _connection_class.new(config)
|
29
|
+
end
|
30
|
+
|
31
|
+
def connection
|
32
|
+
ensure_connection
|
33
|
+
_connection
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'active_support/core_ext/module/delegation'
|
3
|
+
|
4
|
+
module ActiveHouse
|
5
|
+
module Modeling
|
6
|
+
module Query
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
class_methods do
|
10
|
+
delegate :select,
|
11
|
+
:array_join,
|
12
|
+
:left_array_join,
|
13
|
+
:group_by,
|
14
|
+
:limit,
|
15
|
+
:order_by,
|
16
|
+
:having,
|
17
|
+
:from,
|
18
|
+
:union,
|
19
|
+
:where,
|
20
|
+
:where_not,
|
21
|
+
to: :all
|
22
|
+
|
23
|
+
def _query_builder
|
24
|
+
::ActiveHouse::QueryBuilder.new(self)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module ActiveHouse
|
4
|
+
module Modeling
|
5
|
+
module Scope
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
class_attribute :_default_scope, instance_accessor: false
|
10
|
+
class_attribute :_scopes, instance_accessor: false
|
11
|
+
self._scopes = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
class_methods do
|
15
|
+
def default_scope(name)
|
16
|
+
self._default_scope = name.to_sym
|
17
|
+
end
|
18
|
+
|
19
|
+
def scope(name, block)
|
20
|
+
self._scopes = _scopes.merge(name.to_sym => block)
|
21
|
+
end
|
22
|
+
|
23
|
+
def respond_to_missing?(method_name, *_args)
|
24
|
+
scope?(method_name) || super
|
25
|
+
end
|
26
|
+
|
27
|
+
def method_missing(method_name, *args, &_block)
|
28
|
+
if scope?(method_name)
|
29
|
+
scope = _scopes.fetch(method_name.to_sym)
|
30
|
+
all.instance_exec(*args, &scope)
|
31
|
+
else
|
32
|
+
super
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def scope?(name)
|
37
|
+
_scopes.key?(name.to_sym)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -18,9 +18,9 @@ module ActiveHouse
|
|
18
18
|
"'#{value.gsub("'", "\\'")}'"
|
19
19
|
elsif value.is_a?(Time)
|
20
20
|
if value.respond_to?(:zone)
|
21
|
-
"toDateTime('#{value.strftime('%
|
21
|
+
"toDateTime('#{value.strftime('%F %T')}', '#{value.zone}')"
|
22
22
|
else
|
23
|
-
"toDateTime('#{value.strftime('%
|
23
|
+
"toDateTime('#{value.strftime('%F %T')}')"
|
24
24
|
end
|
25
25
|
else
|
26
26
|
value.to_s
|
@@ -33,5 +33,37 @@ module ActiveHouse
|
|
33
33
|
parts.push('') if sql.end_with?('?')
|
34
34
|
parts
|
35
35
|
end
|
36
|
+
|
37
|
+
# @param condition [Hash]
|
38
|
+
def self.build_condition(condition)
|
39
|
+
return [condition.to_s] unless condition.is_a?(Hash)
|
40
|
+
|
41
|
+
condition.map do |field, value|
|
42
|
+
"#{field} #{sign_for_condition(value)} #{format_value(value)}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.sign_for_condition(value)
|
47
|
+
if value.is_a?(Array)
|
48
|
+
'IN'
|
49
|
+
elsif value.nil?
|
50
|
+
'IS'
|
51
|
+
else
|
52
|
+
'='
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.format_fields(model_class, fields)
|
57
|
+
raise ArgumentError, 'wrong number of arguments' if fields.empty?
|
58
|
+
|
59
|
+
fields.map do |field|
|
60
|
+
if field.is_a?(Symbol) && model_class._attribute_opts.key?(field)
|
61
|
+
opts = model_class._attribute_opts.fetch(field)
|
62
|
+
opts.key?(:select) ? "#{opts[:select]} AS #{field}" : field.to_s
|
63
|
+
else
|
64
|
+
field.to_s
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
36
68
|
end
|
37
69
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'plain_model/querying/base'
|
2
|
+
require 'plain_model/querying/except'
|
3
|
+
require 'plain_model/querying/with_model'
|
4
|
+
require_relative 'querying/select'
|
5
|
+
require_relative 'querying/from'
|
6
|
+
require_relative 'querying/where'
|
7
|
+
require_relative 'querying/order_by'
|
8
|
+
require_relative 'querying/group_by'
|
9
|
+
require_relative 'querying/having'
|
10
|
+
require_relative 'querying/limit'
|
11
|
+
require_relative 'querying/union'
|
12
|
+
require_relative 'querying/array_join'
|
13
|
+
require_relative 'querying/scope'
|
14
|
+
require_relative 'querying/collect'
|
15
|
+
|
16
|
+
module ActiveHouse
|
17
|
+
class QueryBuilder
|
18
|
+
include PlainModel::Querying::Base
|
19
|
+
include PlainModel::Querying::Except
|
20
|
+
include PlainModel::Querying::WithModel
|
21
|
+
|
22
|
+
include ActiveHouse::Querying::Select
|
23
|
+
include ActiveHouse::Querying::From
|
24
|
+
include ActiveHouse::Querying::Where
|
25
|
+
include ActiveHouse::Querying::OrderBy
|
26
|
+
include ActiveHouse::Querying::GroupBy
|
27
|
+
include ActiveHouse::Querying::Having
|
28
|
+
include ActiveHouse::Querying::Limit
|
29
|
+
include ActiveHouse::Querying::Union
|
30
|
+
include ActiveHouse::Querying::ArrayJoin
|
31
|
+
include ActiveHouse::Querying::Scope
|
32
|
+
include ActiveHouse::Querying::Collect
|
33
|
+
|
34
|
+
def initialize(model_class = nil)
|
35
|
+
super(model_class || ActiveHouse::Model)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module ActiveHouse
|
2
|
+
module Querying
|
3
|
+
module ArrayJoin
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
private :build_array_join_query_part
|
8
|
+
end
|
9
|
+
|
10
|
+
def build_array_join_query_part
|
11
|
+
parts = []
|
12
|
+
parts << "ARRAY JOIN #{values[:array_join].join(', ')}" unless values[:array_join].empty?
|
13
|
+
parts << "LEFT ARRAY JOIN #{values[:array_join].join(', ')}" unless values[:left_array_join].empty?
|
14
|
+
parts.join("\n")
|
15
|
+
end
|
16
|
+
|
17
|
+
def initial_values
|
18
|
+
super.merge array_join: [], left_array_join: []
|
19
|
+
end
|
20
|
+
|
21
|
+
def array_join!(*fields)
|
22
|
+
formatted_fields = ActiveHouse::PreparedStatement.format_fields(model_class, fields)
|
23
|
+
values[:array_join] = (values[:array_join] + formatted_fields).uniq
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def array_join(*fields)
|
28
|
+
dup.array_join!(*fields)
|
29
|
+
end
|
30
|
+
|
31
|
+
def left_array_join!(*fields)
|
32
|
+
formatted_fields = ActiveHouse::PreparedStatement.format_fields(model_class, fields)
|
33
|
+
values[:left_array_join] = (values[:left_array_join] + formatted_fields).uniq
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def left_array_join(*fields)
|
38
|
+
dup.left_array_join!(*fields)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|