active_house 0.1.5 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 85e74ee14ef20d87860ffb175ba8adeef0488777
4
- data.tar.gz: 226c0ae19eb0e1c451ac7bcbcfec035bbd602f16
3
+ metadata.gz: d444148c72cbef93a8a193e8c73079791e77ecc4
4
+ data.tar.gz: 9fbcef6e31a2627dbc822dddc64d72b1dcb1a3ec
5
5
  SHA512:
6
- metadata.gz: aa2e80513b87275dd3996c09f6c6e63c7392fa0ab930468f1ec7fc08ae389b71d9be993cff385d1dcb6b5d98f056115dedbf1c0079164fe55dd807f1d0f09842
7
- data.tar.gz: 35c22b8dc84e426b967a10169aa707979e3ed6a5ffb472c25c6092f4dccaadd384facc4c09de719e8e9fadafe29bfd3da9c3c7e8d458a06f571045497420d8ce
6
+ metadata.gz: 92e3a2d335222804ef4f09ce2ed8037ffee60b496d6a3d70e1dabfeb86fa87242900a91b72f538c227eb30c9a4241e4707ef92fa5bfd95d9455a835b409bd660
7
+ data.tar.gz: 1e744dc7fa583e5d1861bf8561b4a7165f3624369af37110f05b493825dff5b5d9778c4ab0b5468838647875960e9b70705d57548af4d93db8d68bc59bd20c14
@@ -4,6 +4,8 @@ require_relative 'whereable'
4
4
  require_relative 'orderable'
5
5
  require_relative 'groupable'
6
6
  require_relative 'limitable'
7
+ require_relative 'havingable'
8
+ require_relative 'unionable'
7
9
  require 'active_support/concern'
8
10
 
9
11
  module ActiveHouse
@@ -15,7 +17,9 @@ module ActiveHouse
15
17
  include ActiveHouse::Whereable
16
18
  include ActiveHouse::Orderable
17
19
  include ActiveHouse::Groupable
20
+ include ActiveHouse::Havingable
18
21
  include ActiveHouse::Limitable
22
+ include ActiveHouse::Unionable
19
23
 
20
24
  included do
21
25
  protected
@@ -26,7 +30,8 @@ module ActiveHouse
26
30
 
27
31
  def data=(other_data)
28
32
  chain_methods.values.each do |var|
29
- instance_variable_set(:"@#{var}", other_data.fetch(var).dup)
33
+ value = other_data.fetch(var)
34
+ instance_variable_set(:"@#{var}", value.nil? ? nil : value.dup)
30
35
  end
31
36
  end
32
37
 
@@ -36,8 +41,10 @@ module ActiveHouse
36
41
  build_from_query_part,
37
42
  build_where_query_part,
38
43
  build_group_by_query_part,
44
+ build_having_query_part,
39
45
  build_order_by_query_part,
40
- build_limit_query_part
46
+ build_limit_query_part,
47
+ build_union_query_part
41
48
  ]
42
49
  end
43
50
 
@@ -90,7 +97,23 @@ module ActiveHouse
90
97
  where: :conditions,
91
98
  group_by: :grouping,
92
99
  order_by: :ordering,
93
- limit: :limit
100
+ limit: :limit,
101
+ having: :having,
102
+ union: :unions,
103
+ from: :subquery
104
+ }
105
+ end
106
+
107
+ def chain_defaults
108
+ {
109
+ fields: [],
110
+ conditions: [],
111
+ grouping: [],
112
+ ordering: [],
113
+ limit: { offset: nil, limit: nil },
114
+ having: [],
115
+ union: {},
116
+ subquery: nil,
94
117
  }
95
118
  end
96
119
 
@@ -103,7 +126,7 @@ module ActiveHouse
103
126
 
104
127
  new_data = {}
105
128
  chain_methods.each do |meth, var|
106
- new_data[var] = [] if values.include?(meth)
129
+ new_data[var] = chain_defaults[var].dup if values.include?(meth)
107
130
  end
108
131
  chain_query(new_data)
109
132
  end
@@ -5,18 +5,25 @@ module ActiveHouse
5
5
  included do
6
6
  private
7
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
+
8
14
  def build_from_query_part
9
- "FROM #{table_name}"
15
+ "FROM #{from_subquery}"
10
16
  end
11
17
  end
12
18
 
13
19
  def initialize(*)
14
- @table_name = model_class._table_name
20
+ @subquery = nil
15
21
  super
16
22
  end
17
23
 
