occams-record 1.0.0.rc8 → 1.0.0.rc9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 77e8b9c5da26d6d76932bfca57a9470648e97bb07ca33ee3fbdfe7fa5e67aed7
4
- data.tar.gz: 694e75291ee550813f0732cd8d4d2361e5c6e44f324637789af0afa4637e7865
3
+ metadata.gz: dffcac805f1cbe701d082c2b965aeaa98c89c289fbb1d5bf3e164e5ce5ad8af1
4
+ data.tar.gz: a94cda603a6c408c77f751e2d9358a1f52decb34464bbd8967af9f16fd978712
5
5
  SHA512:
6
- metadata.gz: 5831bafffa9f1da1677d2dff25d59d9a1480be2db886a0e275fa9a7e0d7f874dd22314bd18632df383e7213cb5e0fd50b046a526e44d5cae553c7d807af6bb0a
7
- data.tar.gz: 40ab48b4680d2cf5aabbd48fa90e5564111fc77239bbfa6a0ec7ecdd7f3cc05bb4a906fd28134706a9a216c0eb8c2c9b9cf449791ec1a6dc225334d9fe356233
6
+ metadata.gz: afeb27a07b31d12257161618ea4d9a17088963014d354691de035b3e0e423d7f8d5d1c62991f4c9256282ec7ab4afecf32806ba4f56182cdb9d36a91e4436bf0
7
+ data.tar.gz: aecefa1ddbcb7179b5b24805d1ffcadbd71a25a1f4888c8bb89a433f7900f39dd576885a4e85e33502f568cef82b9da04eccdcaa3f4d9c44964ac59631595442
@@ -2,7 +2,8 @@ require 'active_record'
2
2
  require 'occams-record/version'
3
3
  require 'occams-record/merge'
4
4
  require 'occams-record/eager_loaders'
5
- require 'occams-record/results'
5
+ require 'occams-record/results/results'
6
+ require 'occams-record/results/row'
6
7
  require 'occams-record/query'
7
8
  require 'occams-record/raw_query'
8
9
  require 'occams-record/errors'
@@ -56,13 +56,14 @@ module OccamsRecord
56
56
  node.send(link.name).reduce(Set.new) { |a, child|
57
57
  result = reduce(child, depth + 1)
58
58
  case result
59
+ when nil then a
59
60
  when Array then a + result
60
61
  else a << result
61
62
  end
62
63
  }.to_a
63
64
  when :has_one, :belongs_to
64
65
  child = node.send(link.name)
65
- reduce(child, depth + 1)
66
+ child ? reduce(child, depth + 1) : nil
66
67
  else
67
68
  raise "Unsupported through chain link type '#{link.macro}'"
68
69
  end
@@ -0,0 +1,69 @@
1
+ module OccamsRecord
2
+ # Classes and methods for handing query results.
3
+ module Results
4
+ # ActiveRecord's internal type casting API changes from version to version.
5
+ CASTER = case ActiveRecord::VERSION::MAJOR
6
+ when 4 then :type_cast_from_database
7
+ when 5 then :deserialize
8
+ end
9
+
10
+ #
11
+ # Dynamically build a class for a specific set of result rows. It inherits from OccamsRecord::Results::Row, and optionall includes
12
+ # a user-defined module.
13
+ #
14
+ # @param column_names [Array<String>] the column names in the result set. The order MUST match the order returned by the query.
15
+ # @param column_types [Hash] Column name => type from an ActiveRecord::Result
16
+ # @param association_names [Array<String>] names of associations that will be eager loaded into the results.
17
+ # @param model [ActiveRecord::Base] the AR model representing the table (it holds column & type info).
18
+ # @param modules [Array<Module>] (optional)
19
+ # @return [OccamsRecord::Results::Row] a class customized for this result set
20
+ #
21
+ def self.klass(column_names, column_types, association_names = [], model: nil, modules: nil)
22
+ Class.new(Results::Row) do
23
+ Array(modules).each { |mod| prepend mod } if modules
24
+
25
+ self.columns = column_names.map(&:to_s)
26
+ self.associations = association_names.map(&:to_s)
27
+ self.model_name = model ? model.name : nil
28
+ self.table_name = model ? model.table_name : nil
29
+ self.primary_key = model&.primary_key&.to_s
30
+
31
+ # Build getters & setters for associations. (We need setters b/c they're set AFTER the row is initialized
32
+ attr_accessor(*association_names)
33
+
34
+ # Build id getters for associations, e.g. "widget_ids" for "widgets"
35
+ self.associations.each do |assoc|
36
+ if (ref = model.reflections[assoc]) and !ref.polymorphic? and (ref.macro == :has_many or ref.macro == :has_and_belongs_to_many)
37
+ pkey = ref.association_primary_key.to_sym
38
+ define_method "#{assoc.singularize}_ids" do
39
+ begin
40
+ self.send(assoc).map(&pkey).uniq
41
+ rescue NoMethodError => e
42
+ raise MissingColumnError.new(self, e.name)
43
+ end
44
+ end
45
+ end
46
+ end if model
47
+
48
+ # Build a getter for each attribute returned by the query. The values will be type converted on demand.
49
+ model_column_types = model ? model.attributes_builder.types : {}
50
+ self.columns.each_with_index do |col, idx|
51
+ type =
52
+ column_types[col] ||
53
+ model_column_types[col] ||
54
+ raise("OccamsRecord: Column `#{col}` does not exist on model `#{self.model_name}`")
55
+
56
+ case type.type
57
+ when :datetime
58
+ define_method(col) { @cast_values[idx] ||= type.send(CASTER, @raw_values[idx])&.in_time_zone }
59
+ when :boolean
60
+ define_method(col) { @cast_values[idx] ||= type.send(CASTER, @raw_values[idx]) }
61
+ define_method("#{col}?") { !!send(col) }
62
+ else
63
+ define_method(col) { @cast_values[idx] ||= type.send(CASTER, @raw_values[idx]) }
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -1,71 +1,5 @@
1
1
  module OccamsRecord
