quantum_fields 0.1.1 → 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
  SHA256:
3
- metadata.gz: 9cc27f3dfbb9f1839c4181a91ad750a8ba0f7a255409a5a0574116df423a4a4f
4
- data.tar.gz: 6e22264a1fd7d81ac75befda172afab1e2a6891594a29a692cfdf7b008f74259
3
+ metadata.gz: 225219c6eb2031eac5edd7900a35e3f7c5ce6025175901a7fae160bbf4dc1661
4
+ data.tar.gz: b02f1f72ee6fefa63d2a0264fd1d04cc27b07c9fffe7c6561799f0667cd06aea
5
5
  SHA512:
6
- metadata.gz: 61c95851553049b511fd1afffe1ab3f723f83ab852714843d5abfa876789fd3e9ea1f6cfa0cf35c87183ab37b5c6a6b754a5b328fb697455faf91db5234f029d
7
- data.tar.gz: a92e736b89cd46bc23bdeeb1c538a33cb5f643d2dba17465ff2bc7be512d09bdd9473cb720e38d5720122c6df3f9f58a2ffd146f1b0e58710aa247cff13c2af8
6
+ metadata.gz: 34cafe75d21a630b2c3e647c92b4e623eaa8ec6ea3b363325a1fdcfc5f7ed9afa54f2451dc5bdffba6bf4de64c0ef3f2cf81cbb5283051d5454087ab339c6b98
7
+ data.tar.gz: dccc02766d88453f2006a85426a364a1165db38352e0af5e84be6b98b3e508ad1b4306b4082de485dc514134d9ff5a4b3afbc2b9d7256988fc1cf35139f14aee
@@ -16,6 +16,19 @@ module QuantumFields
16
16
  # This module contains the methods called within the Model to initialize
17
17
  # and to manage how the other methods should behave on the given context.
18
18
  module ClassMethods
19
+ # Method called in the model context to initialize behavior and pass
20
+ # configuration options into quantum_fields. You can use a custom column
21
+ # for your fields and a custom column for your injected validation rules.
22
+ # Initializing the gem behavior on default 'quantum_fields' and
23
+ # 'quantum_rules' columns:
24
+ # => no_sqlize
25
+ # Initializing the gem behavior on default 'quantum_rules' column and a
26
+ # custom fields_column 'my_json_field'
27
+ # => no_sqlize fields_column: :my_json_field
28
+ # Initializing the gem behavior on default 'quantum_fields' column and a
29
+ # custom rules_column 'my_json_field', affecting from where to pull
30
+ # injected validations:
31
+ # => no_sqlize rules_column: :my_json_field
19
32
  def no_sqlize(args = {})
20
33
  class_eval <<-RUBY, __FILE__, __LINE__+1
21
34
  def self.fields_column
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  ActiveRecord::PredicateBuilder.class_eval do
4
+ # Builds an binded Arel operation, injecting json operator if necessary
4
5
  def build(attribute, value)
5
6
  if table.type(attribute.name).force_equality?(value)
6
7
  bind = build_bind_attribute(attribute.name, value)
@@ -16,7 +17,10 @@ ActiveRecord::PredicateBuilder.class_eval do
16
17
  end
17
18
  end
18
19
  ActiveRecord::Relation.class_eval do
19
- def arel_attribute(name) # :nodoc:
20
+ # Returns an Arel::Node that is used to query a field.
21
+ # In case that attribute is a column or if current model
22
+ # hasn't initialized 'no_sqlize' keeps Rails' behavior.
23
+ def arel_attribute(name)
20
24
  if klass.column_names.include?(name.to_s) || !klass.respond_to?(:fields_column)
21
25
  klass.arel_attribute(name, table)
22
26
  else
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module QuantumFields
4
+ class NoSqlizedFieldsColumnMissing < RuntimeError
5
+ def initialize(msg="Missing a JSON field to build QuantumFields")
6
+ super
7
+ end
8
+ end
9
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'quantum_fields/exceptions'
3
4
  module QuantumFields
4
5
  # Module to enable virtual methods in moduls, it creates necessary
5
6
  # methods to simulate the behavior that any field can exist, getting
@@ -10,12 +11,10 @@ module QuantumFields
10
11
  # into `.parameters` JSON as a key-value pair, or recovering it's value if
11
12
  # exists.
12
13
  def method_missing(meth, *args, &block)
13
- if can_no_sqlize?
14
- no_sqlize!(meth, *args, &block)
15
- else
16
- raise NotImplementedError,
17
- "#{model.table_name} should have a `#{fields_column}` JSON column"
18
- end
14
+ method_name = meth.to_s
15
+ super if method_name.ends_with?('!')
16
+ bad_config! unless can_no_sqlize?
17
+ no_sqlize!(method_name, *args, &block)
19
18
  rescue StandardError
20
19
  super
21
20
  end
@@ -24,10 +23,10 @@ module QuantumFields
24
23
  # the premisse that you can always assign a value to any field and recover
25
24
  # only existing fields or the ones that are in the `.parameters` JSON.
26
25
  def respond_to_missing?(method_name, include_private = false)
26
+ bad_config! unless can_no_sqlize?
27
27
  meth = method_name.to_s
