rooftop 0.0.1 → 0.0.3

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +621 -22
  3. data/README.md +168 -25
  4. data/lib/rooftop/base.rb +74 -0
  5. data/lib/{rooftop_client → rooftop}/client.rb +0 -0
  6. data/lib/rooftop/coercions/author_coercion.rb +10 -0
  7. data/lib/rooftop/coercions/parent_coercion.rb +47 -0
  8. data/lib/{rooftop_client → rooftop}/coercions.rb +10 -3
  9. data/lib/rooftop/content_fields/collection.rb +23 -0
  10. data/lib/rooftop/content_fields/content_fields.rb +39 -0
  11. data/lib/rooftop/content_fields/field.rb +12 -0
  12. data/lib/rooftop/errors/record_not_found.rb +3 -0
  13. data/lib/rooftop/field_aliases.rb +41 -0
  14. data/lib/{rooftop_client → rooftop}/headers.rb +1 -1
  15. data/lib/rooftop/hook_calls.rb +40 -0
  16. data/lib/{rooftop_client → rooftop}/models/author.rb +0 -0
  17. data/lib/{rooftop_client → rooftop}/models/media_item.rb +1 -1
  18. data/lib/rooftop/models/menu.rb +9 -0
  19. data/lib/{rooftop_client → rooftop}/models/menu_item.rb +0 -0
  20. data/lib/{rooftop_client → rooftop}/models/taxonomy.rb +0 -0
  21. data/lib/{rooftop_client → rooftop}/models/taxonomy_term.rb +1 -1
  22. data/lib/rooftop/nested.rb +26 -0
  23. data/lib/rooftop/page.rb +17 -0
  24. data/lib/{rooftop_client → rooftop}/post.rb +2 -2
  25. data/lib/{rooftop_client → rooftop}/queries/queries.rb +11 -0
  26. data/lib/rooftop/resource_links/collection.rb +22 -0
  27. data/lib/rooftop/resource_links/link.rb +15 -0
  28. data/lib/rooftop/resource_links/resource_links.rb +15 -0
  29. data/lib/rooftop/version.rb +3 -0
  30. data/lib/rooftop.rb +54 -7
  31. data/rooftop_ruby_client.gemspec +3 -2
  32. metadata +43 -19
  33. data/lib/rooftop_client/base.rb +0 -38
  34. data/lib/rooftop_client/coercions/author_coercion.rb +0 -8
  35. data/lib/rooftop_client/coercions/parent_coercion.rb +0 -45
  36. data/lib/rooftop_client/models/menu.rb +0 -8
  37. data/lib/rooftop_client/page.rb +0 -19
  38. data/lib/rooftop_client/version.rb +0 -3
@@ -2,13 +2,13 @@ module Rooftop
2
2
  module Post
3
3
  def self.included(base)
4
4
  base.include Rooftop::Base
5
+ base.include Rooftop::Nested
5
6
  base.extend ClassMethods
6
- base.send(:collection_path,"posts")
7
7
  end
8
8
 
9
9
  module ClassMethods
10
10
  def post_type=(type)
11
- self.send(:default_scope, ->{ where(type: type) })
11
+ self.api_endpoint = type.pluralize
12
12
  end
13
13
  end
14
14
  end
@@ -19,6 +19,17 @@ module Rooftop
19
19
  #Call the Her `where` method with our new filters
20
20
  super().where(filters)
21
21
  end
22
+
23
+ alias_method :find_by, :where
24
+
25
+ def find_by!(args)
26
+ results = find_by(args)
27
+ if results.present?
28
+ results
29
+ else
30
+ raise Rooftop::RecordNotFound
31
+ end
32
+ end
22
33
  end
23
34
  end
24
35
  end
