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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +9 -0
  3. data/active_house.gemspec +1 -0
  4. data/lib/active_house.rb +1 -1
  5. data/lib/active_house/connection.rb +3 -3
  6. data/lib/active_house/exceptions.rb +9 -0
  7. data/lib/active_house/{logger.rb → logging.rb} +1 -1
  8. data/lib/active_house/model.rb +14 -12
  9. data/lib/active_house/modeling/attributes.rb +102 -0
  10. data/lib/active_house/modeling/connection.rb +38 -0
  11. data/lib/active_house/modeling/query.rb +29 -0
  12. data/lib/active_house/modeling/scope.rb +42 -0
  13. data/lib/active_house/prepared_statement.rb +34 -2
  14. data/lib/active_house/query_builder.rb +38 -0
  15. data/lib/active_house/querying/array_join.rb +42 -0
  16. data/lib/active_house/querying/collect.rb +80 -0
  17. data/lib/active_house/querying/from.rb +30 -0
  18. data/lib/active_house/querying/group_by.rb +30 -0
  19. data/lib/active_house/querying/having.rb +41 -0
  20. data/lib/active_house/querying/limit.rb +35 -0
  21. data/lib/active_house/querying/order_by.rb +58 -0
  22. data/lib/active_house/querying/scope.rb +45 -0
  23. data/lib/active_house/querying/select.rb +35 -0
  24. data/lib/active_house/querying/union.rb +67 -0
  25. data/lib/active_house/querying/where.rb +50 -0
  26. data/lib/active_house/version.rb +1 -1
  27. metadata +34 -22
  28. data/lib/active_house/array_joinable.rb +0 -31
  29. data/lib/active_house/chainable.rb +0 -151
  30. data/lib/active_house/collectable.rb +0 -44
  31. data/lib/active_house/connecting.rb +0 -36
  32. data/lib/active_house/connection_error.rb +0 -6
  33. data/lib/active_house/error.rb +0 -4
  34. data/lib/active_house/fromable.rb +0 -29
  35. data/lib/active_house/groupable.rb +0 -23
  36. data/lib/active_house/havingable.rb +0 -50
  37. data/lib/active_house/limitable.rb +0 -27
  38. data/lib/active_house/modeling.rb +0 -100
  39. data/lib/active_house/orderable.rb +0 -45
  40. data/lib/active_house/query.rb +0 -22
  41. data/lib/active_house/querying.rb +0 -21
  42. data/lib/active_house/scopeable.rb +0 -42
  43. data/lib/active_house/scoping.rb +0 -37
  44. data/lib/active_house/selectable.rb +0 -35
  45. data/lib/active_house/unionable.rb +0 -43
  46. data/lib/active_house/whereable.rb +0 -57
@@ -1,3 +1,3 @@
1
1
  module ActiveHouse
2
- VERSION = '0.4.0'.freeze
2
+ VERSION = '0.5.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_house
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Denis Talakevich
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-08-02 00:00:00.000000000 Z
11
+ date: 2019-08-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.1.10
55
+ - !ruby/object:Gem::Dependency
56
+ name: plain_model
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.2'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.2'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: bundler
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -113,31 +127,29 @@ files:
113
127
  - bin/console
114
128
  - bin/setup
115
129
  - lib/active_house.rb
116
- - lib/active_house/array_joinable.rb
117
- - lib/active_house/chainable.rb
118
- - lib/active_house/collectable.rb
119
130
  - lib/active_house/configuration.rb
120
- - lib/active_house/connecting.rb
121
131
  - lib/active_house/connection.rb
122
- - lib/active_house/connection_error.rb
123
- - lib/active_house/error.rb
124
- - lib/active_house/fromable.rb
125
- - lib/active_house/groupable.rb
126
- - lib/active_house/havingable.rb
127
- - lib/active_house/limitable.rb
128
- - lib/active_house/logger.rb
132
+ - lib/active_house/exceptions.rb
133
+ - lib/active_house/logging.rb
129
134
  - lib/active_house/model.rb
