rooftop 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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