@@ -0,0 +1,22 @@
1
+ module Rooftop
2
+ module ResourceLinks
3
+ class Collection < ::Array
4
+ attr_reader :links
5
+ def initialize(links)
6
+ links.each do |link_type,links|
7
+ links.each do |link|
8
+ self << Rooftop::ResourceLinks::Link.new(link_type,link)
9
+ end
10
+ end
11
+ end
12
+
13
+ # Find links by attribute. Assume there will only be one attribute in the search
14
+ def find_by(hash)
15
+ raise ArgumentError, "you can only find a resource link by one attribute at a time" unless hash.length == 1
16
+ attr = hash.first.first
17
+ val = hash.first.last
18
+ self.select {|l| l.send(attr) == val.to_s}
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,15 @@
1
+ module Rooftop
2
+ module ResourceLinks
3
+ class Link < ::OpenStruct
4
+ attr_accessor :link_type
5
+ def initialize(link_type,args)
6
+ @link_type = link_type
7
+ super(args)
8
+ end
9
+
10
+ def resolve
11
+ raise NotImplementedError, "TODO: resolve the link."
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Rooftop
2
+ module ResourceLinks
3
+ CUSTOM_LINK_RELATION_BASE = "http://docs.rooftopcms.com/link_relations"
4
+ def self.included(base)
5
+ # set up an attribute called resource_links, which is a collection of links
6
+ # to other resources in the API.
7
+ base.send(:after_find, ->(r) {
8
+ if r.respond_to?(:"_links")
9
+ r.resource_links = Rooftop::ResourceLinks::Collection.new(r._links)
10
+ end
11
+ })
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ module Rooftop
2
+ VERSION = "0.0.3"
3
+ end
data/lib/rooftop.rb CHANGED
@@ -1,10 +1,13 @@
1
1
  require 'her'
2
+ require 'faraday-http-cache'
2
3
  require 'require_all'
3
- require_rel '.'
4
-
5
4
  require "active_support/all"
6
5
 
7
6
  module Rooftop
7
+
8
+ DEFAULT_API_NAMESPACE = "wp"
9
+ DEFAULT_API_VERSION = 2
10
+
8
11
  class << self
9
12
  #accessor to set the preview API for use instead of the production one
10
13
  attr_accessor :use_preview_api
@@ -22,12 +25,45 @@ module Rooftop
22
25
  end
23
26
 
24
27
  class Configuration
25
- attr_accessor :api_token, :url, :extra_headers
26
- attr_reader :connection
28
+ attr_accessor :api_token, :url, :site_name, :perform_caching, :cache_store, :cache_logger, :ssl_options, :proxy
29
+ attr_reader :connection,
30
+ :connection_path,
31
+ :api_path, #actually writeable with custom setter
32
+ :extra_headers, #actually writeable with custom setter
33
+ :advanced_options, #actually writeable with custom setter
34
+ :user_agent #actually writeable with custom setter
27
35
 
28
36
  def initialize
29
- @extra_headers ||= []
37
+ @extra_headers = {}
30
38
  @connection ||= Her::API.new
39
+ @advanced_options = {}
40
+ @api_path = "/wp-json/"
41
+ @user_agent = "Rooftop CMS Ruby client #{Rooftop::VERSION} (http://github.com/rooftopcms/rooftop-ruby)"
42
+ @perform_caching = false
43
+ @cache_store = ActiveSupport::Cache.lookup_store(:memory_store)
44
+ @cache_logger = nil
45
+ @ssl_options = {}
46
+ @proxy = nil
47
+ end
48
+
49
+ def api_path=(path)
50
+ @api_path = path || @api_path
51
+ end
52
+
53
+ def user_agent=(agent)
54
+ @user_agent = agent || @user_agent
55
+ end
56
+
57
+ def extra_headers=(headers)
58
+ @extra_headers = headers || @extra_headers
59
+ end
60
+
61
+ def advanced_options=(opts)
62
+ @advanced_options = opts || @advanced_options
63
+ end
64
+
65
+ def user_agent=(agent)
66
+ @user_agent = agent || @user_agent
31
67
  end
32
68
 
33
69
  # Return the Configuration object as a hash, with symbols as keys.
@@ -37,17 +73,25 @@ module Rooftop
37
73
  end
38
74
 
39
75
  def configure_connection
40
- if @url.nil?
76
+ if @api_token.nil? || @url.nil?
41
77
  raise ArgumentError, "You need to configure Rooftop before instantiating a class with a Rooftop mixin"
42
78
  end
43
79
 
44
- @connection.setup url: @url do |c|
80
+ @connection_path = "#{@url}#{@api_path}"
81
+
82
+ @connection.setup url: @connection_path, ssl: @ssl_options, proxy: @proxy do |c|
45
83
  #Headers
46
84
  c.use Rooftop::Headers
