rooftop 0.0.6 → 0.0.7.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rooftop.rb +14 -8
- data/lib/rooftop/base.rb +16 -8
- data/lib/rooftop/coercions.rb +5 -0
- data/lib/rooftop/coercions/title_coercion.rb +26 -0
- data/lib/rooftop/content/collection.rb +14 -3
- data/lib/rooftop/content/content_fields.rb +6 -1
- data/lib/rooftop/content/field.rb +24 -2
- data/lib/rooftop/errors/unresolveable_link_error.rb +5 -0
- data/lib/rooftop/field_aliases.rb +6 -0
- data/lib/rooftop/middleware/debug_middleware.rb +60 -0
- data/lib/rooftop/middleware/embed_middleware.rb +18 -0
- data/lib/rooftop/{headers.rb → middleware/headers.rb} +4 -0
- data/lib/rooftop/middleware/pagination_middleware.rb +26 -0
- data/lib/rooftop/nested.rb +19 -2
- data/lib/rooftop/page.rb +6 -0
- data/lib/rooftop/pagination.rb +16 -0
- data/lib/rooftop/queries/queries.rb +29 -3
- data/lib/rooftop/resource_links/collection.rb +2 -2
- data/lib/rooftop/resource_links/link.rb +19 -3
- data/lib/rooftop/resource_links/resource_links.rb +31 -5
- data/lib/rooftop/scopes.rb +9 -0
- data/lib/rooftop/version.rb +1 -1
- metadata +10 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf9827cc2965fecd6ca71d8ab14d8977e156691b
|
4
|
+
data.tar.gz: 15b808878885da0a5888bd862eae95f5fcf03e46
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 07d4ef3d546e300f33c99887658d0efe9e3a231e13e7f7bd1e519d879d3b64c108ba21ce3e7720eac5e4d1dc534b2780e462b54463624872113e51686aed6825
|
7
|
+
data.tar.gz: d1817d197e0a617c5321a833a6cf547023bdb93ce5ceb80e1cd73904bf8dece8c0d7a243f1e993402d749a5de1bc1378346a8220b39a6feb72657d59bf82dc89
|
data/lib/rooftop.rb
CHANGED
@@ -9,8 +9,8 @@ module Rooftop
|
|
9
9
|
DEFAULT_API_VERSION = 2
|
10
10
|
|
11
11
|
class << self
|
12
|
-
#accessor to set
|
13
|
-
attr_accessor :
|
12
|
+
#accessor to set whether we're in privew mode
|
13
|
+
attr_accessor :preview, :debug_requests, :debug_responses
|
14
14
|
|
15
15
|
#access the configuration class as Rooftop.configuration
|
16
16
|
attr_accessor :configuration
|
@@ -25,7 +25,7 @@ module Rooftop
|
|
25
25
|
end
|
26
26
|
|
27
27
|
class Configuration
|
28
|
-
attr_accessor :api_token, :url, :site_name, :perform_caching, :cache_store, :cache_logger, :ssl_options, :proxy, :post_type_mapping
|
28
|
+
attr_accessor :api_token, :url, :site_name, :perform_caching, :cache_store, :cache_logger, :ssl_options, :proxy, :post_type_mapping, :logger
|
29
29
|
attr_reader :connection,
|
30
30
|
:connection_path,
|
31
31
|
:api_path, #actually writeable with custom setter
|
@@ -45,16 +45,13 @@ module Rooftop
|
|
45
45
|
@ssl_options = {}
|
46
46
|
@proxy = nil
|
47
47
|
@post_type_mapping = {}
|
48
|
+
@logger = nil
|
48
49
|
end
|
49
50
|
|
50
51
|
def api_path=(path)
|
51
52
|
@api_path = path || @api_path
|
52
53
|
end
|
53
54
|
|
54
|
-
def user_agent=(agent)
|
55
|
-
@user_agent = agent || @user_agent
|
56
|
-
end
|
57
|
-
|
58
55
|
def extra_headers=(headers)
|
59
56
|
@extra_headers = headers || @extra_headers
|
60
57
|
end
|
@@ -80,7 +77,16 @@ module Rooftop
|
|
80
77
|
|
81
78
|
@connection_path = "#{@url}#{@api_path}"
|
82
79
|
|
83
|
-
@connection.setup url: @connection_path, ssl: @ssl_options, proxy: @proxy do |c|
|
80
|
+
@connection.setup url: @connection_path, ssl: @ssl_options, proxy: @proxy, send_only_modified_attributes: true do |c|
|
81
|
+
c.use Rooftop::EmbedMiddleware
|
82
|
+
|
83
|
+
c.use Rooftop::PaginationMiddleware
|
84
|
+
|
85
|
+
if @logger
|
86
|
+
c.use Rooftop::DebugMiddleware
|
87
|
+
end
|
88
|
+
|
89
|
+
|
84
90
|
#Headers
|
85
91
|
c.use Rooftop::Headers
|
86
92
|
|
data/lib/rooftop/base.rb
CHANGED
@@ -19,16 +19,26 @@ module Rooftop
|
|
19
19
|
base.include Rooftop::Queries
|
20
20
|
# Links mixin handles the _links key in a response
|
21
21
|
base.include Rooftop::ResourceLinks
|
22
|
+
|
23
|
+
# Pagination mixin - uses pagination metadata set in the PaginationMiddleware
|
24
|
+
base.include Rooftop::Pagination
|
25
|
+
|
22
26
|
# Use the API instance we have configured - in a proc because we can't control load order
|
23
27
|
base.send(:use_api,->{Rooftop.configuration.connection})
|
24
28
|
|
25
29
|
# Turn calls to `content` into a collection of Rooftop::ContentField objects
|
26
30
|
base.include Rooftop::Content
|
27
31
|
|
32
|
+
# Add some useful scopes
|
33
|
+
base.include Rooftop::Scopes
|
34
|
+
|
35
|
+
# Coerce the title field from an object to a string
|
36
|
+
base.include Rooftop::Coercions::TitleCoercion
|
37
|
+
|
28
38
|
# Date and Modified fields are pretty universal in responses from WP, so we can automatically
|
29
39
|
# coerce these to DateTime.
|
30
|
-
base.send(:coerce_field,date: ->(date) {DateTime.parse(date)})
|
31
|
-
base.send(:coerce_field,modified: ->(modified) {DateTime.parse(modified)})
|
40
|
+
base.send(:coerce_field,date: ->(date) {DateTime.parse(date.to_s) unless date.nil?})
|
41
|
+
base.send(:coerce_field,modified: ->(modified) {DateTime.parse(modified.to_s) unless modified.nil?})
|
32
42
|
|
33
43
|
# Having coerced the fields, we can alias them (order is important - coerce first.)
|
34
44
|
base.send(:alias_field, date: :created_at)
|
@@ -64,7 +74,6 @@ module Rooftop
|
|
64
74
|
def setup_path!
|
65
75
|
@api_endpoint ||= collection_path
|
66
76
|
self.collection_path "#{@api_namespace}/v#{@api_version}/#{@api_endpoint}"
|
67
|
-
|
68
77
|
end
|
69
78
|
|
70
79
|
# Allow calling 'first'
|
@@ -72,10 +81,9 @@ module Rooftop
|
|
72
81
|
all.first
|
73
82
|
end
|
74
83
|
|
75
|
-
|
76
|
-
|
77
|
-
|
84
|
+
def reload!
|
85
|
+
self.class.find(self.id) if self.id
|
86
|
+
end
|
78
87
|
end
|
79
|
-
|
80
88
|
end
|
81
|
-
end
|
89
|
+
end
|
data/lib/rooftop/coercions.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Coercions
|
3
|
+
module TitleCoercion
|
4
|
+
def self.included(base)
|
5
|
+
base.send(:after_find, :coerce_title_to_string)
|
6
|
+
base.send(:after_save, :coerce_title_to_string)
|
7
|
+
|
8
|
+
base.send(:before_save, ->(record) {
|
9
|
+
if record.respond_to?(:title) && record.respond_to?(:title_object)
|
10
|
+
record.title_object ||= {}
|
11
|
+
record.title_object[:rendered] = record.title
|
12
|
+
end
|
13
|
+
})
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
def coerce_title_to_string
|
18
|
+
record = self
|
19
|
+
if record.respond_to?(:title) && record.title.is_a?(ActiveSupport::HashWithIndifferentAccess)
|
20
|
+
record.title_object = record.title
|
21
|
+
record.title = record.title[:rendered]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -2,9 +2,20 @@ module Rooftop
|
|
2
2
|
module Content
|
3
3
|
class Collection < ::Array
|
4
4
|
def initialize(content_fields)
|
5
|
-
|
6
|
-
|
5
|
+
content_fields.each do |field|
|
6
|
+
# if the field has a 'fields' key, it is a repeater field. Collect the sub-fields and
|
7
|
+
# set the field content to the collection of repeated fields
|
8
|
+
if field.has_key?('fields')
|
9
|
+
repeated_fields = field[:fields].collect do |repeated_fields|
|
10
|
+
repeated_fields.collect{|field| Rooftop::Content::Field.new(field)}
|
11
|
+
end
|
12
|
+
|
13
|
+
field.delete(:fields)
|
14
|
+
field[:value] = repeated_fields
|
7
15
|
end
|
16
|
+
|
17
|
+
self << Rooftop::Content::Field.new(field)
|
18
|
+
end
|
8
19
|
end
|
9
20
|
|
10
21
|
# Find content_fields by attribute. Assume there will only be one attribute in the search
|
@@ -42,4 +53,4 @@ module Rooftop
|
|
42
53
|
|
43
54
|
end
|
44
55
|
end
|
45
|
-
end
|
56
|
+
end
|
@@ -34,6 +34,11 @@ module Rooftop
|
|
34
34
|
r.fields = Rooftop::Content::Collection.new((basic_fields + advanced_fields))
|
35
35
|
end
|
36
36
|
})
|
37
|
+
|
38
|
+
base.send(:before_save, ->(r) {
|
39
|
+
r.restore_fields! unless r.new?
|
40
|
+
#TODO we need to write these back into the actual fields.
|
41
|
+
})
|
37
42
|
end
|
38
43
|
end
|
39
|
-
end
|
44
|
+
end
|
@@ -2,11 +2,33 @@ module Rooftop
|
|
2
2
|
module Content
|
3
3
|
class Field < ::OpenStruct
|
4
4
|
|
5
|
+
#todo - this would be nice to get working. For a relationship, we should be returning the object not a big hash
|
6
|
+
# def initialize(hash=nil)
|
7
|
+
# if hash.has_key?(:type) && hash[:type] == "relationship"
|
8
|
+
# related_objects = [hash[:value]].flatten
|
9
|
+
# hash[:value] = related_objects.inject([]) do |array,object|
|
10
|
+
# begin
|
11
|
+
# klass = Rooftop.configuration.post_type_mapping[object[:post_type].to_sym] || object[:post_type].to_s.classify.constantize
|
12
|
+
# array << klass.new(object).run_callbacks(:find)
|
13
|
+
# rescue
|
14
|
+
# array << object
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
# super
|
18
|
+
# else
|
19
|
+
# super
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
|
23
|
+
|
5
24
|
|
6
25
|
def to_s
|
7
|
-
|
26
|
+
if respond_to?(:value) && value.is_a?(String)
|
27
|
+
value
|
28
|
+
else
|
29
|
+
inspect
|
30
|
+
end
|
8
31
|
end
|
9
|
-
|
10
32
|
end
|
11
33
|
end
|
12
34
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Code courtesty https://github.com/envylabs/faraday-detailed_logger - MIT licence
|
2
|
+
|
3
|
+
module Rooftop
|
4
|
+
class DebugMiddleware < Faraday::Response::Middleware
|
5
|
+
|
6
|
+
def self.default_logger
|
7
|
+
require "logger"
|
8
|
+
::Logger.new(STDOUT)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Public: Initialize a new Logger middleware.
|
12
|
+
#
|
13
|
+
# app - A Faraday-compatible middleware stack or application.
|
14
|
+
# logger - A Logger-compatible object to which the log information will
|
15
|
+
# be recorded.
|
16
|
+
# progname - A String containing a program name to use when logging.
|
17
|
+
#
|
18
|
+
# Returns a Logger instance.
|
19
|
+
#
|
20
|
+
def initialize(app, logger = nil, progname = nil)
|
21
|
+
super(app)
|
22
|
+
@logger = logger || self.class.default_logger
|
23
|
+
@progname = progname
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def call(env)
|
28
|
+
if Rooftop.debug_requests
|
29
|
+
@logger.info(@progname) { "#{env[:method].upcase} #{env[:url]}" }
|
30
|
+
@logger.debug(@progname) { curl_output(env[:request_headers], env[:body]).inspect }
|
31
|
+
end
|
32
|
+
super
|
33
|
+
end
|
34
|
+
|
35
|
+
def on_complete(env)
|
36
|
+
if Rooftop.debug_responses
|
37
|
+
status = env[:status]
|
38
|
+
log_response_status(@progname, status) { "HTTP #{status}" }
|
39
|
+
@logger.debug(@progname) { curl_output(env[:response_headers], env[:body]).inspect }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
def curl_output(headers, body)
|
45
|
+
string = headers.collect { |k,v| "#{k}: #{v}" }.join("\n")
|
46
|
+
string + "\n\n#{body}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def log_response_status(progname, status, &block)
|
50
|
+
case status
|
51
|
+
when 200..399
|
52
|
+
@logger.info(progname, &block)
|
53
|
+
else
|
54
|
+
@logger.warn(progname, &block)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# This is a bit hacky. It looks like Her.rb strips querystrings with an underscore, and WP requires
|
2
|
+
# '?_embed' in order to embed child links. We look for a query param called 'embed' and change it
|
3
|
+
# to _embed (as well as sending the original)
|
4
|
+
|
5
|
+
module Rooftop
|
6
|
+
class EmbedMiddleware < Faraday::Middleware
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
query = Faraday::Utils.parse_query(env.url.query) || {}
|
10
|
+
query["_embed"] = true if query.has_key?("include_embedded_resources")
|
11
|
+
query["per_page"] = 99999999 unless query.has_key?("per_page")
|
12
|
+
env.url.query = Faraday::Utils.build_query(query.except("include_embedded_resources"))
|
13
|
+
@app.call env
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -5,6 +5,10 @@ module Rooftop
|
|
5
5
|
env[:request_headers]["Api-Token"] = Rooftop.configuration.api_token
|
6
6
|
end
|
7
7
|
|
8
|
+
if Rooftop.preview
|
9
|
+
env[:request_headers]['preview'] = "true"
|
10
|
+
end
|
11
|
+
|
8
12
|
Rooftop.configuration.extra_headers.each do |key,value|
|
9
13
|
env[:request_headers][key.to_s] = value
|
10
14
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Rooftop
|
2
|
+
class PaginationMiddleware < Faraday::Response::Middleware
|
3
|
+
def on_complete(env)
|
4
|
+
@env = env
|
5
|
+
|
6
|
+
pagination = {
|
7
|
+
total_count: header("x-wp-total").to_i,
|
8
|
+
total_pages: header("x-wp-totalpages").to_i,
|
9
|
+
per_page: (header("x-wp-per-page").to_i || 10),
|
10
|
+
page: header("x-wp-page").to_i || 1
|
11
|
+
}
|
12
|
+
|
13
|
+
env[:body].merge!(pagination: pagination)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# Returns a response header value.
|
19
|
+
#
|
20
|
+
# @param [String] name of the header attribute
|
21
|
+
# @return [String] the response header value
|
22
|
+
def header(name)
|
23
|
+
@env.response_headers[name]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/rooftop/nested.rb
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
module Rooftop
|
2
2
|
module Nested
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
@nested_classes ||= []
|
6
|
+
@nested_classes << base unless @nested_classes.include?(base)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.nested_classes
|
10
|
+
@nested_classes
|
11
|
+
end
|
12
|
+
|
13
|
+
def root
|
14
|
+
ancestors.last || resource_links.find_by(link_type: 'self').first
|
15
|
+
end
|
3
16
|
|
4
17
|
def ancestors
|
5
18
|
if respond_to?(:resource_links)
|
@@ -18,9 +31,13 @@ module Rooftop
|
|
18
31
|
end
|
19
32
|
|
20
33
|
def parent
|
21
|
-
if respond_to?(:resource_links)
|
22
|
-
|
34
|
+
if respond_to?(:resource_links) && resource_links
|
35
|
+
ancestors.first
|
23
36
|
end
|
24
37
|
end
|
38
|
+
|
39
|
+
def siblings
|
40
|
+
self.class.find(parent.id).children.reject! {|c| c.id == self.id}
|
41
|
+
end
|
25
42
|
end
|
26
43
|
end
|
data/lib/rooftop/page.rb
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
module Rooftop
|
2
2
|
module Page
|
3
3
|
def self.included(base)
|
4
|
+
@page_classes ||= []
|
5
|
+
@page_classes << base unless @page_classes.include?(base)
|
4
6
|
base.include Rooftop::Base
|
5
7
|
base.include Rooftop::Nested
|
6
8
|
base.extend ClassMethods
|
7
9
|
end
|
8
10
|
|
11
|
+
def self.page_classes
|
12
|
+
@page_classes
|
13
|
+
end
|
14
|
+
|
9
15
|
module ClassMethods
|
10
16
|
|
11
17
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Pagination
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def new_collection(parsed_data)
|
9
|
+
parsed_data[:metadata] ||= {}
|
10
|
+
parsed_data[:metadata][:pagination] = parsed_data[:pagination]
|
11
|
+
|
12
|
+
Her::Model::Attributes.initialize_collection(self, parsed_data)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,12 +1,13 @@
|
|
1
1
|
module Rooftop
|
2
2
|
module Queries
|
3
|
+
PER_PAGE = 99999999
|
3
4
|
def self.included(base)
|
4
5
|
base.extend ClassMethods
|
5
6
|
end
|
6
7
|
|
7
8
|
module ClassMethods
|
8
9
|
# We need to fix up the `where()` filter. WP-API expects a url format for filters like this:
|
9
|
-
# /?filter[something]=foo.
|
10
|
+
# /?filter[something]=foo. But we have a magic hash key to allow us to send things which aren't mangled.
|
10
11
|
def where(args)
|
11
12
|
args = HashWithIndifferentAccess.new(args)
|
12
13
|
# the fact that 'slug' is referred to in the db as 'name' is irritating. Let's fix that
|
@@ -34,7 +35,27 @@ module Rooftop
|
|
34
35
|
end
|
35
36
|
args.delete(:id)
|
36
37
|
end
|
37
|
-
|
38
|
+
|
39
|
+
if args.keys.include?('per_page')
|
40
|
+
per_page = args['per_page']
|
41
|
+
args[:no_filter] ||= []
|
42
|
+
args[:no_filter] << :per_page unless args[:no_filter].include?('per_page')
|
43
|
+
else
|
44
|
+
per_page = Rooftop::Queries::PER_PAGE
|
45
|
+
end
|
46
|
+
|
47
|
+
if args.keys.collect(&:to_sym).include?(:no_filter)
|
48
|
+
args_to_filter = args.except(*args[:no_filter]).except(:no_filter)
|
49
|
+
args_not_to_filter = args.except(args_to_filter).except(:no_filter)
|
50
|
+
filters = args_to_filter.inject({}) {|hash,pair| hash["filter[#{pair.first}]"] = pair.last; hash}
|
51
|
+
filters = {per_page: per_page}.merge(filters).merge(args_not_to_filter)
|
52
|
+
else
|
53
|
+
#TODO DRY
|
54
|
+
filters = args.inject({}) {|hash,pair| hash["filter[#{pair.first}]"] = pair.last; hash}
|
55
|
+
filters = {per_page: per_page}.merge(filters)
|
56
|
+
end
|
57
|
+
|
58
|
+
# we probably want every result without pagination, unless we specify otherwise
|
38
59
|
#Call the Her `where` method with our new filters
|
39
60
|
super().where(filters)
|
40
61
|
end
|
@@ -49,6 +70,11 @@ module Rooftop
|
|
49
70
|
raise Rooftop::RecordNotFoundError
|
50
71
|
end
|
51
72
|
end
|
73
|
+
|
74
|
+
# 'all' needs to have a querystring param passed to really get all. It should be -1 but for some reason that's not working.
|
75
|
+
def all(args = {})
|
76
|
+
super({per_page: Rooftop::Queries::PER_PAGE}.merge(args))
|
77
|
+
end
|
52
78
|
end
|
53
79
|
end
|
54
|
-
end
|
80
|
+
end
|
@@ -2,10 +2,10 @@ module Rooftop
|
|
2
2
|
module ResourceLinks
|
3
3
|
class Collection < ::Array
|
4
4
|
attr_reader :links
|
5
|
-
def initialize(links)
|
5
|
+
def initialize(links, klass=nil)
|
6
6
|
links.each do |link_type,links|
|
7
7
|
links.each do |link|
|
8
|
-
self << Rooftop::ResourceLinks::Link.new(link_type,link)
|
8
|
+
self << Rooftop::ResourceLinks::Link.new(link_type,link, klass)
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
@@ -2,13 +2,29 @@ module Rooftop
|
|
2
2
|
module ResourceLinks
|
3
3
|
class Link < ::OpenStruct
|
4
4
|
attr_accessor :link_type
|
5
|
-
def initialize(link_type,args)
|
5
|
+
def initialize(link_type,args, klass=nil)
|
6
6
|
@link_type = link_type
|
7
|
+
@mapped_class = klass.try(:resource_link_mapping).try(:[],@link_type)
|
7
8
|
super(args)
|
8
9
|
end
|
9
10
|
|
10
|
-
def resolve
|
11
|
-
|
11
|
+
def resolve(klass=nil)
|
12
|
+
# We need to figure out what we're going to instantiate. If it's in the resource link mapping, use that. If not, try the klass passed into the resolve() method. Failing that, make an attempt to constantize something; otherwise we're going to have to raise
|
13
|
+
@mapped_class ||= klass || @link_type.camelize.classify.constantize
|
14
|
+
if @mapped_class
|
15
|
+
# If this link has an ID, we can call find() on the class
|
16
|
+
if respond_to?(:id)
|
17
|
+
return @mapped_class.send(:find, id)
|
18
|
+
else
|
19
|
+
# otherwise we're going to have make a call to the link's href.
|
20
|
+
result = @mapped_class.get(href)
|
21
|
+
result.run_callbacks(:find)
|
22
|
+
return result
|
23
|
+
end
|
24
|
+
else
|
25
|
+
raise Rooftop::ResourceLinks::UnresolvableLinkError, "Couldn't resolve a link of type #{@link_type}. Try passing the class you want to resolve to."
|
26
|
+
end
|
27
|
+
|
12
28
|
end
|
13
29
|
end
|
14
30
|
end
|
@@ -1,15 +1,41 @@
|
|
1
1
|
module Rooftop
|
2
2
|
module ResourceLinks
|
3
3
|
CUSTOM_LINK_RELATION_BASE = "http://docs.rooftopcms.com/link_relations"
|
4
|
+
|
4
5
|
def self.included(base)
|
5
6
|
# set up an attribute called resource_links, which is a collection of links
|
6
7
|
# to other resources in the API.
|
7
|
-
base.send(:after_find,
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
base.send(:after_find, :generate_resource_links)
|
9
|
+
base.send(:after_save, :generate_resource_links)
|
10
|
+
base.extend ClassMethods
|
11
|
+
base.configure_resource_link_mapping
|
12
|
+
end
|
13
|
+
|
14
|
+
def generate_resource_links
|
15
|
+
if self.respond_to?(:"_links")
|
16
|
+
self.resource_links = Rooftop::ResourceLinks::Collection.new(self._links, self.class)
|
17
|
+
end
|
12
18
|
end
|
13
19
|
|
20
|
+
module ClassMethods
|
21
|
+
# This class-level attribute allows us to set a mapping between a resource link name (which is probably
|
22
|
+
# an href, but might be "up" or something) and a class. It means that when we try to resolve a link of a
|
23
|
+
# given name, we know what type of class to instantiate
|
24
|
+
attr_accessor :resource_link_mapping
|
25
|
+
|
26
|
+
def configure_resource_link_mapping
|
27
|
+
@resource_link_mapping ||= {}
|
28
|
+
@resource_link_mapping.merge!({
|
29
|
+
"author" => Rooftop::Author,
|
30
|
+
"https://api.w.org/attachment" => Rooftop::MediaItem,
|
31
|
+
"self" => self,
|
32
|
+
"up" => self,
|
33
|
+
"http://docs.rooftopcms.com/link_relations/ancestors" => self,
|
34
|
+
"http://docs.rooftopcms.com/link_relations/children" => self
|
35
|
+
})
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
14
40
|
end
|
15
41
|
end
|
data/lib/rooftop/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rooftop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ed Jones
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-05-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -112,28 +112,35 @@ files:
|
|
112
112
|
- lib/rooftop/coercions.rb
|
113
113
|
- lib/rooftop/coercions/author_coercion.rb
|
114
114
|
- lib/rooftop/coercions/parent_coercion.rb
|
115
|
+
- lib/rooftop/coercions/title_coercion.rb
|
115
116
|
- lib/rooftop/content/collection.rb
|
116
117
|
- lib/rooftop/content/content_fields.rb
|
117
118
|
- lib/rooftop/content/field.rb
|
118
119
|
- lib/rooftop/errors/field_not_found_error.rb
|
119
120
|
- lib/rooftop/errors/record_not_found_error.rb
|
120
121
|
- lib/rooftop/errors/unmapped_object_error.rb
|
122
|
+
- lib/rooftop/errors/unresolveable_link_error.rb
|
121
123
|
- lib/rooftop/field_aliases.rb
|
122
|
-
- lib/rooftop/headers.rb
|
123
124
|
- lib/rooftop/hook_calls.rb
|
124
125
|
- lib/rooftop/menus/item.rb
|
125
126
|
- lib/rooftop/menus/menu.rb
|
127
|
+
- lib/rooftop/middleware/debug_middleware.rb
|
128
|
+
- lib/rooftop/middleware/embed_middleware.rb
|
129
|
+
- lib/rooftop/middleware/headers.rb
|
130
|
+
- lib/rooftop/middleware/pagination_middleware.rb
|
126
131
|
- lib/rooftop/models/author.rb
|
127
132
|
- lib/rooftop/models/media_item.rb
|
128
133
|
- lib/rooftop/models/taxonomy.rb
|
129
134
|
- lib/rooftop/models/taxonomy_term.rb
|
130
135
|
- lib/rooftop/nested.rb
|
131
136
|
- lib/rooftop/page.rb
|
137
|
+
- lib/rooftop/pagination.rb
|
132
138
|
- lib/rooftop/post.rb
|
133
139
|
- lib/rooftop/queries/queries.rb
|
134
140
|
- lib/rooftop/resource_links/collection.rb
|
135
141
|
- lib/rooftop/resource_links/link.rb
|
136
142
|
- lib/rooftop/resource_links/resource_links.rb
|
143
|
+
- lib/rooftop/scopes.rb
|
137
144
|
- lib/rooftop/version.rb
|
138
145
|
- rooftop.gemspec
|
139
146
|
homepage: http://www.rooftopcms.com
|