perry 0.4.0 → 0.5.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.
- data/Rakefile +2 -1
- data/lib/perry/adapters/abstract_adapter.rb +189 -64
- data/lib/perry/adapters/bertrpc_adapter.rb +3 -2
- data/lib/perry/adapters/restful_http_adapter.rb +36 -11
- data/lib/perry/association.rb +43 -14
- data/lib/perry/base.rb +33 -17
- data/lib/perry/{cacheable → middlewares/cache_records}/entry.rb +7 -7
- data/lib/perry/middlewares/cache_records/scopes.rb +18 -0
- data/lib/perry/{cacheable → middlewares/cache_records}/store.rb +1 -1
- data/lib/perry/middlewares/cache_records.rb +67 -0
- data/lib/perry/middlewares/model_bridge.rb +66 -0
- data/lib/perry/middlewares.rb +8 -0
- data/lib/perry/persistence/response.rb +75 -0
- data/lib/perry/persistence.rb +40 -2
- data/lib/perry/processors/preload_associations.rb +61 -0
- data/lib/perry/processors.rb +5 -0
- data/lib/perry/relation/finder_methods.rb +8 -4
- data/lib/perry/relation/modifiers.rb +37 -0
- data/lib/perry/relation/query_methods.rb +19 -11
- data/lib/perry/relation.rb +9 -4
- data/lib/perry/version.rb +1 -1
- data/lib/perry.rb +5 -0
- metadata +31 -9
- data/lib/perry/association_preload.rb +0 -69
- data/lib/perry/cacheable.rb +0 -80
@@ -0,0 +1,67 @@
|
|
1
|
+
class Perry::Middlewares::CacheRecords; end
|
2
|
+
require 'perry/middlewares/cache_records/store'
|
3
|
+
require 'perry/middlewares/cache_records/entry'
|
4
|
+
require 'perry/middlewares/cache_records/scopes'
|
5
|
+
require 'digest/md5'
|
6
|
+
|
7
|
+
class Perry::Middlewares::CacheRecords
|
8
|
+
include Perry::Logger
|
9
|
+
|
10
|
+
attr_accessor :record_count_threshold
|
11
|
+
|
12
|
+
# TRP: Default to a 5 minute cache
|
13
|
+
DEFAULT_LONGEVITY = 5*60
|
14
|
+
|
15
|
+
def reset_cache_store(default_longevity=DEFAULT_LONGEVITY)
|
16
|
+
@cache_store = Perry::Middlewares::CacheRecords::Store.new(default_longevity)
|
17
|
+
end
|
18
|
+
|
19
|
+
def cache_store
|
20
|
+
@cache_store || reset_cache_store
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(adapter, config={})
|
24
|
+
@adapter = adapter
|
25
|
+
self.record_count_threshold = config[:record_count_threshold]
|
26
|
+
end
|
27
|
+
|
28
|
+
def call(options)
|
29
|
+
if options[:relation]
|
30
|
+
call_with_cache(options)
|
31
|
+
else
|
32
|
+
@adapter.call(options)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def call_with_cache(options)
|
39
|
+
relation = options[:relation]
|
40
|
+
modifiers = relation.modifiers_value
|
41
|
+
query = relation.to_hash
|
42
|
+
|
43
|
+
reset_cache_store if modifiers[:reset_cache]
|
44
|
+
get_fresh = modifiers[:fresh]
|
45
|
+
|
46
|
+
key = key_for_query(query)
|
47
|
+
cached_values = self.cache_store.read(key)
|
48
|
+
|
49
|
+
|
50
|
+
if cached_values && !get_fresh
|
51
|
+
log(query, "CACHE #{relation.klass.name}")
|
52
|
+
cached_values
|
53
|
+
else
|
54
|
+
fresh_values = @adapter.call(options)
|
55
|
+
self.cache_store.write(key, fresh_values) if should_store_in_cache?(fresh_values)
|
56
|
+
fresh_values
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def key_for_query(query_hash)
|
61
|
+
Digest::MD5.hexdigest(self.class.to_s + query_hash.to_a.sort { |a,b| a.to_s.first <=> b.to_s.first }.inspect)
|
62
|
+
end
|
63
|
+
|
64
|
+
def should_store_in_cache?(fresh_values)
|
65
|
+
!self.record_count_threshold || fresh_values.size <= self.record_count_threshold
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
class Perry::Middlewares::ModelBridge
|
2
|
+
|
3
|
+
def initialize(adapter, config={})
|
4
|
+
@adapter = adapter
|
5
|
+
@config = config
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(options)
|
9
|
+
result = @adapter.call(options)
|
10
|
+
|
11
|
+
case options[:mode]
|
12
|
+
when :read
|
13
|
+
build_models_from_records(result, options)
|
14
|
+
when :write
|
15
|
+
update_model_after_save(result, options[:object])
|
16
|
+
result
|
17
|
+
when :delete
|
18
|
+
update_model_after_delete(result, options[:object])
|
19
|
+
result
|
20
|
+
else
|
21
|
+
result
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def build_models_from_records(records, options)
|
28
|
+
if options[:relation]
|
29
|
+
records.collect do |attributes|
|
30
|
+
options[:relation].klass.new_from_data_store(attributes)
|
31
|
+
end
|
32
|
+
else
|
33
|
+
records
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def update_model_after_save(response, model)
|
38
|
+
model.saved = response.success
|
39
|
+
if model.saved
|
40
|
+
if model.new_record?
|
41
|
+
key = response.model_attributes[model.primary_key]
|
42
|
+
raise Perry::PerryError.new('primary key not included in response') if key.nil?
|
43
|
+
model.send("#{model.primary_key}=", key)
|
44
|
+
end
|
45
|
+
model.new_record = false
|
46
|
+
model.reload unless model.read_adapter.nil?
|
47
|
+
else
|
48
|
+
add_errors_to_model(response, model, 'not saved')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def update_model_after_delete(response, model)
|
53
|
+
if response.success
|
54
|
+
model.freeze!
|
55
|
+
else
|
56
|
+
add_errors_to_model(response, model, 'not deleted')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def add_errors_to_model(response, model, default_message)
|
61
|
+
errors = response.errors
|
62
|
+
errors[:base] = default_message if errors.empty?
|
63
|
+
model.errors.merge!(errors)
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Perry::Persistence
|
2
|
+
class Response
|
3
|
+
|
4
|
+
@@parsers = { :json => ::JSON }
|
5
|
+
ATTRIBUTES = [:success, :status, :meta, :raw, :raw_format, :parsed]
|
6
|
+
|
7
|
+
# A boolean value reflecting whether or not the response was successful
|
8
|
+
attr_accessor :success
|
9
|
+
|
10
|
+
# A more detailed report of the success/failure of the response
|
11
|
+
attr_accessor :status
|
12
|
+
|
13
|
+
# Any adapter specific response metadata
|
14
|
+
attr_accessor :meta
|
15
|
+
|
16
|
+
# Raw response -- format specified by raw_format
|
17
|
+
attr_accessor :raw
|
18
|
+
|
19
|
+
# Format of the raw response
|
20
|
+
attr_accessor :raw_format
|
21
|
+
|
22
|
+
# Parsed raw data
|
23
|
+
attr_writer :parsed
|
24
|
+
|
25
|
+
# @attrs: Sets any values listed in ATTRIBUTES
|
26
|
+
def initialize(attrs={})
|
27
|
+
ATTRIBUTES.each do |attr|
|
28
|
+
self.send("#{attr}=", attrs[attr])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def parsed
|
33
|
+
if parser = self.class.parsers[self.raw_format]
|
34
|
+
begin
|
35
|
+
@parsed ||= parser.parse(self.raw)
|
36
|
+
rescue Exception => err
|
37
|
+
Perry.logger.error("Failure parsing raw response #{err.inspect}")
|
38
|
+
Perry.logger.error("Response: #{self.inspect}")
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
else
|
42
|
+
@parsed
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.parsers
|
47
|
+
@@parsers
|
48
|
+
end
|
49
|
+
|
50
|
+
def model_attributes
|
51
|
+
# return the inner hash if nested
|
52
|
+
if parsed_hash.keys.size == 1 && parsed_hash[parsed_hash.keys.first].is_a?(Hash)
|
53
|
+
parsed_hash[parsed_hash.keys.first]
|
54
|
+
else
|
55
|
+
parsed_hash
|
56
|
+
end.symbolize_keys
|
57
|
+
end
|
58
|
+
|
59
|
+
def errors
|
60
|
+
parsed_hash.symbolize_keys
|
61
|
+
end
|
62
|
+
|
63
|
+
protected
|
64
|
+
|
65
|
+
def parsed_hash
|
66
|
+
if parsed.is_a?(Hash)
|
67
|
+
parsed
|
68
|
+
else
|
69
|
+
{}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
data/lib/perry/persistence.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'perry/persistence/response'
|
2
|
+
|
1
3
|
module Perry::Persistence
|
2
4
|
|
3
5
|
module ClassMethods
|
@@ -24,7 +26,8 @@ module Perry::Persistence
|
|
24
26
|
end
|
25
27
|
|
26
28
|
def save
|
27
|
-
|
29
|
+
raise Perry::PerryError.new("cannot write a frozen object") if frozen?
|
30
|
+
write_adapter.call(:write, :object => self).success
|
28
31
|
end
|
29
32
|
|
30
33
|
def save!
|
@@ -41,10 +44,44 @@ module Perry::Persistence
|
|
41
44
|
end
|
42
45
|
|
43
46
|
def destroy
|
44
|
-
|
47
|
+
raise Perry::PerryError.new("cannot destroy a frozen object") if frozen?
|
48
|
+
unless self.new_record? || self.send(primary_key).nil?
|
49
|
+
write_adapter.call(:delete, :object => self).success
|
50
|
+
end
|
45
51
|
end
|
46
52
|
alias :delete :destroy
|
47
53
|
|
54
|
+
def destroy!
|
55
|
+
destroy or raise Perry::RecordNotSaved
|
56
|
+
end
|
57
|
+
alias :delete! :destroy!
|
58
|
+
|
59
|
+
def reload
|
60
|
+
self.attributes = self.class.where(primary_key => self.send(primary_key)).first.attributes
|
61
|
+
end
|
62
|
+
|
63
|
+
# Calls Object#freeze on the model and on the attributes hash in addition to
|
64
|
+
# calling #freeze! to prevent the model from being saved or destroyed.
|
65
|
+
#
|
66
|
+
def freeze
|
67
|
+
freeze!
|
68
|
+
attributes.freeze
|
69
|
+
super
|
70
|
+
end
|
71
|
+
|
72
|
+
# Prevents the model from being saved or destroyed in the future while still
|
73
|
+
# allowing the model and its attributes hash to be modified.
|
74
|
+
#
|
75
|
+
def freeze!
|
76
|
+
@frozen = true
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns true if ether #freeze or #freeze! has been called on the model.
|
80
|
+
#
|
81
|
+
def frozen?
|
82
|
+
!!@frozen
|
83
|
+
end
|
84
|
+
|
48
85
|
end
|
49
86
|
|
50
87
|
def self.included(receiver)
|
@@ -53,3 +90,4 @@ module Perry::Persistence
|
|
53
90
|
end
|
54
91
|
|
55
92
|
end
|
93
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
##
|
2
|
+
# = Perry::Processors::PreloadAssociations
|
3
|
+
#
|
4
|
+
# This adapter processor will allow associations to be eager loaded after the original records are fetched.
|
5
|
+
# Any associations specified in an :includes option will be loaded for all records in the query
|
6
|
+
# (each association in a single request).
|
7
|
+
#
|
8
|
+
# == Configuration Options:
|
9
|
+
#
|
10
|
+
# None
|
11
|
+
#
|
12
|
+
# == Modifiers:
|
13
|
+
#
|
14
|
+
# None
|
15
|
+
#
|
16
|
+
#
|
17
|
+
#
|
18
|
+
class Perry::Processors::PreloadAssociations
|
19
|
+
|
20
|
+
def initialize(adapter, config={})
|
21
|
+
@adapter = adapter
|
22
|
+
@config = config
|
23
|
+
end
|
24
|
+
|
25
|
+
def call(options)
|
26
|
+
results = @adapter.call(options)
|
27
|
+
|
28
|
+
unless results.empty?
|
29
|
+
relation = options[:relation]
|
30
|
+
(includes = relation.to_hash[:includes] || {}).keys.each do |association_id|
|
31
|
+
association = relation.klass.defined_associations[association_id.to_sym]
|
32
|
+
raise Perry::AssociationNotFound, "unknown association #{association_id}" unless association
|
33
|
+
eager_records = association.scope(results).includes(includes[association_id]).all(:modifiers => options[:relation].modifiers_value)
|
34
|
+
|
35
|
+
results.each do |result|
|
36
|
+
scope = association.scope(result)
|
37
|
+
case association.type
|
38
|
+
when :has_one, :has_many
|
39
|
+
scope.records = eager_records.select do |record|
|
40
|
+
record.send(association.foreign_key) == result.send(association.primary_key)
|
41
|
+
end
|
42
|
+
if association.collection?
|
43
|
+
result.send("#{association.id}=", scope)
|
44
|
+
else
|
45
|
+
result.send("#{association.id}=", scope.records.first)
|
46
|
+
end
|
47
|
+
when :belongs_to
|
48
|
+
scope.records = eager_records.select do |record|
|
49
|
+
record.send(association.primary_key) == result.send(association.foreign_key)
|
50
|
+
end
|
51
|
+
result.send("#{association.id}=", scope.records.first)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
results
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
@@ -3,10 +3,12 @@ module Perry::FinderMethods
|
|
3
3
|
def find(ids_or_mode, options={})
|
4
4
|
case ids_or_mode
|
5
5
|
when Fixnum, String
|
6
|
-
self.where(
|
6
|
+
self.where(primary_key => ids_or_mode).first(options) || raise(Perry::RecordNotFound, "Could not find #{@klass} with :#{primary_key} = #{ids_or_mode}")
|
7
7
|
when Array
|
8
|
-
self.where(
|
9
|
-
|
8
|
+
self.where(primary_key => ids_or_mode).all(options).tap do |result|
|
9
|
+
unless result.size == ids_or_mode.size
|
10
|
+
raise Perry::RecordNotFound, "Couldn't find all #{@klass} with ids (#{ids_or_mode.join(',')}) (expected #{ids_or_mode.size} records but got #{result.size})."
|
11
|
+
end
|
10
12
|
end
|
11
13
|
when :all
|
12
14
|
self.all(options)
|
@@ -37,7 +39,7 @@ module Perry::FinderMethods
|
|
37
39
|
relation = clone
|
38
40
|
return relation unless options
|
39
41
|
|
40
|
-
|
42
|
+
Perry::Relation::QUERY_METHODS.each do |finder|
|
41
43
|
relation = relation.send(finder, options[finder]) if options[finder]
|
42
44
|
end
|
43
45
|
|
@@ -50,6 +52,8 @@ module Perry::FinderMethods
|
|
50
52
|
|
51
53
|
relation = relation.sql(options[:sql]) if options.has_key?(:sql)
|
52
54
|
|
55
|
+
relation = relation.modifiers(options[:modifiers]) if options.has_key?(:modifiers)
|
56
|
+
|
53
57
|
relation
|
54
58
|
end
|
55
59
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Perry::Modifiers
|
2
|
+
attr_accessor :modifiers_value, :modifiers_array
|
3
|
+
|
4
|
+
# The modifiers query method allows you to 'extend' your query by adding parameters that
|
5
|
+
# middlewares or adapters can use to modify the query itself or modify how the query is executed.
|
6
|
+
# This method expects a hash or a Proc that returns a hash as its only argument and will merge
|
7
|
+
# that hash onto a master hash of query modifiers.
|
8
|
+
#
|
9
|
+
# For most purposes, the modifiers method acts like any other query method. For example, you
|
10
|
+
# can chain it with other query methods on a relation, and you can build scopes with it.
|
11
|
+
# One exception is that modifiers are not included in the hash returned by Relation#to_hash.
|
12
|
+
# This exception is intended to discourage adapters from passing modifiers to backends external
|
13
|
+
# to perry (such as a data server or a webservice call) whose behavior is undefined with respect
|
14
|
+
# to these additional parameters/
|
15
|
+
#
|
16
|
+
# See also 'perry/middlewares/cache_records/scopes.rb' for examples of how to use the modifiers
|
17
|
+
# pseudo-query method.
|
18
|
+
def modifiers(value={})
|
19
|
+
clone.tap do |r|
|
20
|
+
if value.nil?
|
21
|
+
r.modifiers_array = [] # wipeout all previously set modifiers
|
22
|
+
else
|
23
|
+
r.modifiers_array ||= []
|
24
|
+
r.modifiers_array.push(value)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def modifiers_value
|
30
|
+
self.modifiers_array ||= []
|
31
|
+
{}.tap do |hash|
|
32
|
+
self.modifiers_array.each do |value|
|
33
|
+
hash.merge!(value.is_a?(Proc) ? value.call : value)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -1,8 +1,7 @@
|
|
1
1
|
module Perry::QueryMethods
|
2
2
|
# TRP: Define each of the variables the query options will be stored in.
|
3
|
-
attr_accessor :select_values, :group_values, :order_values, :joins_values, :
|
4
|
-
:limit_value, :offset_value, :from_value,
|
5
|
-
:raw_sql_value, :fresh_value
|
3
|
+
attr_accessor :select_values, :group_values, :order_values, :joins_values, :includes_value, :where_values, :having_values,
|
4
|
+
:limit_value, :offset_value, :from_value, :raw_sql_value
|
6
5
|
|
7
6
|
def select(*args)
|
8
7
|
if block_given?
|
@@ -26,7 +25,7 @@ module Perry::QueryMethods
|
|
26
25
|
|
27
26
|
def includes(*args)
|
28
27
|
args.reject! { |a| a.nil? }
|
29
|
-
clone.tap { |r| r.
|
28
|
+
clone.tap { |r| r.includes_value = (r.includes_value || {}).deep_merge(sanitize_includes(args)) if args_valid? args }
|
30
29
|
end
|
31
30
|
|
32
31
|
def where(*args)
|
@@ -49,13 +48,6 @@ module Perry::QueryMethods
|
|
49
48
|
clone.tap { |r| r.from_value = table }
|
50
49
|
end
|
51
50
|
|
52
|
-
def fresh(val=true)
|
53
|
-
clone.tap do |r|
|
54
|
-
r.fresh_value = val
|
55
|
-
r.reset_queries if r.fresh_value
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
51
|
def sql(raw_sql)
|
60
52
|
clone.tap { |r| r.raw_sql_value = raw_sql }
|
61
53
|
end
|
@@ -66,4 +58,20 @@ module Perry::QueryMethods
|
|
66
58
|
args.respond_to?(:empty?) ? !args.empty? : !!args
|
67
59
|
end
|
68
60
|
|
61
|
+
# This will allow for the nested structure
|
62
|
+
def sanitize_includes(values)
|
63
|
+
case values
|
64
|
+
when Hash
|
65
|
+
values.keys.inject({}) do |hash, key|
|
66
|
+
hash.merge key => sanitize_includes(values[key])
|
67
|
+
end
|
68
|
+
when Array
|
69
|
+
values.inject({}) { |hash, val| hash.merge sanitize_includes(val) }
|
70
|
+
when String, Symbol
|
71
|
+
{ values.to_sym => {} }
|
72
|
+
else
|
73
|
+
{}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
69
77
|
end
|
data/lib/perry/relation.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'perry/relation/query_methods'
|
2
2
|
require 'perry/relation/finder_methods'
|
3
|
+
require 'perry/relation/modifiers'
|
3
4
|
|
4
5
|
# TRP: The concepts behind this class are heavily influenced by ActiveRecord::Relation v.3.0.0RC1
|
5
6
|
# => http://github.com/rails/rails
|
@@ -8,13 +9,15 @@ class Perry::Relation
|
|
8
9
|
attr_reader :klass
|
9
10
|
attr_accessor :records
|
10
11
|
|
11
|
-
SINGLE_VALUE_METHODS = [:limit, :offset, :
|
12
|
-
MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :
|
12
|
+
SINGLE_VALUE_METHODS = [:limit, :offset, :includes, :from]
|
13
|
+
MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having]
|
13
14
|
|
14
|
-
|
15
|
+
QUERY_METHODS = SINGLE_VALUE_METHODS + MULTI_VALUE_METHODS
|
16
|
+
FINDER_OPTIONS = QUERY_METHODS + [:conditions, :search, :sql]
|
15
17
|
|
16
18
|
include Perry::QueryMethods
|
17
19
|
include Perry::FinderMethods
|
20
|
+
include Perry::Modifiers
|
18
21
|
|
19
22
|
def initialize(klass)
|
20
23
|
@klass = klass
|
@@ -36,6 +39,8 @@ class Perry::Relation
|
|
36
39
|
merged_relation = merged_relation.send(option, *r.send("#{option}_values"))
|
37
40
|
end
|
38
41
|
|
42
|
+
merged_relation.send(:modifiers_array=, r.send(:modifiers_array))
|
43
|
+
|
39
44
|
merged_relation
|
40
45
|
end
|
41
46
|
|
@@ -76,7 +81,7 @@ class Perry::Relation
|
|
76
81
|
end
|
77
82
|
|
78
83
|
def eager_load?
|
79
|
-
@
|
84
|
+
@includes_value
|
80
85
|
end
|
81
86
|
|
82
87
|
def inspect
|
data/lib/perry/version.rb
CHANGED
data/lib/perry.rb
CHANGED
@@ -2,9 +2,11 @@
|
|
2
2
|
require 'active_support/core_ext/array'
|
3
3
|
require 'active_support/core_ext/class/inheritable_attributes'
|
4
4
|
require 'active_support/core_ext/hash/deep_merge'
|
5
|
+
require 'active_support/core_ext/hash/keys'
|
5
6
|
begin
|
6
7
|
require 'active_support/core_ext/duplicable' #ActiveSupport 2.3.x
|
7
8
|
Hash.send(:include, ActiveSupport::CoreExtensions::Hash::DeepMerge) unless Hash.instance_methods.include?('deep_merge')
|
9
|
+
Hash.send(:include, ActiveSupport::CoreExtensions::Hash::Keys) unless Hash.instance_methods.include?('symbolize_keys')
|
8
10
|
rescue LoadError => exception
|
9
11
|
require 'active_support/core_ext/object/duplicable' #ActiveSupport 3.0.x
|
10
12
|
end
|
@@ -13,6 +15,9 @@ require 'active_support/core_ext/module/delegation'
|
|
13
15
|
# TRP: Used for pretty logging
|
14
16
|
autoload :Benchmark, 'benchmark'
|
15
17
|
|
18
|
+
# If needed to parse raw adapter responses
|
19
|
+
require 'json'
|
20
|
+
|
16
21
|
require 'ostruct'
|
17
22
|
|
18
23
|
# TRP: Perry core_ext
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: perry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 11
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 5
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.5.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Travis Petticrew
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-05-13 00:00:00 -05:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -112,6 +112,22 @@ dependencies:
|
|
112
112
|
version: 1.3.0
|
113
113
|
type: :runtime
|
114
114
|
version_requirements: *id006
|
115
|
+
- !ruby/object:Gem::Dependency
|
116
|
+
name: json
|
117
|
+
prerelease: false
|
118
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
119
|
+
none: false
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
hash: 11
|
124
|
+
segments:
|
125
|
+
- 1
|
126
|
+
- 4
|
127
|
+
- 6
|
128
|
+
version: 1.4.6
|
129
|
+
type: :runtime
|
130
|
+
version_requirements: *id007
|
115
131
|
description:
|
116
132
|
email: bobo@petticrew.net
|
117
133
|
executables: []
|
@@ -128,19 +144,25 @@ files:
|
|
128
144
|
- lib/perry/adapters/restful_http_adapter.rb
|
129
145
|
- lib/perry/adapters.rb
|
130
146
|
- lib/perry/association.rb
|
131
|
-
- lib/perry/association_preload.rb
|
132
147
|
- lib/perry/associations/common.rb
|
133
148
|
- lib/perry/associations/contains.rb
|
134
149
|
- lib/perry/associations/external.rb
|
135
150
|
- lib/perry/base.rb
|
136
|
-
- lib/perry/cacheable/entry.rb
|
137
|
-
- lib/perry/cacheable/store.rb
|
138
|
-
- lib/perry/cacheable.rb
|
139
151
|
- lib/perry/core_ext/kernel/singleton_class.rb
|
140
152
|
- lib/perry/errors.rb
|
141
153
|
- lib/perry/logger.rb
|
154
|
+
- lib/perry/middlewares/cache_records/entry.rb
|
155
|
+
- lib/perry/middlewares/cache_records/scopes.rb
|
156
|
+
- lib/perry/middlewares/cache_records/store.rb
|
157
|
+
- lib/perry/middlewares/cache_records.rb
|
158
|
+
- lib/perry/middlewares/model_bridge.rb
|
159
|
+
- lib/perry/middlewares.rb
|
160
|
+
- lib/perry/persistence/response.rb
|
142
161
|
- lib/perry/persistence.rb
|
162
|
+
- lib/perry/processors/preload_associations.rb
|
163
|
+
- lib/perry/processors.rb
|
143
164
|
- lib/perry/relation/finder_methods.rb
|
165
|
+
- lib/perry/relation/modifiers.rb
|
144
166
|
- lib/perry/relation/query_methods.rb
|
145
167
|
- lib/perry/relation.rb
|
146
168
|
- lib/perry/scopes/conditions.rb
|
@@ -179,7 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
179
201
|
requirements: []
|
180
202
|
|
181
203
|
rubyforge_project:
|
182
|
-
rubygems_version: 1.
|
204
|
+
rubygems_version: 1.6.2
|
183
205
|
signing_key:
|
184
206
|
specification_version: 3
|
185
207
|
summary: Ruby library for querying and mapping data through generic interfaces
|