active_file_record 0.0.2a → 0.0.3a
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.
- data/active_file_record.gemspec +1 -1
- data/lib/active_file_record/associations.rb +57 -0
- data/lib/active_file_record/associations/association.rb +101 -0
- data/lib/active_file_record/associations/association_scope.rb +29 -0
- data/lib/active_file_record/associations/belongs_to_association.rb +78 -0
- data/lib/active_file_record/associations/builder/association.rb +46 -0
- data/lib/active_file_record/associations/builder/belongs_to.rb +13 -0
- data/lib/active_file_record/associations/singular_association.rb +64 -0
- data/lib/active_file_record/attribute_assignment.rb +25 -0
- data/lib/active_file_record/attribute_methods.rb +48 -0
- data/lib/active_file_record/attribute_methods/read.rb +26 -0
- data/lib/active_file_record/attribute_methods/write.rb +27 -0
- data/lib/active_file_record/base.rb +81 -0
- data/lib/active_file_record/callbacks.rb +21 -0
- data/lib/active_file_record/criteria.rb +10 -0
- data/lib/active_file_record/file_handler.rb +66 -0
- data/lib/active_file_record/file_handler/active_file.rb +13 -0
- data/lib/active_file_record/file_handler/attribute.rb +5 -0
- data/lib/active_file_record/inheritance.rb +42 -0
- data/lib/active_file_record/integration.rb +13 -0
- data/lib/active_file_record/nodes.rb +2 -0
- data/lib/active_file_record/nodes/binary.rb +19 -0
- data/lib/active_file_record/nodes/equality.rb +11 -0
- data/lib/active_file_record/persistence.rb +53 -0
- data/lib/active_file_record/predications.rb +9 -0
- data/lib/active_file_record/reflection.rb +140 -0
- data/lib/active_file_record/relation.rb +73 -0
- data/lib/active_file_record/relation/finder_methods.rb +88 -0
- data/lib/active_file_record/relation/predicate_builder.rb +21 -0
- data/lib/active_file_record/relation/search_methods.rb +65 -0
- data/lib/active_file_record/scoping.rb +28 -0
- data/lib/active_file_record/scoping/named.rb +72 -0
- data/lib/active_file_record/validations.rb +12 -0
- data/lib/active_file_record/version.rb +1 -1
- metadata +33 -1
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'active_support/core_ext/object/blank'
|
2
|
+
|
3
|
+
module ActiveFileRecord
|
4
|
+
class Relation
|
5
|
+
include SearchMethods, FinderMethods
|
6
|
+
|
7
|
+
delegate :file_handler, :filename, :primary_key, :to => :klass
|
8
|
+
|
9
|
+
MULTI_VALUE_METHODS = [:where]
|
10
|
+
SINGLE_VALUE_METHODS = [:limit]
|
11
|
+
|
12
|
+
attr_accessor :default_scoped
|
13
|
+
|
14
|
+
attr_reader :file, :klass, :loaded
|
15
|
+
attr_accessor :extensions, :default_scoped
|
16
|
+
alias :loaded? :loaded
|
17
|
+
|
18
|
+
|
19
|
+
def initialize(klass, file)
|
20
|
+
@klass = klass
|
21
|
+
@file = file
|
22
|
+
|
23
|
+
@implicit_readonly = nil
|
24
|
+
@loaded = false
|
25
|
+
@default_scoped = false
|
26
|
+
|
27
|
+
SINGLE_VALUE_METHODS.each {|v| instance_variable_set(:"@#{v}_value", nil)}
|
28
|
+
MULTI_VALUE_METHODS.each {|v| instance_variable_set(:"@#{v}_values", [])}
|
29
|
+
@extensions = []
|
30
|
+
@create_with_value = {}
|
31
|
+
end
|
32
|
+
|
33
|
+
def inspect
|
34
|
+
to_a.inspect
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_a
|
38
|
+
exec_queries
|
39
|
+
end
|
40
|
+
|
41
|
+
def exec_queries
|
42
|
+
return @records if loaded?
|
43
|
+
default_scoped = self
|
44
|
+
@records = find_with_associations
|
45
|
+
@loaded = true
|
46
|
+
@records
|
47
|
+
end
|
48
|
+
|
49
|
+
def merge(r)
|
50
|
+
return self unless r
|
51
|
+
return to_a & r if r.is_a?(Array)
|
52
|
+
|
53
|
+
merged_relation = clone
|
54
|
+
merged_wheres = @where_values + r.where_values
|
55
|
+
|
56
|
+
merged_relation.where_values = merged_wheres
|
57
|
+
|
58
|
+
(Relation::SINGLE_VALUE_METHODS - [:lock, :create_with, :reordering]).each do |method|
|
59
|
+
value = r.send(:"#{method}_value")
|
60
|
+
merged_relation.send(:"#{method}_value=", value) unless value.nil?
|
61
|
+
end
|
62
|
+
|
63
|
+
# Apply scope extension modules
|
64
|
+
merged_relation.send :apply_modules, r.extensions
|
65
|
+
|
66
|
+
merged_relation
|
67
|
+
end
|
68
|
+
|
69
|
+
private :exec_queries
|
70
|
+
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'active_support/core_ext/object/blank'
|
2
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
3
|
+
|
4
|
+
module ActiveFileRecord
|
5
|
+
module FinderMethods
|
6
|
+
def find(*args)
|
7
|
+
case args.first
|
8
|
+
when :first, :last, :all
|
9
|
+
send(args.first)
|
10
|
+
else
|
11
|
+
find_with_ids(*args)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# A convenience wrapper for <tt>find(:first, *args)</tt>. You can pass in all the
|
16
|
+
# same arguments to this method as you can to <tt>find(:first)</tt>.
|
17
|
+
def first #(*args)
|
18
|
+
#if args.any?
|
19
|
+
# if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash))
|
20
|
+
# limit(*args).to_a
|
21
|
+
# else
|
22
|
+
# apply_finder_options(args.first).first
|
23
|
+
# end
|
24
|
+
#else
|
25
|
+
find_first
|
26
|
+
#end
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
# A convenience wrapper for <tt>find(:last, *args)</tt>. You can pass in all the
|
31
|
+
# same arguments to this method as you can to <tt>find(:last)</tt>.
|
32
|
+
def last(*args)
|
33
|
+
find_last
|
34
|
+
end
|
35
|
+
|
36
|
+
# A convenience wrapper for <tt>find(:all, *args)</tt>. You can pass in all the
|
37
|
+
# same arguments to this method as you can to <tt>find(:all)</tt>.
|
38
|
+
def all(*args)
|
39
|
+
args.any? ? apply_finder_options(args.first).to_a : to_a
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
|
46
|
+
def find_with_ids(*ids)
|
47
|
+
#ids = ids.flatten.compact.uniq
|
48
|
+
|
49
|
+
case ids.size
|
50
|
+
|
51
|
+
when 0
|
52
|
+
raise RecordNotFound, "Couldn't find #{@klass.name} without an ID"
|
53
|
+
when 1
|
54
|
+
result = find_one(ids.first.to_i)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def find_one(id)
|
59
|
+
column = :id
|
60
|
+
relation = where({primary_key=>{:eq => id}})
|
61
|
+
record = relation.first
|
62
|
+
|
63
|
+
unless record
|
64
|
+
raise RecordNotFound , "Couldn't find #{@klass.name}"
|
65
|
+
end
|
66
|
+
|
67
|
+
record
|
68
|
+
end
|
69
|
+
|
70
|
+
def find_first
|
71
|
+
if loaded?
|
72
|
+
@records.first
|
73
|
+
else
|
74
|
+
@first ||= limit(1).to_a[0]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def find_last
|
79
|
+
if loaded?
|
80
|
+
@records.last
|
81
|
+
else
|
82
|
+
to_a.last
|
83
|
+
@last ||= to_a.last
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ActiveFileRecord
|
2
|
+
class PredicateBuilder # :nodoc:
|
3
|
+
def self.build_from_hash(attributes, default_file)
|
4
|
+
file = default_file
|
5
|
+
|
6
|
+
# FIXME: We need to sanitize attributes
|
7
|
+
|
8
|
+
predicates = attributes.map do |field, value|
|
9
|
+
active_file = ActiveFile.new(file)
|
10
|
+
attribute = active_file[field.to_sym]
|
11
|
+
|
12
|
+
compare_method = value.keys.first
|
13
|
+
attr_value = value.values.first
|
14
|
+
|
15
|
+
attribute.send(compare_method, attr_value)
|
16
|
+
end
|
17
|
+
|
18
|
+
predicates.flatten
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
#require 'active_support/core_ext/array/wrap'
|
2
|
+
#require 'active_support/core_ext/object/blank'
|
3
|
+
|
4
|
+
module ActiveFileRecord
|
5
|
+
module SearchMethods
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
attr_accessor :where_values, :limit_value
|
9
|
+
|
10
|
+
def select
|
11
|
+
relation = clone
|
12
|
+
relation
|
13
|
+
end
|
14
|
+
|
15
|
+
def where(opts)
|
16
|
+
return self if opts.blank?
|
17
|
+
|
18
|
+
relation = clone
|
19
|
+
relation.where_values += build_where(opts)
|
20
|
+
relation
|
21
|
+
end
|
22
|
+
|
23
|
+
def limit(value)
|
24
|
+
relation = clone
|
25
|
+
relation.limit_value = value
|
26
|
+
relation
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def build_where(opts)
|
32
|
+
PredicateBuilder.build_from_hash(opts, filename)
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def apply_modules(modules)
|
37
|
+
unless modules.empty?
|
38
|
+
@extensions += modules
|
39
|
+
modules.each {|extension| extend(extension) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
def find_with_associations
|
46
|
+
relation = construct_relation_for_association_find
|
47
|
+
rows = file_handler.select_all(relation)
|
48
|
+
end
|
49
|
+
|
50
|
+
def construct_relation_for_association_find
|
51
|
+
result = self.class.new(@klass, file)
|
52
|
+
result.default_scoped = default_scoped
|
53
|
+
|
54
|
+
Relation::MULTI_VALUE_METHODS.each do |method|
|
55
|
+
result.send(:"#{method}_values=", send(:"#{method}_values"))
|
56
|
+
end
|
57
|
+
|
58
|
+
Relation::SINGLE_VALUE_METHODS.each do |method|
|
59
|
+
result.send(:"#{method}_value=", send(:"#{method}_value"))
|
60
|
+
end
|
61
|
+
|
62
|
+
relation = result.select
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module ActiveFileRecord
|
4
|
+
module Scoping
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
include Named
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
def unscoped
|
14
|
+
block_given? ? relation.scoping { yield } : relation
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
protected
|
19
|
+
def current_scope #:nodoc:
|
20
|
+
Thread.current["#{self}_current_scope"]
|
21
|
+
end
|
22
|
+
#
|
23
|
+
def current_scope=(scope) #:nodoc:
|
24
|
+
Thread.current["#{self}_current_scope"] = scope
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'active_support/core_ext/array'
|
2
|
+
require 'active_support/core_ext/hash/except'
|
3
|
+
require 'active_support/core_ext/kernel/singleton_class'
|
4
|
+
require 'active_support/core_ext/object/blank'
|
5
|
+
require 'active_support/core_ext/class/attribute'
|
6
|
+
|
7
|
+
module ActiveFileRecord
|
8
|
+
# = Active Record Named \Scopes
|
9
|
+
module Scoping
|
10
|
+
module Named
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
|
15
|
+
def scoped(options = nil)
|
16
|
+
|
17
|
+
if options
|
18
|
+
scoped.apply_finder_options(options)
|
19
|
+
else
|
20
|
+
if current_scope
|
21
|
+
current_scope.clone
|
22
|
+
else
|
23
|
+
scope = relation
|
24
|
+
scope.default_scoped = true
|
25
|
+
scope
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def scope_attributes # :nodoc:
|
31
|
+
if current_scope
|
32
|
+
current_scope.scope_for_create
|
33
|
+
else
|
34
|
+
scope = relation
|
35
|
+
scope.default_scoped = true
|
36
|
+
scope.scope_for_create
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def scope_attributes? # :nodoc:
|
41
|
+
current_scope || default_scopes.any?
|
42
|
+
end
|
43
|
+
|
44
|
+
def scope(name, scope_options = {})
|
45
|
+
name = name.to_sym
|
46
|
+
valid_scope_name?(name)
|
47
|
+
extension = Module.new(&Proc.new) if block_given?
|
48
|
+
|
49
|
+
scope_proc = lambda do |*args|
|
50
|
+
options = scope_options.respond_to?(:call) ? unscoped { scope_options.call(*args) } : scope_options
|
51
|
+
options = scoped.apply_finder_options(options) if options.is_a?(Hash)
|
52
|
+
|
53
|
+
relation = scoped.merge(options)
|
54
|
+
|
55
|
+
extension ? relation.extending(extension) : relation
|
56
|
+
end
|
57
|
+
|
58
|
+
singleton_class.send(:redefine_method, name, &scope_proc)
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
|
63
|
+
def valid_scope_name?(name)
|
64
|
+
if logger && respond_to?(name, true)
|
65
|
+
logger.warn "Creating scope :#{name}. " \
|
66
|
+
"Overwriting existing method #{self.name}.#{name}."
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_file_record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3a
|
5
5
|
prerelease: 5
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -25,6 +25,38 @@ files:
|
|
25
25
|
- Rakefile
|
26
26
|
- active_file_record.gemspec
|
27
27
|
- lib/active_file_record.rb
|
28
|
+
- lib/active_file_record/associations.rb
|
29
|
+
- lib/active_file_record/associations/association.rb
|
30
|
+
- lib/active_file_record/associations/association_scope.rb
|
31
|
+
- lib/active_file_record/associations/belongs_to_association.rb
|
32
|
+
- lib/active_file_record/associations/builder/association.rb
|
33
|
+
- lib/active_file_record/associations/builder/belongs_to.rb
|
34
|
+
- lib/active_file_record/associations/singular_association.rb
|
35
|
+
- lib/active_file_record/attribute_assignment.rb
|
36
|
+
- lib/active_file_record/attribute_methods.rb
|
37
|
+
- lib/active_file_record/attribute_methods/read.rb
|
38
|
+
- lib/active_file_record/attribute_methods/write.rb
|
39
|
+
- lib/active_file_record/base.rb
|
40
|
+
- lib/active_file_record/callbacks.rb
|
41
|
+
- lib/active_file_record/criteria.rb
|
42
|
+
- lib/active_file_record/file_handler.rb
|
43
|
+
- lib/active_file_record/file_handler/active_file.rb
|
44
|
+
- lib/active_file_record/file_handler/attribute.rb
|
45
|
+
- lib/active_file_record/inheritance.rb
|
46
|
+
- lib/active_file_record/integration.rb
|
47
|
+
- lib/active_file_record/nodes.rb
|
48
|
+
- lib/active_file_record/nodes/binary.rb
|
49
|
+
- lib/active_file_record/nodes/equality.rb
|
50
|
+
- lib/active_file_record/persistence.rb
|
51
|
+
- lib/active_file_record/predications.rb
|
52
|
+
- lib/active_file_record/reflection.rb
|
53
|
+
- lib/active_file_record/relation.rb
|
54
|
+
- lib/active_file_record/relation/finder_methods.rb
|
55
|
+
- lib/active_file_record/relation/predicate_builder.rb
|
56
|
+
- lib/active_file_record/relation/search_methods.rb
|
57
|
+
- lib/active_file_record/scoping.rb
|
58
|
+
- lib/active_file_record/scoping/named.rb
|
59
|
+
- lib/active_file_record/validations.rb
|
28
60
|
- lib/active_file_record/version.rb
|
29
61
|
homepage: ''
|
30
62
|
licenses: []
|