18
- def table_name
19
- @table_name
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
20
27
  end
21
28
  end
22
29
  end
@@ -0,0 +1,50 @@
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
@@ -6,22 +6,22 @@ module ActiveHouse
6
6
  private
7
7
 
8
8
  def build_limit_query_part
9
- return if @limit.empty?
10
- if @limit[1]
11
- "LIMIT #{@limit[0]}, #{@limit[1]}"
9
+ return if @limit[:limit].nil?
10
+ if @limit[:offset]
11
+ "LIMIT #{@limit[:limit]}, #{@limit[:offset]}"
12
12
  else
13
- "LIMIT #{@limit[0]}"
13
+ "LIMIT #{@limit[:limit]}"
14
14
  end
15
15
  end
16
16
  end
17
17
 
18
18
  def initialize(*)
19
- @limit = []
19
+ @limit = { offset: nil, limit: nil }
20
20
  super
21
21
  end
22
22
 
23
23
  def limit(limit_value, offset_value = nil)
24
- chain_query limit: (@limit + [limit_value, offset_value]).uniq
24
+ chain_query limit: { offset: offset_value || @limit[:offset], limit: limit_value }
25
25
  end
26
26
  end
27
27
  end
@@ -38,7 +38,7 @@ module ActiveHouse
38
38
 
39
39
  def attributes(*names)
40
40
  options = names.extract_options!
41
- names.each { |name| attributes(name, options.dup) }
41
+ names.each { |name| attribute(name, options.dup) }
42
42
  end
43
43
 
44
44
  def load!(params)
@@ -1,3 +1,5 @@
1
+ require 'active_support/core_ext/object/try'
2
+
1
3
  module ActiveHouse
2
4
  module Orderable
3
5
  extend ActiveSupport::Concern
@@ -25,7 +27,7 @@ module ActiveHouse
25
27
  elsif clause.is_a?(Hash)
26
28
  if clause.keys.one?
27
29
  direction = clause.values.first
28
- raise ArgumentError, 'direction must be asc or desc' if [:asc, :desc].exclude?(direction.try!(:to_sym))
30
+ raise ArgumentError, 'direction must be asc or desc' unless [:asc, :desc].include?(direction.try!(:to_sym))
29
31
  "#{clause.keys.first} #{direction.to_s.upcase}"
30
32
  else
31
33
  clause.assert_valid_keys(:field, :direction, :collate)
@@ -11,7 +11,7 @@ module ActiveHouse
11
11
  end
12
12
 
13
13
  class_methods do
14
- delegate :to_a, :select, :where, :group_by, :limit, to: :all
14
+ delegate :to_a, :select, :where, :group_by, :limit, :order_by, :having, to: :all
15
15
 
16
16
  def all
17
17
  _query_class.new(self)
@@ -0,0 +1,43 @@
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, &block)
27
+ raise ArgumentError, "can't find union by name #{name}" unless @unions.key?(name)
28
+ new_union = block.call 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,3 +1,3 @@
1
1
  module ActiveHouse
2
- VERSION = '0.1.5'.freeze
2
+ VERSION = '0.2.0'.freeze
3
3
  end
@@ -8,10 +8,6 @@ module ActiveHouse
8
8
  included do
9
9
  private
10
10
 
11
- def format_condition_value(value)
12
- ActiveHouse::PreparedStatement.format_value(value)
13
- end
14
-
15
11
  def format_condition(*conditions)
16
12
  raise ArgumentError, 'wrong number of arguments' if conditions.empty?
17
13
  return ActiveHouse::PreparedStatement.prepare_sql(*conditions) if conditions.size > 1
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.1.5
4
+ version: 0.2.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: 2018-07-25 00:00:00.000000000 Z
11
+ date: 2018-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -122,6 +122,7 @@ files:
122
122
  - lib/active_house/error.rb
123
123
  - lib/active_house/fromable.rb
124
124
  - lib/active_house/groupable.rb
125
+ - lib/active_house/havingable.rb
125
126
  - lib/active_house/limitable.rb
126
127
  - lib/active_house/logger.rb
127
128
  - lib/active_house/model.rb
@@ -133,6 +134,7 @@ files:
133
134
  - lib/active_house/scopeable.rb
134
135
  - lib/active_house/scoping.rb
135
136
  - lib/active_house/selectable.rb
137
+ - lib/active_house/unionable.rb
136
138
  - lib/active_house/version.rb
137
139
  - lib/active_house/whereable.rb
138
140
  homepage: https://github.com/senid231/active_house