-
Notifications
You must be signed in to change notification settings - Fork 360
/
collection.rb
94 lines (85 loc) · 2.97 KB
/
collection.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# frozen_string_literal: true
require "active_support/core_ext/module/delegation"
require "active_support/inflector"
module ActiveResource # :nodoc:
class Collection # :nodoc:
SELF_DEFINE_METHODS = [:to_a, :collect!, :map!, :all?]
include Enumerable
delegate :to_yaml, :all?, *(Array.instance_methods(false) - SELF_DEFINE_METHODS), to: :to_a
# The array of actual elements returned by index actions
attr_accessor :elements, :resource_class, :original_params
# ActiveResource::Collection is a wrapper to handle parsing index responses that
# do not directly map to Rails conventions.
#
# You can define a custom class that inherits from ActiveResource::Collection
# in order to to set the elements instance.
#
# GET /posts.json delivers following response body:
# {
# posts: [
# {
# title: "ActiveResource now has associations",
# body: "Lorem Ipsum"
# },
# {...}
# ],
# next_page: "/posts.json?page=2"
# }
#
# A Post class can be setup to handle it with:
#
# class Post < ActiveResource::Base
# self.site = "http://example.com"
# self.collection_parser = PostCollection
# end
#
# And the collection parser:
#
# class PostCollection < ActiveResource::Collection
# attr_accessor :next_page
# def initialize(parsed = {})
# @elements = parsed['posts']
# @next_page = parsed['next_page']
# end
# end
#
# The result from a find method that returns multiple entries will now be a
# PostParser instance. ActiveResource::Collection includes Enumerable and
# instances can be iterated over just like an array.
# @posts = Post.find(:all) # => PostCollection:xxx
# @posts.next_page # => "/posts.json?page=2"
# @posts.map(&:id) # =>[1, 3, 5 ...]
#
# The initialize method will receive the ActiveResource::Formats parsed result
# and should set @elements.
def initialize(elements = [])
@elements = elements
end
def to_a
elements
end
def collect!
return elements unless block_given?
set = []
each { |o| set << yield(o) }
@elements = set
self
end
alias map! collect!
def first_or_create(attributes = {})
first || resource_class.create(original_params.update(attributes))
rescue NoMethodError
raise "Cannot create resource from resource type: #{resource_class.inspect}"
end
def first_or_initialize(attributes = {})
first || resource_class.new(original_params.update(attributes))
rescue NoMethodError
raise "Cannot build resource from resource type: #{resource_class.inspect}"
end
def where(clauses = {})
raise ArgumentError, "expected a clauses Hash, got #{clauses.inspect}" unless clauses.is_a? Hash
new_clauses = original_params.merge(clauses)
resource_class.where(new_clauses)
end
end
end