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
@@ -1,27 +0,0 @@
|
|
1
|
-
module ActiveHouse
|
2
|
-
module Limitable
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
included do
|
6
|
-
private
|
7
|
-
|
8
|
-
def build_limit_query_part
|
9
|
-
return if @limit[:limit].nil?
|
10
|
-
if @limit[:offset]
|
11
|
-
"LIMIT #{@limit[:limit]}, #{@limit[:offset]}"
|
12
|
-
else
|
13
|
-
"LIMIT #{@limit[:limit]}"
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def initialize(*)
|
19
|
-
@limit = { offset: nil, limit: nil }
|
20
|
-
super
|
21
|
-
end
|
22
|
-
|
23
|
-
def limit(limit_value, offset_value = nil)
|
24
|
-
chain_query limit: { offset: offset_value || @limit[:offset], limit: limit_value }
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,100 +0,0 @@
|
|
1
|
-
require 'active_support/concern'
|
2
|
-
|
3
|
-
module ActiveHouse
|
4
|
-
module Modeling
|
5
|
-
extend ActiveSupport::Concern
|
6
|
-
|
7
|
-
included do
|
8
|
-
class_attribute :_attribute_opts, instance_writer: false
|
9
|
-
self._attribute_opts = {}
|
10
|
-
|
11
|
-
private
|
12
|
-
|
13
|
-
def parse_attribute_method_name(method_name)
|
14
|
-
name, is_setter = method_name.to_s.match(/\A(.+)?(=)?\z/).captures
|
15
|
-
name = name.to_sym
|
16
|
-
is_setter = !is_setter.nil?
|
17
|
-
[name, is_setter]
|
18
|
-
end
|
19
|
-
|
20
|
-
def attribute_method?(name, is_setter, *args)
|
21
|
-
(_attribute_opts.key?(name) || @_attributes.key?(name)) && (is_setter ? args.size == 1 : true)
|
22
|
-
end
|
23
|
-
|
24
|
-
def get_attribute(name)
|
25
|
-
@_attributes[name]
|
26
|
-
end
|
27
|
-
|
28
|
-
def set_attribute(name, value)
|
29
|
-
opts = _attribute_opts.fetch(name, {})
|
30
|
-
value = opts[:cast].call(value) if opts[:cast]
|
31
|
-
@_attributes[name] = value
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
class_methods do
|
36
|
-
def attribute(name, options = {})
|
37
|
-
name = name.to_sym
|
38
|
-
self._attribute_opts = _attribute_opts.merge(name => options)
|
39
|
-
define_method(name) do
|
40
|
-
get_attribute(name)
|
41
|
-
end
|
42
|
-
define_method("#{name}=") do |value|
|
43
|
-
set_attribute(name, value)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def attributes(*names)
|
48
|
-
options = names.extract_options!
|
49
|
-
names.each { |name| attribute(name, options.dup) }
|
50
|
-
end
|
51
|
-
|
52
|
-
def load!(params)
|
53
|
-
new.tap do |model|
|
54
|
-
params.each { |name, value| model[name] = value }
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def initialize(params = {})
|
60
|
-
@_attributes = {}
|
61
|
-
assign_attributes(params) unless params.nil?
|
62
|
-
end
|
63
|
-
|
64
|
-
def as_json(*_args)
|
65
|
-
to_h
|
66
|
-
end
|
67
|
-
|
68
|
-
def to_h
|
69
|
-
@_attributes.dup
|
70
|
-
end
|
71
|
-
|
72
|
-
def [](key)
|
73
|
-
get_attribute(key.to_sym)
|
74
|
-
end
|
75
|
-
|
76
|
-
def []=(key, value)
|
77
|
-
set_attribute(key.to_sym, value)
|
78
|
-
end
|
79
|
-
|
80
|
-
def assign_attributes(params)
|
81
|
-
params.each do |key, val|
|
82
|
-
public_send("#{key}=", val)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def respond_to_missing?(method_name, *args)
|
87
|
-
name, is_setter = parse_attribute_method_name(method_name)
|
88
|
-
attribute_method?(name, is_setter, *args)
|
89
|
-
end
|
90
|
-
|
91
|
-
def method_missing(method_name, *args, &block)
|
92
|
-
name, is_setter = parse_attribute_method_name(method_name)
|
93
|
-
if attribute_method?(name, is_setter, *args)
|
94
|
-
is_setter ? set_attribute(name, args.first) : get_attribute(name)
|
95
|
-
else
|
96
|
-
super
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/object/try'
|
2
|
-
|
3
|
-
module ActiveHouse
|
4
|
-
module Orderable
|
5
|
-
extend ActiveSupport::Concern
|
6
|
-
|
7
|
-
included do
|
8
|
-
private
|
9
|
-
|
10
|
-
def build_order_by_query_part
|
11
|
-
"ORDER BY #{@ordering.join(', ')}" unless @ordering.empty?
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def initialize(*)
|
16
|
-
@ordering = []
|
17
|
-
super
|
18
|
-
end
|
19
|
-
|
20
|
-
def order_by(*clauses)
|
21
|
-
raise ArgumentError, 'wrong number of arguments' if clauses.empty?
|
22
|
-
formatter_clauses = clauses.map do |clause|
|
23
|
-
if clause.is_a?(String)
|
24
|
-
clause
|
25
|
-
elsif clause.is_a?(Symbol)
|
26
|
-
clause.to_s
|
27
|
-
elsif clause.is_a?(Hash)
|
28
|
-
if clause.keys.one?
|
29
|
-
direction = clause.values.first
|
30
|
-
raise ArgumentError, 'direction must be asc or desc' unless [:asc, :desc].include?(direction.try!(:to_sym))
|
31
|
-
"#{clause.keys.first} #{direction.to_s.upcase}"
|
32
|
-
else
|
33
|
-
clause.assert_valid_keys(:field, :direction, :collate)
|
34
|
-
[
|
35
|
-
clause.fetch(:field),
|
36
|
-
clause[:direction].try!(:to_s).try!(:upcase),
|
37
|
-
clause.key?(:collate) ? "COLLATE '#{clause[:collate]}'" : nil
|
38
|
-
].reject(&:nil?).join(' ')
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
chain_query ordering: (@ordering + formatter_clauses).uniq
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
data/lib/active_house/query.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
require_relative 'chainable'
|
2
|
-
require_relative 'scopeable'
|
3
|
-
require_relative 'collectable'
|
4
|
-
|
5
|
-
module ActiveHouse
|
6
|
-
class Query
|
7
|
-
attr_reader :model_class
|
8
|
-
|
9
|
-
def initialize(model_class = ActiveHouse::Model)
|
10
|
-
@model_class = model_class
|
11
|
-
super()
|
12
|
-
end
|
13
|
-
|
14
|
-
def connection
|
15
|
-
model_class.connection
|
16
|
-
end
|
17
|
-
|
18
|
-
include ActiveHouse::Chainable
|
19
|
-
include ActiveHouse::Collectable
|
20
|
-
include ActiveHouse::Scopeable
|
21
|
-
end
|
22
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'active_support/concern'
|
2
|
-
require 'active_support/core_ext/module/delegation'
|
3
|
-
|
4
|
-
module ActiveHouse
|
5
|
-
module Querying
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
|
8
|
-
included do
|
9
|
-
class_attribute :_query_class, instance_accessor: false
|
10
|
-
self._query_class = ActiveHouse::Query
|
11
|
-
end
|
12
|
-
|
13
|
-
class_methods do
|
14
|
-
delegate :to_a, :select, :where, :group_by, :limit, :order_by, :having, :from, to: :all
|
15
|
-
|
16
|
-
def all
|
17
|
-
_query_class.new(self)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'active_support/concern'
|
2
|
-
|
3
|
-
module ActiveHouse
|
4
|
-
module Scopeable
|
5
|
-
extend ActiveSupport::Concern
|
6
|
-
|
7
|
-
included do
|
8
|
-
private
|
9
|
-
|
10
|
-
def apply_scope(name, *args)
|
11
|
-
scope = model_class._scopes.fetch(name.to_sym)
|
12
|
-
instance_exec(*args, &scope)
|
13
|
-
end
|
14
|
-
|
15
|
-
def scope?(name)
|
16
|
-
model_class._scopes.key?(name.to_sym)
|
17
|
-
end
|
18
|
-
|
19
|
-
def apply_default_scope
|
20
|
-
return if model_class._default_scope.nil?
|
21
|
-
apply_scope(model_class._default_scope)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def initialize(*)
|
26
|
-
super
|
27
|
-
with_current_query { apply_default_scope }
|
28
|
-
end
|
29
|
-
|
30
|
-
def respond_to_missing?(method_name, *_args)
|
31
|
-
scope?(method_name) || super
|
32
|
-
end
|
33
|
-
|
34
|
-
def method_missing(method_name, *args, &_block)
|
35
|
-
if scope?(method_name)
|
36
|
-
apply_scope(method_name, *args)
|
37
|
-
else
|
38
|
-
super
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
data/lib/active_house/scoping.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'active_support/concern'
|
2
|
-
|
3
|
-
module ActiveHouse
|
4
|
-
module Scoping
|
5
|
-
extend ActiveSupport::Concern
|
6
|
-
|
7
|
-
included do
|
8
|
-
class_attribute :_default_scope, instance_accessor: false
|
9
|
-
class_attribute :_scopes, instance_accessor: false
|
10
|
-
self._scopes = {}
|
11
|
-
end
|
12
|
-
|
13
|
-
class_methods do
|
14
|
-
def default_scope(name)
|
15
|
-
self._default_scope = name.to_sym
|
16
|
-
end
|
17
|
-
|
18
|
-
def scope(name, block)
|
19
|
-
self._scopes = _scopes.merge(name.to_sym => block)
|
20
|
-
end
|
21
|
-
|
22
|
-
def respond_to_missing?(method_name, *_args)
|
23
|
-
_scopes.key?(method_name.to_sym)
|
24
|
-
end
|
25
|
-
|
26
|
-
def method_missing(method_name, *args, &_block)
|
27
|
-
method_name = method_name.to_sym
|
28
|
-
if _scopes.key?(method_name)
|
29
|
-
scope = _scopes.fetch(method_name)
|
30
|
-
all.instance_exec(*args, &scope)
|
31
|
-
else
|
32
|
-
super
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
module ActiveHouse
|
2
|
-
module Selectable
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
included do
|
6
|
-
private
|
7
|
-
|
8
|
-
def build_select_query_part
|
9
|
-
if !@fields.empty?
|
10
|
-
"SELECT\n#{@fields.join(",\n")}"
|
11
|
-
else
|
12
|
-
'SELECT *'
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def initialize(*)
|
18
|
-
@fields = []
|
19
|
-
super
|
20
|
-
end
|
21
|
-
|
22
|
-
def select(*fields)
|
23
|
-
raise ArgumentError, 'wrong number of arguments' if fields.empty?
|
24
|
-
formatted_fields = fields.map do |field|
|
25
|
-
if field.is_a?(Symbol) && model_class._attribute_opts.key?(field)
|
26
|
-
opts = model_class._attribute_opts.fetch(field)
|
27
|
-
opts.key?(:select) ? "#{opts[:select]} AS #{field}" : field.to_s
|
28
|
-
else
|
29
|
-
field.to_s
|
30
|
-
end
|
31
|
-
end
|
32
|
-
chain_query fields: (@fields + formatted_fields).uniq
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
module ActiveHouse
|
2
|
-
module Unionable
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
included do
|
6
|
-
private
|
7
|
-
|
8
|
-
def build_union_query_part
|
9
|
-
"UNION ALL\n#{@unions.values.map(&:to_query).join("\n")}" unless @unions.values.empty?
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def initialize(*)
|
14
|
-
@unions = {}
|
15
|
-
super
|
16
|
-
end
|
17
|
-
|
18
|
-
def union(name, query)
|
19
|
-
query = query.all if query.is_a?(ActiveHouse::Model)
|
20
|
-
raise ArgumentError, 'argument must be model or query object' unless query.is_a?(ActiveHouse::Query)
|
21
|
-
new_unions = @unions.map { |n, q| [n, q.dup] }.to_h
|
22
|
-
new_unions[name] = query.dup
|
23
|
-
chain_query unions: new_unions
|
24
|
-
end
|
25
|
-
|
26
|
-
def update_union(name)
|
27
|
-
raise ArgumentError, "can't find union by name #{name}" unless @unions.key?(name)
|
28
|
-
new_union = yield union_for(name)
|
29
|
-
union(name, new_union)
|
30
|
-
end
|
31
|
-
|
32
|
-
def union_for(name)
|
33
|
-
raise ArgumentError, "can't find union by name #{name}" unless @unions.key?(name)
|
34
|
-
@unions[name].dup
|
35
|
-
end
|
36
|
-
|
37
|
-
def except_union(name)
|
38
|
-
new_unions = @unions.map { |n, q| [n, q.dup] }.to_h
|
39
|
-
new_unions.delete(name)
|
40
|
-
chain_query unions: new_unions
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
require_relative 'prepared_statement'
|
2
|
-
require 'active_support/core_ext/array/wrap'
|
3
|
-
|
4
|
-
module ActiveHouse
|
5
|
-
module Whereable
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
|
8
|
-
included do
|
9
|
-
private
|
10
|
-
|
11
|
-
def format_condition(*conditions)
|
12
|
-
raise ArgumentError, 'wrong number of arguments' if conditions.empty?
|
13
|
-
return ActiveHouse::PreparedStatement.prepare_sql(*conditions) if conditions.size > 1
|
14
|
-
condition = conditions.first
|
15
|
-
if condition.is_a?(Hash)
|
16
|
-
condition.map do |field, value|
|
17
|
-
"#{field} #{sign_for_condition(value)} #{ActiveHouse::PreparedStatement.format_value(value)}"
|
18
|
-
end
|
19
|
-
else
|
20
|
-
condition.to_s
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def sign_for_condition(value)
|
25
|
-
if value.is_a?(Array)
|
26
|
-
'IN'
|
27
|
-
elsif value.nil?
|
28
|
-
'IS'
|
29
|
-
else
|
30
|
-
'='
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def build_where_query_part
|
35
|
-
"WHERE\n" + @conditions.join(" AND\n") unless @conditions.empty?
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def initialize(*)
|
40
|
-
@conditions = []
|
41
|
-
super
|
42
|
-
end
|
43
|
-
|
44
|
-
def where(*conditions)
|
45
|
-
raise ArgumentError, 'wrong number of arguments' if conditions.empty?
|
46
|
-
formatted_conditions = Array.wrap(format_condition(*conditions))
|
47
|
-
chain_query conditions: (@conditions + formatted_conditions).uniq
|
48
|
-
end
|
49
|
-
|
50
|
-
def where_not(*conditions)
|
51
|
-
raise ArgumentError, 'wrong number of arguments' if conditions.empty?
|
52
|
-
formatted_conditions = Array.wrap(format_condition(*conditions))
|
53
|
-
negative_condition = "NOT (#{formatted_conditions.join(' AND ')})"
|
54
|
-
chain_query conditions: (@conditions + [negative_condition]).uniq
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|