xing-backend 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/deprecated_classes.rb +28 -0
- data/lib/xing/controllers/base.rb +40 -0
- data/lib/xing/controllers/root_resources_controller.rb +12 -0
- data/lib/xing/engine.rb +27 -0
- data/lib/xing/mappers/base.rb +135 -0
- data/lib/xing/mappers.rb +6 -0
- data/lib/xing/serializers/base.rb +50 -0
- data/lib/xing/serializers/root_resources.rb +9 -0
- data/lib/xing/serializers.rb +7 -0
- data/lib/xing/services/error_converter.rb +47 -0
- data/lib/xing/services/json_tree_lister.rb +56 -0
- data/lib/xing/services/snapshot_fetcher.rb +33 -0
- data/lib/xing/services/snapshot_writer.rb +19 -0
- data/lib/xing/services.rb +9 -0
- data/lib/xing-backend.rb +34 -0
- data/spec/deprecated_classes/active_model_error_converter_spec.rb +11 -0
- data/spec/deprecated_classes/base_serializer_spec.rb +11 -0
- data/spec/deprecated_classes/hypermedia_json_mapper_spec.rb +11 -0
- data/spec/deprecated_classes/json_tree_lister_spec.rb +14 -0
- data/spec/deprecated_classes/remote_snapshot_fetcher_spec.rb +8 -0
- data/spec/deprecated_classes/resources_serializer_spec.rb +12 -0
- data/spec/xing/controllers/base_spec.rb +7 -0
- data/spec/xing/controllers/root_resources_controller_spec.rb +8 -0
- data/spec/xing/mappers/base_spec.rb +56 -0
- data/spec/xing/serializers/base_spec.rb +32 -0
- data/spec/xing/serializers/root_resources_spec.rb +20 -0
- data/spec/xing/services/error_converter_spec.rb +61 -0
- data/spec/xing/services/json_tree_lister_spec.rb +109 -0
- data/spec/xing/services/snapshot_fetcher_spec.rb +75 -0
- data/spec/xing_spec.rb +7 -0
- data/spec_help/dummy/README.rdoc +28 -0
- data/spec_help/dummy/Rakefile +6 -0
- data/spec_help/dummy/app/assets/javascripts/application.js +13 -0
- data/spec_help/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec_help/dummy/app/controllers/application_controller.rb +5 -0
- data/spec_help/dummy/app/helpers/application_helper.rb +2 -0
- data/spec_help/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec_help/dummy/bin/bundle +3 -0
- data/spec_help/dummy/bin/rails +4 -0
- data/spec_help/dummy/bin/rake +4 -0
- data/spec_help/dummy/bin/setup +29 -0
- data/spec_help/dummy/config/application.rb +25 -0
- data/spec_help/dummy/config/boot.rb +5 -0
- data/spec_help/dummy/config/database.yml +25 -0
- data/spec_help/dummy/config/environment.rb +5 -0
- data/spec_help/dummy/config/environments/development.rb +41 -0
- data/spec_help/dummy/config/environments/production.rb +79 -0
- data/spec_help/dummy/config/environments/test.rb +42 -0
- data/spec_help/dummy/config/initializers/assets.rb +11 -0
- data/spec_help/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec_help/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec_help/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec_help/dummy/config/initializers/inflections.rb +16 -0
- data/spec_help/dummy/config/initializers/mime_types.rb +4 -0
- data/spec_help/dummy/config/initializers/session_store.rb +3 -0
- data/spec_help/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec_help/dummy/config/locales/en.yml +23 -0
- data/spec_help/dummy/config/routes.rb +56 -0
- data/spec_help/dummy/config/secrets.yml +22 -0
- data/spec_help/dummy/config.ru +4 -0
- data/spec_help/dummy/db/test.sqlite3 +0 -0
- data/spec_help/dummy/log/test.log +48 -0
- data/spec_help/dummy/public/404.html +67 -0
- data/spec_help/dummy/public/422.html +67 -0
- data/spec_help/dummy/public/500.html +66 -0
- data/spec_help/dummy/public/favicon.ico +0 -0
- data/spec_help/spec_helper.rb +29 -0
- metadata +222 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 81e5fbc0eab9a8177181d26d407b447a7bde5e78
|
4
|
+
data.tar.gz: 5e55cf12697cab2d64f021c4e918643382867212
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ae67633934b7e3b807aca8f178895a52d1751188b04c4cebfd051abf5076280eb9c9063ab612cc8c12137bf70c02ebb64bd4999339c1451d953f9a932c0a6316
|
7
|
+
data.tar.gz: 0ea48e465a1e35135b46c093161ddd836c8117b3568a2765cb223044f9a53a3dfb745d4d12306fc6b9a320c7c6c5ae4def2ca7d32d68b8c4bef478b03a5219a6
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'xing-backend'
|
2
|
+
require 'active_support/deprecation'
|
3
|
+
|
4
|
+
module Xing
|
5
|
+
DEPRECATED_CLASSES = {
|
6
|
+
:HypermediaJSONMapper => Xing::Mappers::Base,
|
7
|
+
:BaseSerializer => Xing::Serializers::Base,
|
8
|
+
:ResourcesSerializer => Xing::Serializers::RootResources,
|
9
|
+
:JsonTreeLister => Xing::Services::JsonTreeLister,
|
10
|
+
:ActiveModelErrorConverter => Xing::Services::ErrorConverter,
|
11
|
+
:RemoteSnapshotFetcher => Xing::Services::SnapshotFetcher
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
#Xing::DEPRECATED_CLASSES.each do |old, new|
|
16
|
+
|
17
|
+
## with great power comes great responsibility
|
18
|
+
#Object.const_set(old, ActiveSupport::Deprecation::DeprecatedConstantProxy.new(old, new))
|
19
|
+
#end
|
20
|
+
|
21
|
+
def Object.const_missing(name)
|
22
|
+
if (klass = ::Xing::DEPRECATED_CLASSES[name.to_sym])
|
23
|
+
warn "[DEPRECATION] #{name} is deprecated. Please use #{klass.to_s} instead."
|
24
|
+
klass
|
25
|
+
else
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'devise_token_auth'
|
2
|
+
|
3
|
+
module Xing
|
4
|
+
module Controllers
|
5
|
+
class Base < ActionController::Base
|
6
|
+
include DeviseTokenAuth::Concerns::SetUserByToken
|
7
|
+
|
8
|
+
respond_to :json
|
9
|
+
|
10
|
+
protect_from_forgery
|
11
|
+
before_filter :check_format
|
12
|
+
|
13
|
+
def check_format
|
14
|
+
if request.subdomains.include? Xing.backend_subdomain
|
15
|
+
if request.headers["Accept"] =~ /json/
|
16
|
+
params[:format] = :json
|
17
|
+
else
|
18
|
+
render :nothing => true, :status => 406
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def json_body
|
24
|
+
@json_body ||= request.body.read
|
25
|
+
end
|
26
|
+
|
27
|
+
def parse_json
|
28
|
+
@parsed_json ||= JSON.parse(json_body)
|
29
|
+
end
|
30
|
+
|
31
|
+
def failed_to_process(error_document)
|
32
|
+
render :status => 422, :json => error_document
|
33
|
+
end
|
34
|
+
|
35
|
+
def successful_create(new_resource_path)
|
36
|
+
render :status => 201, :json => {}, :location => new_resource_path
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rails/rfc6570'
|
2
|
+
|
3
|
+
module Xing
|
4
|
+
module Controllers
|
5
|
+
class RootResourcesController < ::Xing::Controllers::Base
|
6
|
+
def index
|
7
|
+
@resources = rfc6570_routes(ignore: %w(format), path_only: true)
|
8
|
+
render :json => Xing::Serializers::RootResources.new(@resources)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/xing/engine.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Xing
|
2
|
+
|
3
|
+
class Engine < ::Rails::Engine
|
4
|
+
isolate_namespace Xing
|
5
|
+
|
6
|
+
config.autoload_paths += Dir[File.join(__FILE__, '../controllers/**/')]
|
7
|
+
|
8
|
+
config.generators do |g|
|
9
|
+
g.test_framework :rspec
|
10
|
+
end
|
11
|
+
|
12
|
+
# The ErrorConverter leverages (abuses?) the I18n mechanism to translate
|
13
|
+
# ActiveModel validation errors into Xing JSON resource errors. Here we
|
14
|
+
# need to make sure the locales file for language 'json' is loaded for
|
15
|
+
# I18n.
|
16
|
+
initializer 'xing errors locales path' do
|
17
|
+
I18n.load_path += Dir[File.join(File.dirname(__FILE__), '..', 'config', 'locales', '*.{rb,yml}')]
|
18
|
+
end
|
19
|
+
|
20
|
+
# Set the backend subdomain if it hasn't been configured by the user.
|
21
|
+
initializer 'set subdomain' do
|
22
|
+
Xing.configure do |xng_config|
|
23
|
+
xng_config.backend_subdomain ||= 'api'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
# This code is only used in the context of Rails apps, and depends pretty
|
2
|
+
# heavily on rails core extensions, so we are requiring them here.
|
3
|
+
require 'active_support'
|
4
|
+
require 'active_support/core_ext'
|
5
|
+
|
6
|
+
module Xing
|
7
|
+
module Mappers
|
8
|
+
class Base
|
9
|
+
class MissingLinkException < Exception; end
|
10
|
+
|
11
|
+
# Subclasses must define:
|
12
|
+
# aliases -- for self.record
|
13
|
+
# record_class -- if the mapper maps to an AR object
|
14
|
+
#
|
15
|
+
# Subclasses should usually define:
|
16
|
+
# assign_values -- move values from JSON into the mapped AR record
|
17
|
+
#
|
18
|
+
# Subclasses may also want to define:
|
19
|
+
# find_existing_record -- for locating the underlying AR record
|
20
|
+
# build_new_record -- for for instantiating a new underlying AR record
|
21
|
+
# map_nested_models
|
22
|
+
# build_errors -- if simply copying AR errors is insufficient
|
23
|
+
# save -- if they need to save more than 1 AR record
|
24
|
+
|
25
|
+
# When updating records, pass the locator (e.g. DB id, url_slug, or other
|
26
|
+
# unique resource extracted from the resource path) as the second argument.
|
27
|
+
def initialize(json, locator = nil)
|
28
|
+
@source_json = json
|
29
|
+
if @source_json.is_a? String
|
30
|
+
@source_hash = JSON.parse(json).with_indifferent_access
|
31
|
+
else
|
32
|
+
@source_hash = @source_json
|
33
|
+
end
|
34
|
+
@locator = locator
|
35
|
+
end
|
36
|
+
attr_accessor :locator, :error_data
|
37
|
+
attr_writer :record
|
38
|
+
|
39
|
+
def router
|
40
|
+
Rails.application.routes
|
41
|
+
end
|
42
|
+
|
43
|
+
def normalize_path(path)
|
44
|
+
path = "/#{path}"
|
45
|
+
path.squeeze!('/')
|
46
|
+
path.sub!(%r{/+\Z}, '')
|
47
|
+
path.gsub!(/(%[a-f0-9]{2})/) { $1.upcase }
|
48
|
+
path = '/' if path == ''
|
49
|
+
path
|
50
|
+
end
|
51
|
+
|
52
|
+
# This helper is used to deconstruct a URL for the purpose of extracting
|
53
|
+
# components. For example, menu_item_mapper uses it to extract the url_slug
|
54
|
+
# component of a page route. We are here abusing recognize_path, which isn't
|
55
|
+
# supposed to be used outside of tests (see
|
56
|
+
# https://github.com/rails/rails/issues/2656), but we don't know what the
|
57
|
+
# alternative is.
|
58
|
+
def route_to(path)
|
59
|
+
path = "http://#{BACKEND_SUBDOMAIN}.example.com#{normalize_path(path)}";
|
60
|
+
router.recognize_path(path)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Default save - subclasses might override
|
64
|
+
def save
|
65
|
+
perform_mapping
|
66
|
+
unless self.errors[:data].present?
|
67
|
+
self.record.save
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Default for finding an existing record - override this *or* define
|
72
|
+
# #record_class (e.g. `return Page`
|
73
|
+
def find_existing_record
|
74
|
+
@record = record_class.find(@locator)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Default for building a new record - override this *or* define #record_class
|
78
|
+
# (e.g. `return Page`
|
79
|
+
def build_new_record
|
80
|
+
@record = record_class.new
|
81
|
+
end
|
82
|
+
|
83
|
+
def perform_mapping
|
84
|
+
data = unwrap_data(@source_hash)
|
85
|
+
self.error_data = Hash.new { |hash, key| hash[key] = {} }
|
86
|
+
|
87
|
+
assign_values(data)
|
88
|
+
map_nested_models
|
89
|
+
build_errors
|
90
|
+
end
|
91
|
+
|
92
|
+
def unwrap_data(hash)
|
93
|
+
hash['data'].with_indifferent_access
|
94
|
+
end
|
95
|
+
|
96
|
+
def wrap_data(hash)
|
97
|
+
{
|
98
|
+
data: hash
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
def record
|
103
|
+
@record ||= if !locator.nil?
|
104
|
+
find_existing_record
|
105
|
+
else
|
106
|
+
build_new_record
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def assign_values(data_hash)
|
111
|
+
# Override in subclasses to assign needed values here
|
112
|
+
record # force loading or creation of the underlying DB record
|
113
|
+
update_record
|
114
|
+
end
|
115
|
+
|
116
|
+
# Do nothing if there are no nested models
|
117
|
+
# Override this method in subclass if necessary
|
118
|
+
def map_nested_models
|
119
|
+
end
|
120
|
+
|
121
|
+
def build_errors
|
122
|
+
self.add_ar_arrors(self.record)
|
123
|
+
end
|
124
|
+
|
125
|
+
def errors
|
126
|
+
wrap_data(error_data)
|
127
|
+
end
|
128
|
+
|
129
|
+
def add_ar_arrors(object)
|
130
|
+
object_errors = ActiveModelErrorConverter.new(object).convert
|
131
|
+
error_data.deep_merge!(object_errors)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
data/lib/xing/mappers.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rails'
|
2
|
+
require 'active_model_serializers'
|
3
|
+
|
4
|
+
module Xing
|
5
|
+
module Serializers
|
6
|
+
|
7
|
+
# The base class for all Xing serializers that produce
|
8
|
+
# Xing Hypermedia JSON resources. In general, subclasses
|
9
|
+
# of Xing::Serializers::Base should:
|
10
|
+
#
|
11
|
+
# * Define a links method that returns a hash of hypermedia links to
|
12
|
+
# related resources
|
13
|
+
#
|
14
|
+
# * Specify the attributes (via the ActiveModel::Serializers 'attributes'
|
15
|
+
# class method) that will be copied into the data: block
|
16
|
+
# of the generated resource.
|
17
|
+
#
|
18
|
+
# * Define methods for any attributes that do not exist as plain attributes
|
19
|
+
# in the ActiveModel being serialized. Note that this may (and often will) include
|
20
|
+
# calling other serializers on related resources or other data, in order to
|
21
|
+
# generate embedded resources.
|
22
|
+
#
|
23
|
+
# Xing serializers descend from ActiveModel::Serializer and are typically
|
24
|
+
# instantiated with an instance of an ActiveModel model in the usual way.
|
25
|
+
#
|
26
|
+
class Base < ActiveModel::Serializer
|
27
|
+
|
28
|
+
def routes
|
29
|
+
Rails.application.routes.url_helpers
|
30
|
+
end
|
31
|
+
|
32
|
+
def root
|
33
|
+
false
|
34
|
+
end
|
35
|
+
|
36
|
+
def as_json_with_wrap(options={})
|
37
|
+
{
|
38
|
+
:links => links,
|
39
|
+
:data => as_json_without_wrap
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def links
|
44
|
+
{}
|
45
|
+
end
|
46
|
+
|
47
|
+
alias_method_chain :as_json, :wrap
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Xing
|
2
|
+
module Services
|
3
|
+
class ErrorConverter
|
4
|
+
|
5
|
+
|
6
|
+
def initialize(am_object)
|
7
|
+
@am_object = am_object
|
8
|
+
end
|
9
|
+
attr_reader :am_object
|
10
|
+
|
11
|
+
# This is a terrible hack to preserve the semantic meaning of
|
12
|
+
# different error types -- neccesary because ActiveModel::Errors
|
13
|
+
# frustratingly translates semantic error messages through i18n
|
14
|
+
# as soon as it gets them
|
15
|
+
def json_errors
|
16
|
+
@json_errors ||= begin
|
17
|
+
old_locale = I18n.locale
|
18
|
+
I18n.locale = "json"
|
19
|
+
am_object.valid?
|
20
|
+
error_hash = am_object.errors.to_hash.deep_dup
|
21
|
+
I18n.locale = old_locale
|
22
|
+
error_hash
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def regular_errors
|
27
|
+
@regular_errors ||= begin
|
28
|
+
am_object.valid?
|
29
|
+
am_object.errors.to_hash.deep_dup
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def convert
|
34
|
+
final_errors = {}
|
35
|
+
json_errors.each_key do |key|
|
36
|
+
final_errors[key] = {
|
37
|
+
:type => json_errors[key][0],
|
38
|
+
:message => regular_errors[key][0]
|
39
|
+
}
|
40
|
+
end
|
41
|
+
final_errors
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'active_model_serializers'
|
2
|
+
require 'active_support/core_ext'
|
3
|
+
|
4
|
+
module Xing
|
5
|
+
module Services
|
6
|
+
class JsonTreeLister
|
7
|
+
|
8
|
+
class TreeNode
|
9
|
+
include ActiveModel::SerializerSupport
|
10
|
+
|
11
|
+
def initialize(node, children)
|
12
|
+
@node = node
|
13
|
+
@children = children
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :node, :children
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(nodes, node_serializer)
|
20
|
+
@nodes = nodes
|
21
|
+
@node_serializer = node_serializer
|
22
|
+
@stack = [[]]
|
23
|
+
@path = []
|
24
|
+
end
|
25
|
+
|
26
|
+
def render_node(node, children)
|
27
|
+
@node_serializer.new(TreeNode.new(node, children)).as_json
|
28
|
+
end
|
29
|
+
|
30
|
+
def pop_level
|
31
|
+
children = @stack.pop
|
32
|
+
@stack.last << render_node(@path.pop, children)
|
33
|
+
end
|
34
|
+
|
35
|
+
def render
|
36
|
+
(@nodes + [nil]).each_cons(2) do |this, after|
|
37
|
+
until @path.empty? or @path.last.is_ancestor_of?(this)
|
38
|
+
pop_level
|
39
|
+
end
|
40
|
+
if after.nil? or !this.is_ancestor_of?(after)
|
41
|
+
@stack.last << render_node(this, [])
|
42
|
+
else
|
43
|
+
@path << this
|
44
|
+
@stack << []
|
45
|
+
end
|
46
|
+
end
|
47
|
+
until @path.empty?
|
48
|
+
pop_level
|
49
|
+
end
|
50
|
+
return @stack.last.first
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'typhoeus'
|
2
|
+
require 'addressable/uri'
|
3
|
+
require 'xing/services/snapshot_writer'
|
4
|
+
require 'sidekiq/worker'
|
5
|
+
|
6
|
+
module Xing::Services
|
7
|
+
class SnapshotFetcher
|
8
|
+
include Sidekiq::Worker
|
9
|
+
include SnapshotWriter
|
10
|
+
|
11
|
+
def perform(url, path)
|
12
|
+
admin_server = Rails.application.secrets.snapshot_server['url']
|
13
|
+
user_password = "#{Rails.application.secrets.snapshot_server['user']}:#{Rails.application.secrets.snapshot_server['password']}"
|
14
|
+
snapshot_url = Addressable::URI.join(url,path).to_s
|
15
|
+
request = Typhoeus::Request.new(admin_server, userpwd: user_password, params: { url: snapshot_url })
|
16
|
+
|
17
|
+
hydra = Typhoeus::Hydra.new
|
18
|
+
hydra.queue(request)
|
19
|
+
hydra.run
|
20
|
+
|
21
|
+
response = request.response
|
22
|
+
|
23
|
+
if response.success?
|
24
|
+
html = response.body
|
25
|
+
write(path, html)
|
26
|
+
else
|
27
|
+
logger.warn response.status_message
|
28
|
+
logger.warn response.body
|
29
|
+
raise "Query to #{admin_server} for #{path} failed!"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Xing::Services
|
2
|
+
module SnapshotWriter
|
3
|
+
def write(path, html)
|
4
|
+
if Rails.env.test?
|
5
|
+
snapshot_file = "#{ Rails.root }/spec/fixtures/sitemap_scratch/#{path.present? ? path : 'index'}.html"
|
6
|
+
else
|
7
|
+
snapshot_file = "#{ Rails.root }/public/frontend_snapshots/#{path.present? ? path : 'index'}.html"
|
8
|
+
end
|
9
|
+
dirname = File.dirname(snapshot_file)
|
10
|
+
unless File.directory?(dirname)
|
11
|
+
FileUtils.mkdir_p(dirname)
|
12
|
+
end
|
13
|
+
|
14
|
+
File.open(snapshot_file, "w+:ASCII-8BIT:UTF-8") do |f|
|
15
|
+
f.write(html)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/xing-backend.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rails'
|
2
|
+
require 'xing_backend_token_auth'
|
3
|
+
require 'rails/rfc6570'
|
4
|
+
require 'sidekiq'
|
5
|
+
|
6
|
+
module Xing
|
7
|
+
mattr_accessor :backend_subdomain
|
8
|
+
|
9
|
+
# Configure xing via pattern similar to Rails:
|
10
|
+
#
|
11
|
+
# Xing.configure do |config|
|
12
|
+
# config.setting = 'value'
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# Supported settings right now are:
|
16
|
+
# * backend_subdomain (default: 'api')
|
17
|
+
def self.configure(&block)
|
18
|
+
yield self
|
19
|
+
end
|
20
|
+
|
21
|
+
module Controllers
|
22
|
+
autoload :Base, 'xing/controllers/base'
|
23
|
+
|
24
|
+
# NOTE: The rails router expects the the controller to have "Controller" as
|
25
|
+
# the suffix of the name, or it complains.
|
26
|
+
autoload :RootResourcesController, 'xing/controllers/root_resources_controller'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
require 'xing/mappers'
|
31
|
+
require 'xing/engine'
|
32
|
+
require 'xing/serializers'
|
33
|
+
require 'xing/services'
|
34
|
+
require 'deprecated_classes'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'deprecated_classes'
|
2
|
+
|
3
|
+
describe ActiveModelErrorConverter, :type => :deprecation do
|
4
|
+
let :resource do
|
5
|
+
double('resource')
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should be the correct class" do
|
9
|
+
expect(ActiveModelErrorConverter.new(resource)).to be_a(Xing::Services::ErrorConverter)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'deprecated_classes'
|
2
|
+
|
3
|
+
describe JsonTreeLister, :type => :deprecation do
|
4
|
+
let :models do
|
5
|
+
double('models')
|
6
|
+
end
|
7
|
+
let :serializer do
|
8
|
+
double('serializer')
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should be the correct class" do
|
12
|
+
expect(JsonTreeLister.new(models, serializer)).to be_a(Xing::Services::JsonTreeLister)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
|
2
|
+
require 'deprecated_classes'
|
3
|
+
|
4
|
+
describe ResourcesSerializer do
|
5
|
+
let :resource do
|
6
|
+
double('hash_of_links')
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should be the correct class" do
|
10
|
+
expect(ResourcesSerializer.new(resource)).to be_a(Xing::Serializers::RootResources)
|
11
|
+
end
|
12
|
+
end
|