47
85
 
86
+ # Caching
87
+ if @perform_caching
88
+ c.use Faraday::HttpCache, store: @cache_store, serializer: Marshal, logger: @cache_logger
89
+ end
90
+
48
91
  # Request
49
92
  c.use Faraday::Request::UrlEncoded
50
93
 
94
+
51
95
  # Response
52
96
  c.use Her::Middleware::DefaultParseJSON
53
97
 
@@ -57,3 +101,6 @@ module Rooftop
57
101
  end
58
102
  end
59
103
  end
104
+
105
+ #load everything after this.
106
+ require_rel '.'
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'rooftop_client/version'
4
+ require 'rooftop/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "rooftop"
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
  spec.summary = "An ActiveRecord-like interface to the Rooftop CMS JSON API"
12
12
  spec.description = "An ActiveRecord-like interface to the Rooftop CMS JSON API"
13
13
  spec.homepage = "http://www.rooftopcms.com"
14
- spec.license = "MIT"
14
+ spec.license = "GPL v3"
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0")
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
@@ -24,5 +24,6 @@ Gem::Specification.new do |spec|
24
24
  spec.add_dependency "activesupport"
25
25
  spec.add_dependency "require_all"
26
26
  spec.add_dependency "her"
27
+ spec.add_dependency "faraday-http-cache"
27
28
 
28
29
  end
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.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ed Jones
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-14 00:00:00.000000000 Z
11
+ date: 2015-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - '>='
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: faraday-http-cache
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  description: An ActiveRecord-like interface to the Rooftop CMS JSON API
84
98
  email:
85
99
  - ed@errorstudio.co.uk
@@ -93,26 +107,36 @@ files:
93
107
  - README.md
94
108
  - Rakefile
95
109
  - lib/rooftop.rb
96
- - lib/rooftop_client/base.rb
97
- - lib/rooftop_client/client.rb
98
- - lib/rooftop_client/coercions.rb
99
- - lib/rooftop_client/coercions/author_coercion.rb
100
- - lib/rooftop_client/coercions/parent_coercion.rb
101
- - lib/rooftop_client/headers.rb
102
- - lib/rooftop_client/models/author.rb
103
- - lib/rooftop_client/models/media_item.rb
104
- - lib/rooftop_client/models/menu.rb
105
- - lib/rooftop_client/models/menu_item.rb
106
- - lib/rooftop_client/models/taxonomy.rb
107
- - lib/rooftop_client/models/taxonomy_term.rb
108
- - lib/rooftop_client/page.rb
109
- - lib/rooftop_client/post.rb
110
- - lib/rooftop_client/queries/queries.rb
111
- - lib/rooftop_client/version.rb
110
+ - lib/rooftop/base.rb
111
+ - lib/rooftop/client.rb
112
+ - lib/rooftop/coercions.rb
113
+ - lib/rooftop/coercions/author_coercion.rb
114
+ - lib/rooftop/coercions/parent_coercion.rb
115
+ - lib/rooftop/content_fields/collection.rb
116
+ - lib/rooftop/content_fields/content_fields.rb
117
+ - lib/rooftop/content_fields/field.rb
118
+ - lib/rooftop/errors/record_not_found.rb
119
+ - lib/rooftop/field_aliases.rb
120
+ - lib/rooftop/headers.rb
121
+ - lib/rooftop/hook_calls.rb
122
+ - lib/rooftop/models/author.rb
123
+ - lib/rooftop/models/media_item.rb
124
+ - lib/rooftop/models/menu.rb
125
+ - lib/rooftop/models/menu_item.rb
126
+ - lib/rooftop/models/taxonomy.rb
127
+ - lib/rooftop/models/taxonomy_term.rb
128
+ - lib/rooftop/nested.rb
129
+ - lib/rooftop/page.rb
130
+ - lib/rooftop/post.rb
131
+ - lib/rooftop/queries/queries.rb
132
+ - lib/rooftop/resource_links/collection.rb
133
+ - lib/rooftop/resource_links/link.rb
134
+ - lib/rooftop/resource_links/resource_links.rb
135
+ - lib/rooftop/version.rb
112
136
  - rooftop_ruby_client.gemspec
113
137
  homepage: http://www.rooftopcms.com
114
138
  licenses:
115
- - MIT
139
+ - GPL v3
116
140
  metadata: {}
117
141
  post_install_message:
118
142
  rdoc_options: []
@@ -1,38 +0,0 @@
1
- module Rooftop
2
- module Base
3
- def self.included(base)
4
- base.include Her::Model
5
- # Coercions allow you to pass a block to do something with a returned field
6
- base.include Rooftop::Coercions
7
- # Queries mixin includes a fixup for there `where()` method
8
- base.include Rooftop::Queries
9
- # Use the API instance we have configured - in a proc because we can't control load order
10
- base.send(:use_api,->{Rooftop.configuration.connection})
11
- # WP returns an uppercase attribute for ID. Annoying.
12
- # base.send(:primary_key, :"ID")
13
- # Date and Modified fields are pretty universal in responses from WP, so we can automatically
14
- # coerce these to DateTime.
15
- base.send(:coerce_field,date: ->(date) {DateTime.parse(date)})
16
- base.send(:coerce_field,modified: ->(modified) {DateTime.parse(modified)})
17
- base.extend ClassMethods
18
- end
19
-
20
- module ClassMethods
21
- # Allow calling 'first'
22
- def first
23
- all.first
24
- end
25
- end
26
-
27
- # Utility method to make the 'created' field have a more rubyish name
28
- def created_at
29
- date
30
- end
31
-
32
- # Utility method to make the 'updated' field have a more rubyish name
33
- def updated_at
34
- modified
35
- end
36
-
37
- end
38
- end
@@ -1,8 +0,0 @@
1
- module Rooftop
2
- module AuthorCoercion
3
- def self.included(base)
4
- base.send(:after_find, ->(r) { r.author.registered = DateTime.parse(r.author.registered)})
5
- base.send(:coerce_field, {author: ->(author) { Rooftop::Author.new(author) }})
6
- end
7
- end
8
- end
@@ -1,45 +0,0 @@
1
- # Coerce any field called 'parent' which returns an ID into an actual object
2
- module Rooftop
3
- module ParentCoercion
4
- def self.included(base)
5
- base.extend ClassMethods
6
- # base.send(:after_find, ->(r) {
7
- # if r.has_parent?
8
- # r.instance_variable_set(:"parent_#{base.to_s.underscore}", resolve_parent_id())
9
- # r.class.send(:attr_reader, :"parent_#{base.to_s.underscore}")
10
- # end
11
- # })
12
- # base.send(:coerce_field, parent: ->(p) { base.send(:resolve_parent_id,p) })
13
- end
14
-
15
- module ClassMethods
16
- def add_parent_reference
17
- define_method :"parent_#{self.to_s.underscore}" do
18
- puts "hello"
19
- end
20
- end
21
- end
22
-
23
- def has_parent?
24
- respond_to?(:parent) && parent.is_a?(Fixnum) && parent != 0
25
- end
26
-
27
- def resolve_parent_id
28
- if respond_to?(:parent)
29
- if parent.is_a?(Fixnum)
30
- if parent == 0
31
- #no parent
32
- return nil
33
- else
34
- return self.class.send(:find, id)
35
- end
36
- else
37
- return parent
38
- end
39
-
40
- end
41
-
42
- end
43
- end
44
-
45
- end
@@ -1,8 +0,0 @@
1
- module Rooftop
2
- class Menu
3
- include Rooftop::Base
4
- has_many :menu_items, class: "Rooftop::MenuItem"
5
- collection_path "menus"
6
- coerce_field items: ->(items) { items.collect {|i| MenuItem.new(i)} unless items.nil?}
7
- end
8
- end
@@ -1,19 +0,0 @@
1
- module Rooftop
2
- module Page
3
- def self.included(base)
4
- base.include Rooftop::Base
5
- #TODO instead of the silly coercion, we should be able to use Her to do this
6
- # has_one :parent, data_field: :parent, class_name: "Page", path: "/pages"
7
- base.include Rooftop::ParentCoercion
8
- base.extend ClassMethods
9
- base.send(:collection_path,"pages")
10
- end
11
-
12
- module ClassMethods
13
-
14
- end
15
-
16
-
17
-
18
- end
19
- end
@@ -1,3 +0,0 @@
1
- module Rooftop
2
- VERSION = "0.0.1"
3
- end