28
- can_no_sqlize? && meth.ends_with?('=') || meth.ends_with?('changed?') ||
29
- try(fields_column).try(:[], meth).present? ||
30
- super
28
+ meth.ends_with?('=') || meth.ends_with?('?') ||
29
+ try(fields_column).try(:[], meth).present? || super
31
30
  end
32
31
 
33
32
  # Overriding a ActiveRecord method that is used in `.create` and `.update`
@@ -58,15 +57,21 @@ module QuantumFields
58
57
  # The behavior that a noSQL method should have. It either assigns a value into
59
58
  # an attribute or retrieves it's value, depending in the method called.
60
59
  def no_sqlize!(meth, *args, &_block)
61
- method_name = meth.to_s
62
60
  initialize_fields
63
- if method_name.ends_with?('=')
64
- assing_to(method_name.chomp('='), args.first)
61
+ if meth.ends_with?('=')
62
+ assing_to(meth.chomp('='), args.first)
63
+ elsif meth.ends_with?('?')
64
+ read_nosqlized(meth.chomp('?')).present?
65
65
  else
66
- try(fields_column).try(:[], method_name)
66
+ read_nosqlized(meth)
67
67
  end
68
68
  end
69
69
 
70
+ # Read the value of a `meth` key in :fields_column
71
+ def read_nosqlized(meth)
72
+ try(fields_column).try(:[], meth)
73
+ end
74
+
70
75
  # Assings a value to a key in :fields_column which allows saving any virtual
71
76
  # attribute
72
77
  def assing_to(param, value)
@@ -76,12 +81,18 @@ module QuantumFields
76
81
  # Checks if requirements are met for the feature
77
82
  def can_no_sqlize?
78
83
  model.column_names.include?(fields_column.to_s) &&
79
- %i[json jsonb].include?(no_sqlize_column.type)
84
+ %i[hstore json jsonb].include?(no_sqlize_column.type)
80
85
  end
81
86
 
82
87
  # Retrieve which column is being used to sqlize
83
88
  def no_sqlize_column
84
89
  model.columns.find { |col| col.name == fields_column.to_s }
85
90
  end
91
+
92
+ # Raises an exception indicating bad configuration of the gem
93
+ def bad_config!
94
+ raise QuantumFields::NoSqlizedFieldsColumnMissing,
95
+ "#{model.table_name} should have a `#{fields_column}` JSON column"
96
+ end
86
97
  end
87
98
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'quantum_fields/support/postgresql'
4
- require 'quantum_fields/support/mysql'
4
+ require 'quantum_fields/support/mysql2'
5
5
  require 'quantum_fields/support/sqlite3'
6
6
 
7
7
  module QuantumFields
@@ -3,7 +3,7 @@
3
3
  module QuantumFields
4
4
  module Support
5
5
  # Abstracts MySQL support for quantum_fields operations
6
- module Mysql
6
+ module Mysql2
7
7
  class << self
8
8
  # Returns an Arel node in the context of given field and JSON key,
9
9
  # which in this context constructs as "json_extract("my_models"."my_json_field", '$.key')"
@@ -7,6 +7,7 @@ module QuantumFields
7
7
  extend ActiveSupport::Concern
8
8
  included do
9
9
  before_validation :map_injected_validations
10
+ # Maps your rules_column for defined validations
10
11
  def map_injected_validations
11
12
  send(self.class.rules_column).try(:deep_symbolize_keys)&.each do |field, rules|
12
13
  validations = rules[:validates]
@@ -14,6 +15,9 @@ module QuantumFields
14
15
  end
15
16
  end
16
17
 
18
+ private
19
+
20
+ # Injects validations on a given field
17
21
  def inject_validations(field, validations)
18
22
  validations.each do |method, value|
19
23
  singleton_class.validates field, method => value
@@ -1,3 +1,3 @@
1
1
  module QuantumFields
2
- VERSION = '0.1.1'
2
+ VERSION = '0.2.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quantum_fields
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fernando Bellincanta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-22 00:00:00.000000000 Z
11
+ date: 2019-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -52,6 +52,34 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 1.3.6
55
+ - !ruby/object:Gem::Dependency
56
+ name: pg
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: mysql2
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
55
83
  description: QuantumFields is a gem to extend your Rails model's making them able
56
84
  to use virtual fields from a JSON column or a Text column serialized as a Hash.
57
85
  This means that you can use fields that were not explicitly declared in your schema
@@ -67,10 +95,11 @@ files:
67
95
  - Rakefile
68
96
  - lib/quantum_fields.rb
69
97
  - lib/quantum_fields/active_record_patch.rb
98
+ - lib/quantum_fields/exceptions.rb
70
99
  - lib/quantum_fields/no_sqlize.rb
71
100
  - lib/quantum_fields/railtie.rb
72
101
  - lib/quantum_fields/support.rb
73
- - lib/quantum_fields/support/mysql.rb
102
+ - lib/quantum_fields/support/mysql2.rb
74
103
  - lib/quantum_fields/support/postgresql.rb
75
104
  - lib/quantum_fields/support/sqlite3.rb
76
105
  - lib/quantum_fields/validation_injector.rb