active_house 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|