130
- - lib/active_house/modeling.rb
131
- - lib/active_house/orderable.rb
135
+ - lib/active_house/modeling/attributes.rb
136
+ - lib/active_house/modeling/connection.rb
137
+ - lib/active_house/modeling/query.rb
138
+ - lib/active_house/modeling/scope.rb
132
139
  - lib/active_house/prepared_statement.rb
133
- - lib/active_house/query.rb
134
- - lib/active_house/querying.rb
135
- - lib/active_house/scopeable.rb
136
- - lib/active_house/scoping.rb
137
- - lib/active_house/selectable.rb
138
- - lib/active_house/unionable.rb
140
+ - lib/active_house/query_builder.rb
141
+ - lib/active_house/querying/array_join.rb
142
+ - lib/active_house/querying/collect.rb
143
+ - lib/active_house/querying/from.rb
144
+ - lib/active_house/querying/group_by.rb
145
+ - lib/active_house/querying/having.rb
146
+ - lib/active_house/querying/limit.rb
147
+ - lib/active_house/querying/order_by.rb
148
+ - lib/active_house/querying/scope.rb
149
+ - lib/active_house/querying/select.rb
150
+ - lib/active_house/querying/union.rb
151
+ - lib/active_house/querying/where.rb
139
152
  - lib/active_house/version.rb
140
- - lib/active_house/whereable.rb
141
153
  homepage: https://github.com/senid231/active_house
142
154
  licenses:
143
155
  - MIT
