Module: Protector::Adapters::ActiveRecord::Relation
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/protector/adapters/active_record/relation.rb
Overview
Patches ActiveRecord::Relation
Instance Method Summary collapse
-
#calculate(*args) ⇒ Object
Merges current relation with restriction and calls real
calculate
. - #count(*args) ⇒ Object
- #except(*args) ⇒ Object
-
#exec_queries_with_protector(*args) ⇒ Object
Patches current relation to fulfill restriction and call real
exec_queries
. -
#exists?(*args) ⇒ Boolean
Merges current relation with restriction and calls real
exists?
. - #only(*args) ⇒ Object
-
#protector_expand_inclusion(inclusion, results = [], base = [], klass = @klass) ⇒ Object
Indexes
includes
format by actual entity class. -
#protector_meta ⇒ Object
Gets DSL::Meta::Box of this relation.
-
#protector_substitute_includes(subject, relation) ⇒ Object
Swaps
includes
withpreload
whether it's not referenced or merges security scope of proper class otherwise. - #sum(*args) ⇒ Object
- #unscoped ⇒ Object
Instance Method Details
#calculate(*args) ⇒ Object
Merges current relation with restriction and calls real calculate
65 66 67 68 |
# File 'lib/protector/adapters/active_record/relation.rb', line 65 def calculate(*args) return super unless protector_subject? merge(.relation).unrestrict!.calculate *args end |
#count(*args) ⇒ Object
This is here cause NullRelation
can return nil
from count
55 56 57 |
# File 'lib/protector/adapters/active_record/relation.rb', line 55 def count(*args) super || 0 end |
#except(*args) ⇒ Object
44 45 46 47 |
# File 'lib/protector/adapters/active_record/relation.rb', line 44 def except(*args) return super unless protector_subject? super.restrict!(protector_subject) end |
#exec_queries_with_protector(*args) ⇒ Object
Patches current relation to fulfill restriction and call real exec_queries
Patching includes:
- turning
includes
(that are not referenced for eager loading) intopreload
- delaying built-in preloading to the stage where selection is restricted
- merging current relation with restriction (of self and every eager association)
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/protector/adapters/active_record/relation.rb', line 83 def exec_queries_with_protector(*args) return @records if loaded? return exec_queries_without_protector unless protector_subject? subject = protector_subject relation = merge(.relation).unrestrict! relation = protector_substitute_includes(subject, relation) # Preserve associations from internal loading. We are going to handle that # ourselves respecting security scopes FTW! associations, relation.preload_values = relation.preload_values, [] @records = relation.send(:exec_queries).each{|record| record.restrict!(subject)} # Now we have @records restricted properly so let's preload associations! associations.each do |association| ::ActiveRecord::Associations::Preloader.new(@records, association).run end @loaded = true @records end |
#exists?(*args) ⇒ Boolean
Merges current relation with restriction and calls real exists?
71 72 73 74 |
# File 'lib/protector/adapters/active_record/relation.rb', line 71 def exists?(*args) return super unless protector_subject? merge(.relation).unrestrict!.exists? *args end |
#only(*args) ⇒ Object
49 50 51 52 |
# File 'lib/protector/adapters/active_record/relation.rb', line 49 def only(*args) return super unless protector_subject? super.restrict!(protector_subject) end |
#protector_expand_inclusion(inclusion, results = [], base = [], klass = @klass) ⇒ Object
Indexes includes
format by actual entity class
Turns {foo: :bar}
into [[Foo, :foo], [Bar, {foo: :bar}]
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/protector/adapters/active_record/relation.rb', line 153 def (inclusion, results=[], base=[], klass=@klass) if inclusion.is_a?(Hash) (inclusion, results, base, klass) else Array(inclusion).each do |i| if i.is_a?(Hash) (i, results, base, klass) else results << [ klass.reflect_on_association(i.to_sym).klass, i.to_sym ] end end end results end |
#protector_meta ⇒ Object
Gets DSL::Meta::Box of this relation
29 30 31 32 33 34 35 36 |
# File 'lib/protector/adapters/active_record/relation.rb', line 29 def # We don't seem to require columns here as well @klass..evaluate( Protector::Adapters::ActiveRecord, @klass, protector_subject ) end |
#protector_substitute_includes(subject, relation) ⇒ Object
Swaps includes
with preload
whether it's not referenced or merges
security scope of proper class otherwise
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/protector/adapters/active_record/relation.rb', line 108 def protector_substitute_includes(subject, relation) if eager_loading? (includes_values + eager_load_values).each do |klass, path| # AR drops default_scope for eagerly loadable associations # https://github.com/inossidabile/protector/issues/3 # and so should we = klass..evaluate( Protector::Adapters::ActiveRecord, klass, subject ) if .scoped? unscoped = klass.unscoped # AR 4 has awfull inconsistency when it comes to method `all` # We have to mimic base class behaviour for relation we get from `unscoped` if Protector::Adapters::ActiveRecord.modern? class <<unscoped def all self end end end # Finally we merge unscoped basic relation extended with protection scope relation = relation.merge unscoped.instance_eval(&.scope_proc) end end else relation.preload_values += includes_values relation.includes_values = [] end relation end |
#sum(*args) ⇒ Object
This is here cause NullRelation
can return nil
from sum
60 61 62 |
# File 'lib/protector/adapters/active_record/relation.rb', line 60 def sum(*args) super || 0 end |
#unscoped ⇒ Object
Unscoped relation drops properties and therefore should be re-restricted
39 40 41 42 |
# File 'lib/protector/adapters/active_record/relation.rb', line 39 def unscoped return super unless protector_subject? super.restrict!(protector_subject) end |