rooftop-rails 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/app/controllers/concerns/rooftop/rails/nested_resource.rb +65 -0
- data/app/helpers/rooftop/rails/content_helper.rb +35 -0
- data/app/helpers/{rooftop_rails → rooftop}/webhooks_helper.rb +0 -0
- data/app/models/concerns/rooftop/rails/nested_model.rb +52 -0
- data/lib/rooftop/rails.rb +13 -6
- data/lib/rooftop/rails/engine.rb +12 -1
- data/lib/rooftop/rails/errors.rb +5 -0
- data/lib/rooftop/rails/route_resolver.rb +34 -0
- data/lib/rooftop/rails/version.rb +1 -1
- metadata +40 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ce7b53b614dba3b91d76917209fdd360b3074ee
|
4
|
+
data.tar.gz: 9b3034dca31a3d7011d635b46639e519ebb90a51
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7420b709d0dd54f2e485a87240a50e319806df71870d730d022d71529bf4a09407d1674fee1a29c2eb68b8cdea539d9e24c6451848533096f8d68d9985624f8e
|
7
|
+
data.tar.gz: dc72a561f64cb5e2ab552771ca5bfe61cba476117d9a39be140090cf44fb29db9b2eac4794d5750c71f12e431e7644f33037f28769a4e09f5d22fcaa4416a8e4
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Rails
|
3
|
+
# A controller mixin which can load a resource from a nested path. Useful mostly for pages.
|
4
|
+
# The mixin defines some dynamic instance methods on the controller, and a class method to define the name of the model you want to load.
|
5
|
+
module NestedResource
|
6
|
+
def self.included(base)
|
7
|
+
base.extend ClassMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
attr_reader :resource_name, :resource_class
|
12
|
+
# A class method defined on the controller which gives you an easy way to find a resource from a deeply-nested path, and optionally check that the path provided is correct.
|
13
|
+
# By adding a call to `nested_rooftop_resource` in your controller class, the following happens:
|
14
|
+
# - The resource model you identify has Rooftop::Rails::NestedModel mixed into it
|
15
|
+
# - Methods for finding a model object and validating that the path is correct are added
|
16
|
+
# For example:
|
17
|
+
# class PagesController
|
18
|
+
# include Rooftop::Rails::NestedResource
|
19
|
+
# nested_rooftop_resource :page
|
20
|
+
# before_action :find_and_validate_page, except: :index
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# Note that the methods on the controller are dynamically named according to the resource name - i.e. find_and_validate_page in this case.
|
24
|
+
# You need to set up your routes so that a single param called `nested_path` is passed to this controller for any methods you're calling `find_and_validate_page` on, for example:
|
25
|
+
# match "/*nested_path", via: [:get], to: "pages#show"
|
26
|
+
# This is a greedy route so you probably want it at the bottom.
|
27
|
+
def nested_rooftop_resource(resource)
|
28
|
+
@resource_name = resource
|
29
|
+
@resource_class = resource.to_s.classify.constantize
|
30
|
+
@resource_class.send(:include, Rooftop::Rails::NestedModel)
|
31
|
+
|
32
|
+
# Set up the dynamically-named find_[resource name]
|
33
|
+
define_method "find_#{@resource_name}" do
|
34
|
+
respond_to do |format|
|
35
|
+
format.html do
|
36
|
+
resource = self.class.resource_class.send(:find_by_nested_path, params[:nested_path])
|
37
|
+
instance_variable_set("@#{self.class.resource_name}",resource)
|
38
|
+
end
|
39
|
+
format.all do
|
40
|
+
raise ActionController::RoutingError, "Not found: #{request.original_fullpath}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
# Set up the dynamically-named validate_[resource name]
|
46
|
+
define_method "validate_#{@resource_name}" do
|
47
|
+
resource = instance_variable_get("@#{self.class.resource_name}")
|
48
|
+
if resource.nested_path != params[:nested_path]
|
49
|
+
raise Rooftop::Rails::AncestorMismatch, "The #{self.class.resource_name} you requested has a different path"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
# Set up the dynamically-named find_and_validate_[resource name]
|
53
|
+
# (this is a utility method to call the two above)
|
54
|
+
define_method "find_and_validate_#{@resource_name}" do
|
55
|
+
send(:"find_#{self.class.resource_name}")
|
56
|
+
send(:"validate_#{self.class.resource_name}")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Rails
|
3
|
+
# A mixin helper to make it easier to deal with content coming out of Rooftop.
|
4
|
+
# For example, rendering relative links in the context of your application.
|
5
|
+
module ContentHelper
|
6
|
+
|
7
|
+
# Parse content and replace links from Rooftop with links to your resources.
|
8
|
+
# We introspect your routes using Rooftop::Rails::RouteResolver, which also gives you scope for
|
9
|
+
# manually overriding something, by setting Rooftop::Rails.configuration.resource_route_mapping.
|
10
|
+
# See the readme for more info.
|
11
|
+
|
12
|
+
# @param content [String] the content you want to parse, e.g. an html field from Rooftop.
|
13
|
+
# @return [String] the HTML, parsed to point to your URL structure.
|
14
|
+
def parse_links(content)
|
15
|
+
_fragment = Nokogiri::HTML.fragment(content, 'UTF-8')
|
16
|
+
_fragment.css("a[data-rooftop-link-type]").each do |a|
|
17
|
+
# build up the slug path for the resource we're linking to
|
18
|
+
if a['data-rooftop-link-ancestor-slugs'] #we have a nested resource, we need to build up the slug path
|
19
|
+
path = a['data-rooftop-link-ancestor-slugs'].split(",").push(a['data-rooftop-link-slug'])
|
20
|
+
resource_id = path.join("/")
|
21
|
+
else
|
22
|
+
resource_id = a['data-rooftop-link-slug']
|
23
|
+
end
|
24
|
+
|
25
|
+
a['href'] = Rooftop::Rails::RouteResolver.new(a['data-rooftop-link-type'], resource_id).resolve
|
26
|
+
end
|
27
|
+
_fragment.to_html
|
28
|
+
end
|
29
|
+
|
30
|
+
def parse_content(content)
|
31
|
+
parse_links(content).html_safe
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
File without changes
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Rails
|
3
|
+
|
4
|
+
# This module adds methods for finding by a nested path of slugs, and generating a
|
5
|
+
# nested path of slugs
|
6
|
+
module NestedModel
|
7
|
+
|
8
|
+
def self.included(base)
|
9
|
+
base.extend ClassMethods
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
# Get a model from a nested path. Assumes `slug` is the field you'll be finding by.
|
14
|
+
# Accepts options for the path delimiter and whether you want to unescape url strings
|
15
|
+
|
16
|
+
# @param path [String] the path - the last of which will be the thing we find
|
17
|
+
# @param opts [Hash] options - path delimiter and unescape
|
18
|
+
# @return object [Object] an instance of the class this is mixed into
|
19
|
+
def find_by_nested_path(path, opts = {})
|
20
|
+
options = {delimiter: '/', unescape: false}
|
21
|
+
options.merge!(opts)
|
22
|
+
path = CGI::unescape(path) if options[:unescape]
|
23
|
+
delimiter = options[:delimiter]
|
24
|
+
slug = "#{options[:prefix]}#{path}".gsub(/^\//, '').split(delimiter).last
|
25
|
+
entity = where(slug: slug).first
|
26
|
+
if entity.nil?
|
27
|
+
raise Rooftop::RecordNotFoundError, "Couldn't find #{self} with slug #{slug}"
|
28
|
+
else
|
29
|
+
return entity
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Given a field (and optional delimiter), return a path to the current object.
|
35
|
+
# e.g. you'd end up with /path/to/page (where this object is 'page')
|
36
|
+
# @param [Symbol] the field to use to create the path
|
37
|
+
# @param [String] the delimiter to use. Defaults to "/"
|
38
|
+
# @return [String] the path as a string
|
39
|
+
def nested_path(opts = {})
|
40
|
+
options = {delimiter: "/", prefix: ""}
|
41
|
+
options.merge!(opts)
|
42
|
+
delimiter = options[:delimiter]
|
43
|
+
prefix = options[:prefix].empty? ? "" : "#{options[:prefix]}#{delimiter}"
|
44
|
+
path = ([slug] + ancestors.collect(&:slug)).reverse.join(delimiter).gsub(prefix,"")
|
45
|
+
return path
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
|
data/lib/rooftop/rails.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
require 'rooftop'
|
2
|
-
|
3
|
-
|
4
|
-
require "rooftop/rails/development_constraint"
|
5
|
-
require "rooftop/rails/preview"
|
2
|
+
require 'require_all'
|
3
|
+
require_rel '.'
|
6
4
|
|
7
5
|
module Rooftop
|
8
6
|
module Rails
|
@@ -25,15 +23,24 @@ module Rooftop
|
|
25
23
|
:authenticate_webhooks,
|
26
24
|
:webhooks_username,
|
27
25
|
:webhooks_password,
|
28
|
-
:perform_caching,
|
29
26
|
:preview_username,
|
30
27
|
:preview_password,
|
31
28
|
:preview_domain,
|
32
|
-
:enable_preview_domain
|
29
|
+
:enable_preview_domain,
|
30
|
+
:perform_caching,
|
31
|
+
:cache_store,
|
32
|
+
:cache_logger,
|
33
|
+
:ssl_options,
|
34
|
+
:proxy,
|
35
|
+
:resource_route_map
|
33
36
|
|
34
37
|
def initialize
|
35
38
|
@authenticate_webhooks = true
|
36
39
|
@perform_caching = ::Rails.configuration.action_controller.perform_caching
|
40
|
+
@cache_store = ::Rails.cache
|
41
|
+
@cache_logger = ::Rails.logger
|
42
|
+
@ssl_options = {}
|
43
|
+
@resource_route_map = {}
|
37
44
|
end
|
38
45
|
end
|
39
46
|
end
|
data/lib/rooftop/rails/engine.rb
CHANGED
@@ -17,7 +17,12 @@ module Rooftop
|
|
17
17
|
config.extra_headers = Rooftop::Rails.configuration.extra_headers
|
18
18
|
config.advanced_options = Rooftop::Rails.configuration.advanced_options
|
19
19
|
config.api_path = Rooftop::Rails.configuration.api_path
|
20
|
-
config.url = Rooftop::Rails.configuration.url || "
|
20
|
+
config.url = Rooftop::Rails.configuration.url || "https://#{config.site_name}.rooftopcms.io"
|
21
|
+
config.perform_caching = Rooftop::Rails.configuration.perform_caching
|
22
|
+
config.cache_store = Rooftop::Rails.configuration.cache_store
|
23
|
+
config.cache_logger = Rooftop::Rails.configuration.cache_logger
|
24
|
+
config.ssl_options = Rooftop::Rails.configuration.ssl_options
|
25
|
+
config.proxy = Rooftop::Rails.configuration.proxy
|
21
26
|
end
|
22
27
|
end
|
23
28
|
|
@@ -26,6 +31,12 @@ module Rooftop
|
|
26
31
|
include Rooftop::Rails::Preview
|
27
32
|
end
|
28
33
|
end
|
34
|
+
|
35
|
+
initializer "add_helpers" do
|
36
|
+
ActiveSupport.on_load(:action_view) do
|
37
|
+
include Rooftop::Rails::ContentHelper
|
38
|
+
end
|
39
|
+
end
|
29
40
|
end
|
30
41
|
end
|
31
42
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Rooftop
|
2
|
+
module Rails
|
3
|
+
# A class to generate a proper rails route for Rooftop resources.
|
4
|
+
#
|
5
|
+
# You can configure a custom route in Rooftop::Rails::Configuration.resource_route_map. If you don't,
|
6
|
+
# this class will introspect the Rails routes to try and guess. Otherwise it'll return nothing.
|
7
|
+
class RouteResolver
|
8
|
+
# Create the route resolver, with a type (post, page, whatever) and an optional ID
|
9
|
+
attr_accessor :type, :id
|
10
|
+
def initialize(type, id=nil)
|
11
|
+
@type = type.to_sym
|
12
|
+
@id = id
|
13
|
+
end
|
14
|
+
|
15
|
+
def resolve
|
16
|
+
route_config = Rooftop::Rails.configuration.resource_route_map
|
17
|
+
resource_key = @id.nil? ? @type.to_s.pluralize.to_sym : @type
|
18
|
+
if route_config[resource_key]
|
19
|
+
return route_config[resource_key].try(:call,@id)
|
20
|
+
else
|
21
|
+
begin
|
22
|
+
route_info = ::Rails.application.routes.named_routes[resource_key].defaults
|
23
|
+
route_info.reverse_merge!(id: @id) unless @id.nil?
|
24
|
+
::Rails.application.routes.url_helpers.url_for(route_info.merge(only_path: true))
|
25
|
+
rescue
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rooftop-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Error Studio
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: require_all
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: rails
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -24,20 +38,34 @@ dependencies:
|
|
24
38
|
- - ~>
|
25
39
|
- !ruby/object:Gem::Version
|
26
40
|
version: '4.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: nokogiri
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.6'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.6'
|
27
55
|
- !ruby/object:Gem::Dependency
|
28
56
|
name: rooftop
|
29
57
|
requirement: !ruby/object:Gem::Requirement
|
30
58
|
requirements:
|
31
|
-
- - '
|
59
|
+
- - '='
|
32
60
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
61
|
+
version: 0.0.5
|
34
62
|
type: :runtime
|
35
63
|
prerelease: false
|
36
64
|
version_requirements: !ruby/object:Gem::Requirement
|
37
65
|
requirements:
|
38
|
-
- - '
|
66
|
+
- - '='
|
39
67
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
68
|
+
version: 0.0.5
|
41
69
|
description: This gem provides utility methods and a mountable engine for Rails applications
|
42
70
|
using the Rooftop gem
|
43
71
|
email:
|
@@ -47,13 +75,18 @@ extensions: []
|
|
47
75
|
extra_rdoc_files: []
|
48
76
|
files:
|
49
77
|
- Rakefile
|
78
|
+
- app/controllers/concerns/rooftop/rails/nested_resource.rb
|
50
79
|
- app/controllers/rooftop_rails/webhooks_controller.rb
|
51
|
-
- app/helpers/
|
80
|
+
- app/helpers/rooftop/rails/content_helper.rb
|
81
|
+
- app/helpers/rooftop/webhooks_helper.rb
|
82
|
+
- app/models/concerns/rooftop/rails/nested_model.rb
|
52
83
|
- config/routes.rb
|
53
84
|
- lib/rooftop/rails.rb
|
54
85
|
- lib/rooftop/rails/development_constraint.rb
|
55
86
|
- lib/rooftop/rails/engine.rb
|
87
|
+
- lib/rooftop/rails/errors.rb
|
56
88
|
- lib/rooftop/rails/preview.rb
|
89
|
+
- lib/rooftop/rails/route_resolver.rb
|
57
90
|
- lib/rooftop/rails/version.rb
|
58
91
|
- test/controllers/rooftop_rails/webhooks_controller_test.rb
|
59
92
|
- test/dummy/README.rdoc
|