@@ -1,31 +0,0 @@
1
- module ActiveHouse
2
- module ArrayJoinable
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- private
7
-
8
- def build_array_join_query_part
9
- "ARRAY JOIN #{@array_joins.join(', ')}" unless @array_joins.empty?
10
- end
11
- end
12
-
13
- def initialize(*)
14
- @array_joins = []
15
- super
16
- end
17
-
18
- def array_join(*fields)
19
- raise ArgumentError, 'wrong number of arguments' if fields.empty?
20
- formatted_fields = fields.map do |field|
21
- if field.is_a?(Symbol) && model_class._attribute_opts.key?(field)
22
- opts = model_class._attribute_opts.fetch(field)
23
- opts.key?(:select) ? "#{opts[:select]} AS #{field}" : field.to_s
24
- else
25
- field.to_s
26
- end
27
- end
28
- chain_query array_joins: (@array_joins + formatted_fields).uniq
29
- end
30
- end
31
- end
@@ -1,151 +0,0 @@
1
- require_relative 'selectable'
2
- require_relative 'fromable'
3
- require_relative 'whereable'
4
- require_relative 'orderable'
5
- require_relative 'groupable'
6
- require_relative 'limitable'
7
- require_relative 'havingable'
8
- require_relative 'unionable'
9
- require_relative 'array_joinable'
10
- require 'active_support/concern'
11
-
12
- module ActiveHouse
13
- module Chainable
14
- extend ActiveSupport::Concern
15
-
16
- include ActiveHouse::Selectable
17
- include ActiveHouse::Fromable
18
- include ActiveHouse::Whereable
19
- include ActiveHouse::Orderable
20
- include ActiveHouse::Groupable
21
- include ActiveHouse::Havingable
22
- include ActiveHouse::Limitable
23
- include ActiveHouse::Unionable
24
- include ActiveHouse::ArrayJoinable
25
-
26
- included do
27
- protected
28
-
29
- def data
30
- chain_methods.values.map { |var| [var, instance_variable_get(:"@#{var}")] }.to_h
31
- end
32
-
33
- def data=(other_data)
34
- chain_methods.values.each do |var|
35
- value = other_data.fetch(var)
36
- instance_variable_set(:"@#{var}", value.nil? ? nil : value.dup)
37
- end
38
- end
39
-
40
- def query_parts
41
- [
42
- build_select_query_part,
43
- build_from_query_part,
44
- build_array_join_query_part,
45
- build_where_query_part,
46
- build_group_by_query_part,
47
- build_having_query_part,
48
- build_order_by_query_part,
49
- build_limit_query_part,
50
- build_union_query_part
51
- ]
52
- end
53
-
54
- def build_query
55
- query_parts.reject(&:nil?).join("\n")
56
- end
57
-
58
- private
59
-
60
- # By default each chain method (select, where, group_by) returns new instance of query
61
- # but in some cases we need to modify and return existing query object
62
- # (for example when we apply default_scope on query initialize).
63
- # For this you need just to wrap code that appends chain methods with #with_current_query.
64
- # Example:
65
- #
66
- # scope1 = SomeModel.all # object id #1
67
- # scope2 = scope1.where(id: 3) # object id #2
68
- # scope3 = scope2.send(:with_current_query) { scope2.where(success: true) } # object id #2
69
- #
70
- def with_current_query
71
- @_with_current_query = true
72
- yield
73
- ensure
74
- @_with_current_query = false
75
- end
76
-
77
- def chain_query(options = {})
78
- options.assert_valid_keys(*chain_methods.values)
79
- if @_with_current_query
80
- self.data = data.merge(options)
81
- self
82
- else
83
- new_instance = self.class.new(model_class)
84
- new_instance.data = data.merge(options)
85
- new_instance
86
- end
87
- end
88
- end
89
-
90
- def initialize(*)
91
- @_with_current_query = false
92
- super
93
- end
94
-
95
- # key - chain method name
96
- # value - instance variable name that which store values
97
- def chain_methods
98
- {
99
- select: :fields,
100
- where: :conditions,
101
- group_by: :grouping,
102
- order_by: :ordering,
103
- limit: :limit,
104
- having: :having,
105
- union: :unions,
106
- from: :subquery,
107
- array_join: :array_joins
108
- }
109
- end
110
-
111
- # key - instance variable name that which store values
112
- # value - default value for the variable
113
- def chain_defaults
114
- {
115
- fields: [],
116
- conditions: [],
117
- grouping: [],
118
- ordering: [],
119
- limit: { offset: nil, limit: nil },
120
- having: [],
121
- union: {},
122
- subquery: nil,
123
- array_joins: []
124
- }
125
- end
126
-
127
- def except(*values)
128
- raise ArgumentError, 'wrong number of arguments' if values.empty?
129
- not_allowed = values - chain_methods.keys
130
- unless not_allowed.empty?
131
- raise ArgumentError, "Values #{not_allowed} are not allowed, allowed only #{chain_methods.keys}."
132
- end
133
-
134
- new_data = {}
135
- chain_methods.each do |meth, var|
136
- new_data[var] = chain_defaults[var].dup if values.include?(meth)
137
- end
138
- chain_query(new_data)
139
- end
140
-
141
- def to_query
142
- build_query
143
- end
144
-
145
- def dup
146
- chain_query
147
- end
148
-
149
- alias clone dup
150
- end
151
- end
@@ -1,44 +0,0 @@
1
- require 'active_support/concern'
2
- require 'active_support/core_ext/string/filters'
3
- require 'active_support/core_ext/module/delegation'
4
-
5
- module ActiveHouse
6
- module Collectable
7
- extend ActiveSupport::Concern
8
-
9
- def initialize(*)
10
- @collection = nil
11
- super
12
- end
13
-
14
- def to_a
15
- collection
16
- end
17
-
18
- def reset
19
- @collection = nil
20
- end
21
-
22
- def loaded?
23
- !@collection.nil?
24
- end
25
-
26
- def to_hashes
27
- connection.select_rows(to_query.squish)
28
- end
29
-
30
- def collection
31
- @collection ||= fetch_collection
32
- end
33
-
34
- def fetch_collection
35
- to_hashes.map { |row| model_class.load!(row) }
36
- end
37
-
38
- included do
39
- private :collection, :fetch_collection
40
- delegate :each, :size, :count, :map, :collect, :detect, :filter, :reject, :inject, :reduce, :all?, :any?,
41
- to: :to_a
42
- end
43
- end
44
- end
@@ -1,36 +0,0 @@
1
- require_relative 'connection'
2
- require_relative 'configuration'
3
- require 'active_support/core_ext/class/attribute'
4
- require 'active_support/concern'
5
-
6
- module ActiveHouse
7
- module Connecting
8
- extend ActiveSupport::Concern
9
-
10
- included do
11
- class_attribute :_connection_class, instance_accessor: false
12
- class_attribute :_connection, instance_accessor: false
13
- self._connection_class = ActiveHouse::Connection
14
- end
15
-
16
- class_methods do
17
- def ensure_connection
18
- establish_connection if _connection.nil?
19
- end
20
-
21
- def establish_connection(name_or_config = nil)
22
- config = if name_or_config.is_a?(Hash)
23
- name_or_config.symbolize_keys
24
- else
25
- ActiveHouse.configuration.connection_config_for(name_or_config)
26
- end
27
- self._connection = _connection_class.new(config)
28
- end
29
-
30
- def connection
31
- ensure_connection
32
- _connection
33
- end
34
- end
35
- end
36
- end
@@ -1,6 +0,0 @@
1
- require_relative 'error'
2
-
3
- module ActiveHouse
4
- class ConnectionError < Error
5
- end
6
- end
@@ -1,4 +0,0 @@
1
- module ActiveHouse
2
- class Error < ::StandardError
3
- end
4
- end
@@ -1,29 +0,0 @@
1
- module ActiveHouse
2
- module Fromable
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- private
7
-
8
- def from_subquery
9
- return model_class._table_name if @subquery.nil?
10
- query = @subquery.is_a?(ActiveHouse::Query) ? @subquery.to_query : @subquery
11
- "( #{query} )"
12
- end
13
-
14
- def build_from_query_part
15
- "FROM #{from_subquery}"
16
- end
17
- end
18
-
19
- def initialize(*)
20
- @subquery = nil
21
- super
22
- end
23
-
24
- def from(table_or_subquery)
25
- raise ArgumentError, '' if !table_or_subquery.is_a?(ActiveHouse::Query) && !table_or_subquery.is_a?(String)
26
- chain_query subquery: table_or_subquery.dup
27
- end
28
- end
29
- end
@@ -1,23 +0,0 @@
1
- module ActiveHouse
2
- module Groupable
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- private
7
-
8
- def build_group_by_query_part
9
- "GROUP BY #{@grouping.join(', ')}" unless @grouping.empty?
10
- end
11
- end
12
-
13
- def initialize(*)
14
- @grouping = []
15
- super
16
- end
17
-
18
- def group_by(*fields)
19
- raise ArgumentError, 'wrong number of arguments' if fields.empty?
20
- chain_query grouping: (@grouping + fields.map(&:to_s)).uniq
21
- end
22
- end
23
- end
@@ -1,50 +0,0 @@
1
- require_relative 'prepared_statement'
2
- require 'active_support/core_ext/array/wrap'
3
-
4
- module ActiveHouse
5
- module Havingable
6
- extend ActiveSupport::Concern
7
-
8
- included do
9
- private
10
-
11
- def format_having(*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_having(value)} #{ActiveHouse::PreparedStatement.format_value(value)}"
18
- end
19
- else
20
- condition.to_s
21
- end
22
- end
23
-
24
- def sign_for_having(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_having_query_part
35
- "HAVING\n" + @having.join(" AND\n") unless @having.empty?
36
- end
37
- end
38
-
39
- def initialize(*)
40
- @having = []
41
- super
42
- end
43
-
44
- def having(*conditions)
45
- raise ArgumentError, 'wrong number of arguments' if conditions.empty?
46
- formatted_conditions = Array.wrap(format_having(*conditions))
47
- chain_query having: (@having + formatted_conditions).uniq
48
- end
49
- end
50
- end