active_file_record 0.0.2a → 0.0.3a
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|