2
- # Classes and methods for handing query results.
3
2
  module Results
4
- # ActiveRecord's internal type casting API changes from version to version.
5
- CASTER = case ActiveRecord::VERSION::MAJOR
6
- when 4 then :type_cast_from_database
7
- when 5 then :deserialize
8
- end
9
-
10
- #
11
- # Dynamically build a class for a specific set of result rows. It inherits from OccamsRecord::Results::Row, and optionall includes
12
- # a user-defined module.
13
- #
14
- # @param column_names [Array<String>] the column names in the result set. The order MUST match the order returned by the query.
15
- # @param column_types [Hash] Column name => type from an ActiveRecord::Result
16
- # @param association_names [Array<String>] names of associations that will be eager loaded into the results.
17
- # @param model [ActiveRecord::Base] the AR model representing the table (it holds column & type info).
18
- # @param modules [Array<Module>] (optional)
19
- # @return [OccamsRecord::Results::Row] a class customized for this result set
20
- #
21
- def self.klass(column_names, column_types, association_names = [], model: nil, modules: nil)
22
- Class.new(Results::Row) do
23
- Array(modules).each { |mod| prepend mod } if modules
24
-
25
- self.columns = column_names.map(&:to_s)
26
- self.associations = association_names.map(&:to_s)
27
- self.model_name = model ? model.name : nil
28
- self.table_name = model ? model.table_name : nil
29
- self.primary_key = model&.primary_key&.to_s
30
-
31
- # Build getters & setters for associations. (We need setters b/c they're set AFTER the row is initialized
32
- attr_accessor(*association_names)
33
-
34
- # Build id getters for associations, e.g. "widget_ids" for "widgets"
35
- self.associations.each do |assoc|
36
- if (ref = model.reflections[assoc]) and !ref.polymorphic? and (ref.macro == :has_many or ref.macro == :has_and_belongs_to_many)
37
- pkey = ref.association_primary_key.to_sym
38
- define_method "#{assoc.singularize}_ids" do
39
- begin
40
- self.send(assoc).map(&pkey).uniq
41
- rescue NoMethodError => e
42
- raise MissingColumnError.new(self, e.name)
43
- end
44
- end
45
- end
46
- end if model
47
-
48
- # Build a getter for each attribute returned by the query. The values will be type converted on demand.
49
- model_column_types = model ? model.attributes_builder.types : {}
50
- self.columns.each_with_index do |col, idx|
51
- type =
52
- column_types[col] ||
53
- model_column_types[col] ||
54
- raise("OccamsRecord: Column `#{col}` does not exist on model `#{self.model_name}`")
55
-
56
- case type.type
57
- when :datetime
58
- define_method(col) { @cast_values[idx] ||= type.send(CASTER, @raw_values[idx])&.in_time_zone }
59
- when :boolean
60
- define_method(col) { @cast_values[idx] ||= type.send(CASTER, @raw_values[idx]) }
61
- define_method("#{col}?") { !!send(col) }
62
- else
63
- define_method(col) { @cast_values[idx] ||= type.send(CASTER, @raw_values[idx]) }
64
- end
65
- end
66
- end
67
- end
68
-
69
3
  #
70
4
  # Abstract class for result rows.
71
5
  #
@@ -3,5 +3,5 @@
3
3
  #
4
4
  module OccamsRecord
5
5
  # Library version
6
- VERSION = '1.0.0.rc8'.freeze
6
+ VERSION = '1.0.0.rc9'.freeze
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: occams-record
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.rc8
4
+ version: 1.0.0.rc9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jordan Hollinger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-20 00:00:00.000000000 Z
11
+ date: 2019-01-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -57,7 +57,8 @@ files:
57
57
  - lib/occams-record/merge.rb
58
58
  - lib/occams-record/query.rb
59
59
  - lib/occams-record/raw_query.rb
60
- - lib/occams-record/results.rb
60
+ - lib/occams-record/results/results.rb
61
+ - lib/occams-record/results/row.rb
61
62
  - lib/occams-record/ugly.rb
62
63
  - lib/occams-record/version.rb
63
64
  homepage: https://jhollinger.github.io/occams-record/