llt-core 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 99ad6c4858497e80179b2537f7e945f41972b79e
4
+ data.tar.gz: 6647133228668feb869b4c846525d2345e5da2e9
5
+ SHA512:
6
+ metadata.gz: 920a2015f453e256c3769381852df4329eba586b1aa3f16c3fb725fde00d58db48964154b4cb07c41ee2167bf077a27e6bbce30eba02a6b41a30fed28df6b9cd
7
+ data.tar.gz: b1787c797c2af8da0e8e1d1311304cd2a6369d7679cde3c8d3bb0100317ed34bb4200e4a704d1b47d850edc2435439a8c8d110bf8b19d592c534ae32984ebd6e
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --tty
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ before_script:
3
+ - "export JRUBY_OPTS=--2.0"
4
+ rvm:
5
+ - 2.1.0
6
+ - 2.0.0
7
+ - jruby-20mode
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'coveralls', require: false
4
+
5
+ # Specify your gem's dependencies in llt-core.gemspec
6
+ gemspec
7
+
8
+ platform :jruby do
9
+ gem 'jruby-httpclient'
10
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 LFDM
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # LLT::Core
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'llt-core'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install llt-core
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,95 @@
1
+ require 'cgi'
2
+
3
+ module LLT
4
+ module Core
5
+ module Api
6
+ module Helpers
7
+ def uu(text)
8
+ CGI.unescape(text)
9
+ end
10
+
11
+ def u(text)
12
+ CGI.escape(text)
13
+ end
14
+
15
+ # tries to resolve an uri or a text included in the params
16
+ def extract_text(params)
17
+ if uri = params[:uri]
18
+ get_from_uri(uri)
19
+ else
20
+ params[:text]
21
+ end
22
+ end
23
+
24
+ def extract_markup_params(params)
25
+ mu_params = %i{ recursive indexing inline }
26
+ extracted = [params[:tags]]
27
+ relevant = mu_params.each_with_object({}) do |param, h|
28
+ val = params[param]
29
+ val = params[param.to_s] if val.nil?
30
+ h[param] = val unless val.nil?
31
+ end
32
+ extracted << relevant
33
+ end
34
+
35
+ def to_xml(elements, params = {})
36
+ root = params[:root] || 'doc'
37
+ root_close = root.match(/^\w+/)[0]
38
+ tags, options = *extract_markup_params(params)
39
+ body = elements.each_with_object('') do |e, str|
40
+ # need to clone, otherwise the tags will get eaten
41
+ # up in the markup method, but we cannot if tags
42
+ # is nil
43
+ cloned_tags = (tags ? tags.clone : tags)
44
+ # Options need to be cloned as well! Time for another
45
+ # jruby issue: The keywords seem to be eaten up somewhere
46
+ # along the road. Need to investigate further.
47
+ str << e.to_xml(cloned_tags, options.clone)
48
+ end
49
+ "#{XML_DECLARATION}<#{root}>#{body}</#{root_close}>"
50
+ end
51
+
52
+ def typecast_params!(params)
53
+ params.each do |k, v|
54
+ params[k] = typecast(v)
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ XML_DECLARATION = %{<?xml version="1.0" encoding="UTF-8"?>}
61
+
62
+ def typecast(val)
63
+ if val.kind_of?(Array)
64
+ val.map { |e| typecast(e) }
65
+ else
66
+ case val
67
+ when 'true' then true
68
+ when 'false' then false
69
+ when 'nil' then nil
70
+ else val
71
+ end
72
+ end
73
+ end
74
+
75
+ # Net::Http.get is broken in jruby when running in
76
+ # 2.0 mode - we need to use some different when going
77
+ # the java route.
78
+ if RUBY_PLATFORM == 'java'
79
+ require 'http_client'
80
+ HTTP_CLIENT = HTTP::Client.new
81
+
82
+ def get_from_uri(uri)
83
+ HTTP_CLIENT.get(uri)
84
+ end
85
+ else
86
+ require 'open-uri'
87
+
88
+ def get_from_uri(uri)
89
+ URI(uri).read
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1 @@
1
+ require 'llt/core/api/helpers'
@@ -0,0 +1,138 @@
1
+ module LLT
2
+ module Core
3
+ module Containable
4
+ include Enumerable
5
+
6
+ attr_reader :container, :id
7
+ alias_method :n, :id
8
+
9
+ def initialize(string, id = nil)
10
+ @string = string
11
+ @container = []
12
+ @id = id
13
+ end
14
+
15
+ def <<(obj)
16
+ @container << obj
17
+ @container.flatten!
18
+ end
19
+
20
+ def [](arg)
21
+ @container[arg]
22
+ end
23
+
24
+ def to_s
25
+ @string
26
+ end
27
+
28
+ def to_xml(tags = nil, indexing: true,
29
+ recursive: true,
30
+ inline: false,
31
+ attrs: {})
32
+
33
+ # for easier recursion it's solved in a way that might
34
+ # look awkward on first sight
35
+ tags = Array(tags)
36
+ tag = tags.shift || default_xml_tag
37
+ end_of_recursion = false
38
+
39
+ val = if recursive && all? { |e| e.respond_to?(:to_xml)}
40
+ attrs.merge!(inline_id(tag)) if inline && indexing
41
+ recursive_xml(tags, indexing, inline, attrs)
42
+ else
43
+ end_of_recursion = true
44
+ as_xml
45
+ end
46
+
47
+ if inline
48
+ end_of_recursion ? wrap_with_xml(tag, val, indexing, attrs) : val
49
+ else
50
+ wrap_with_xml(tag, val, indexing, attrs)
51
+ end
52
+ end
53
+
54
+ def as_xml
55
+ @string
56
+ end
57
+
58
+ def as_json
59
+ @string
60
+ end
61
+
62
+ # @return [string] the default xml tag defined for the instances class
63
+ def xml_tag
64
+ self.class.default_xml_tag
65
+ end
66
+ alias_method :default_xml_tag, :xml_tag
67
+
68
+ def each(&blk)
69
+ @container.each(&blk)
70
+ end
71
+
72
+ def all?(&blk)
73
+ @container.empty? ? false : super
74
+ end
75
+
76
+ def include? x
77
+ @container.include? x
78
+ end
79
+
80
+ def empty?
81
+ @container.empty?
82
+ end
83
+
84
+ def self.included(klass)
85
+ klass.extend(ClassMethods)
86
+ end
87
+
88
+ private
89
+
90
+ # id is represented as @n attribute in the xml, as xml:id
91
+ # is reserved for something else
92
+ def wrap_with_xml(tag, string, indexing, attrs = {})
93
+ merge_id!(attrs) if indexing && @id
94
+ attr = attrs.any? ? " #{to_xml_attrs(attrs)}" : ''
95
+ "<#{tag}#{attr}>#{string}</#{tag}>"
96
+ end
97
+
98
+ def to_xml_attrs(attrs)
99
+ attrs.map { |k, v| %{#{k}="#{v}"} }.join(' ')
100
+ end
101
+
102
+ def recursive_xml(tags, indexing, inline, attrs)
103
+ each_with_object('') do |element, s|
104
+ s << element.to_xml(tags.clone, indexing: indexing, recursive: true,
105
+ inline: inline, attrs: attrs)
106
+ end
107
+ end
108
+
109
+ def merge_id!(attrs)
110
+ attrs.merge!(id_as_xml => @id,)
111
+ end
112
+
113
+ def id_as_xml
114
+ 'n'
115
+ end
116
+
117
+ def inline_id(tag)
118
+ { "#{tag}_#{id_as_xml}" => @id }
119
+ end
120
+
121
+ module ClassMethods
122
+ def container_alias(al)
123
+ alias_method al, :container
124
+ alias_method "no_#{al}?", :empty?
125
+ end
126
+
127
+ # Defines the default xml tag used by #to_xml
128
+ def xml_tag(tag)
129
+ @default_xml_tag = tag
130
+ end
131
+
132
+ def default_xml_tag
133
+ @default_xml_tag
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,133 @@
1
+ module LLT
2
+ module Core
3
+ # Module that holds the shared functionality of all
4
+ # LLT Services.
5
+ #
6
+ # cf. specs for documentation
7
+ module Serviceable
8
+ def self.included(klass)
9
+ klass.extend(ClassMethods)
10
+ end
11
+
12
+ attr_reader :default_options
13
+
14
+ # Initializes a new service instance and configures its services
15
+ def initialize(options = {})
16
+ configure(options)
17
+ set_default_options(options)
18
+ register
19
+ end
20
+
21
+ # Registers self in the service_class with force
22
+ def register!
23
+ guarded do
24
+ write_to_register
25
+ end
26
+ end
27
+
28
+ def fork_instance
29
+ # Not sure atm how services should be handled here -
30
+ # decide later.
31
+ self.class.new(@default_options)
32
+ end
33
+
34
+ private
35
+
36
+ def set_default_options(opts)
37
+ # do not want to capture any service instance here
38
+ # taking the to_s root to enable indifferent access and provide
39
+ # security against DOS attacks...
40
+ relevant_keys = self.class.default_options.keys.map(&:to_s)
41
+ relevant_opts = opts.each_with_object({}) do |(k, v), h|
42
+ h[k.to_sym] = v if relevant_keys.include?(k.to_s)
43
+ end
44
+ @default_options = self.class.default_options.merge(relevant_opts)
45
+ end
46
+
47
+ def parse_option(opt, options)
48
+ # string keys in options are valid
49
+ #
50
+ # we cannot just do simple ||'s, because some options might
51
+ # be a totally legitimate false
52
+ option = options[opt]
53
+ option = options[opt.to_s] if option.nil?
54
+
55
+ option.nil? ? @default_options[opt] : option
56
+ end
57
+
58
+ # Sets instance variables for all used services.
59
+ def configure(options)
60
+ used_services.each do |service, def_instance|
61
+ inst = options[service] || registered(service) || def_instance.call
62
+ instance_variable_set("@#{service}", inst)
63
+ end
64
+ end
65
+
66
+ def registered(service)
67
+ guarded do
68
+ service_class.fetch(service)
69
+ end
70
+ end
71
+
72
+ def register
73
+ guarded do
74
+ write_to_register unless service_class.registered?(service_name)
75
+ end
76
+ end
77
+
78
+ def used_services
79
+ self.class.used_services
80
+ end
81
+
82
+ def guarded
83
+ if service_class
84
+ yield
85
+ end
86
+ end
87
+
88
+ def write_to_register
89
+ service_class.register(service_name => self)
90
+ end
91
+
92
+ # Class that is used to register a service.
93
+ # Returns LLT::Service if it is defined.
94
+ def service_class
95
+ if defined?(LLT::Service)
96
+ LLT::Service
97
+ else
98
+ nil
99
+ end
100
+ end
101
+
102
+ # Name used to register service
103
+ # Should be implemented by including class
104
+ def service_name
105
+ :undefined_service
106
+ end
107
+ end
108
+
109
+ module ClassMethods
110
+ def default_options
111
+ {}
112
+ end
113
+
114
+ def used_services
115
+ @used_services ||= {}
116
+ end
117
+
118
+ def method_missing(meth, *args, &blk)
119
+ if meth.match(/^uses_(.*)/)
120
+ key = $1.to_sym
121
+ used_services[key] = blk
122
+ attr_accessor key
123
+ else
124
+ super
125
+ end
126
+ end
127
+
128
+ def respond_to_missing?(meth, include_private = false)
129
+ meth.match(/^uses_(.*)/) || super
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,5 @@
1
+ module LLT
2
+ module Core
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
data/lib/llt/core.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "llt/core/version"
2
+
3
+ module LLT
4
+ module Core
5
+ require 'llt/core/containable'
6
+ require 'llt/core/serviceable'
7
+ end
8
+ end
data/llt-core.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'llt/core/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "llt-core"
8
+ spec.version = LLT::Core::VERSION
9
+ spec.authors = ["LFDM"]
10
+ spec.email = ["1986gh@gmail.com"]
11
+ spec.description = %q{LLT::Core classes and modules}
12
+ spec.summary = %q{Contains classes and modules that are shared across several llt gems}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "rack-test"
25
+ spec.add_development_dependency "simplecov", "~> 0.7"
26
+ spec.add_dependency "sinatra"
27
+ spec.add_dependency "sinatra-contrib"
28
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+ require 'llt/core/api'
3
+
4
+ describe LLT::Core::Api::Helpers do
5
+ let(:dummy) do
6
+ Class.new { include LLT::Core::Api::Helpers }.new
7
+ end
8
+
9
+ describe "#extract_text" do
10
+ it "tries to resolve a passed or a given text param" do
11
+ pending
12
+ end
13
+ end
14
+
15
+ describe "#uu" do
16
+ it "unescapes url strings" do
17
+ url = 'http%3A%2F%2Ftest.com'
18
+ dummy.uu(url).should == 'http://test.com'
19
+ end
20
+ end
21
+
22
+ describe "#u" do
23
+ it "escapes url strings" do
24
+ url = 'http://test.com'
25
+ dummy.u(url).should == 'http%3A%2F%2Ftest.com'
26
+ end
27
+ end
28
+
29
+ describe "#extract_markup_params" do
30
+ it "extracts the relevant params for markup methods from html params" do
31
+ params = { 'recursive' => true, 'text' => 'test' }
32
+ dummy.extract_markup_params(params).should == [nil, { recursive: true }]
33
+ end
34
+
35
+ it "returns an array that should be exploded when used with #to_xml" do
36
+ params = { recursive: true, tags: %w{ a b }}
37
+ extracted = [%w{ a b }, { recursive: true }]
38
+ dummy.extract_markup_params(params).should == extracted
39
+ end
40
+ end
41
+
42
+ describe "#to_xml" do
43
+ it "calls to xml on all elements of a given array and joins them to a string" do
44
+ el1, el2 = double, double
45
+ el1.stub(to_xml: '<a>')
46
+ el2.stub(to_xml: '<b>')
47
+ dummy.to_xml([el1, el2]).should =~ /<a><b>/
48
+ end
49
+
50
+ it "includes the xml declaration" do
51
+ el1 = double
52
+ el1.stub(to_xml: '<a>')
53
+ dummy.to_xml([el1]).should =~ /<\?xml version="1\.0" encoding="UTF-8"\?>/
54
+ end
55
+
56
+ it "looks for an optional param 'root', which is used to wrap the xml stream" do
57
+ el1 = double
58
+ el1.stub(to_xml: '<a>')
59
+ res = /<body cite="128">.*<\/body>/
60
+ dummy.to_xml([el1], { root: 'body cite="128"'}).should =~ res
61
+ end
62
+
63
+ it "its root element defaults to doc" do
64
+ el1 = double
65
+ el1.stub(to_xml: '<a>')
66
+ dummy.to_xml([el1]).should =~ /<doc>.*<\/doc>/
67
+ end
68
+ end
69
+
70
+ describe "#typecast_params!" do
71
+ it "does typecasting for boolean strings" do
72
+ params = { a: 1, b: 'true' }
73
+ dummy.typecast_params!(params).should == { a: 1, b: true }
74
+ end
75
+
76
+ it "looks into Arrays as well" do
77
+ params = { a: 'true', b: ['nil', 'false'] }
78
+ dummy.typecast_params!(params).should == { a: true, b: [nil, false] }
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,233 @@
1
+ require 'spec_helper'
2
+
3
+ describe LLT::Core::Containable do
4
+ let(:dummy) do
5
+ Class.new do
6
+ include LLT::Core::Containable
7
+ end
8
+ end
9
+
10
+ let(:other_dummy) do
11
+ Class.new do
12
+ include LLT::Core::Containable
13
+ end
14
+ end
15
+
16
+ let(:third_dummy) do
17
+ Class.new do
18
+ include LLT::Core::Containable
19
+ end
20
+ end
21
+
22
+ let(:instance) { dummy.new('') }
23
+
24
+ describe "#to_s" do
25
+ it "returns the string it has been initialized with" do
26
+ obj = dummy.new('test')
27
+ obj.to_s.should == 'test'
28
+ end
29
+ end
30
+
31
+ describe "#id" do
32
+ it "returns the id it has been initialized with" do
33
+ obj = dummy.new('test', 1)
34
+ obj.id.should == 1
35
+ end
36
+ end
37
+
38
+ describe "#n" do
39
+ it "is an alias for #id (for xml terminology)" do
40
+ obj = dummy.new('test', 1)
41
+ obj.n.should == 1
42
+ end
43
+ end
44
+
45
+ context "xml handling" do
46
+ describe ".xml_tag" do
47
+ it "sets the classes default xml tag" do
48
+ dummy.xml_tag('s')
49
+ instance.xml_tag.should == 's'
50
+ end
51
+ end
52
+
53
+ describe "#as_xml" do
54
+ it "represent the xml value that is used in #to_xml, defaults to the string it has been initialized with" do
55
+ obj = dummy.new('test')
56
+ obj.as_xml.should == 'test'
57
+ end
58
+
59
+ it "can be overwritten" do
60
+ obj = dummy.new('test')
61
+ obj.stub(:as_xml) { 'custom' }
62
+ obj.as_xml.should == 'custom'
63
+ end
64
+ end
65
+
66
+ describe "#to_xml" do
67
+ it "returns the #as_xml value as xml with its default tag" do
68
+ dummy.xml_tag 'test'
69
+ obj = dummy.new('string')
70
+ obj.to_xml.should == '<test>string</test>'
71
+ end
72
+
73
+ it "allows the tag to be given as param" do
74
+ obj = dummy.new('string')
75
+ obj.to_xml('tag').should == '<tag>string</tag>'
76
+ end
77
+
78
+ it "can be called recursively to include the container elements inside the default tag" do
79
+ dummy.xml_tag 's'
80
+ other_dummy.xml_tag 'w'
81
+
82
+ sentence = dummy.new('a simple sentence')
83
+ token1 = other_dummy.new('a')
84
+ token2 = other_dummy.new('simple')
85
+ token3 = other_dummy.new('sentence')
86
+ sentence << [token1, token2, token3]
87
+ result = '<s><w>a</w><w>simple</w><w>sentence</w></s>'
88
+ sentence.to_xml(recursive: true).should == result
89
+ end
90
+
91
+ it "allows multiple tags given in an Array, which will be used recursively" do
92
+ sentence = dummy.new('a simple sentence')
93
+ token1 = dummy.new('a')
94
+ token2 = dummy.new('simple')
95
+ token3 = dummy.new('sentence')
96
+ token1 << dummy.new('a')
97
+ sentence << [token1, token2, token3]
98
+ result = '<a><b><c>a</c></b><b>simple</b><b>sentence</b></a>'
99
+ sentence.to_xml(%w{ a b c }, recursive: true).should == result
100
+ end
101
+
102
+ it "falls back to the default tags when not enough custom tags are given" do
103
+ dummy.xml_tag 's'
104
+
105
+ sentence = dummy.new('a simple sentence')
106
+ token1 = dummy.new('a')
107
+ token2 = dummy.new('simple')
108
+ token3 = dummy.new('sentence')
109
+ token1 << dummy.new('a')
110
+ sentence << [token1, token2, token3]
111
+ result = '<a><b><s>a</s></b><b>simple</b><b>sentence</b></a>'
112
+ sentence.to_xml(%w{ a b }, recursive: true).should == result
113
+ end
114
+
115
+ it "can use a mix of custom and default tags if you pass nils" do
116
+ dummy.xml_tag 's'
117
+
118
+ sentence = dummy.new('a simple sentence')
119
+ token1 = dummy.new('a')
120
+ token2 = dummy.new('simple')
121
+ token3 = dummy.new('sentence')
122
+ token1 << dummy.new('a')
123
+ sentence << [token1, token2, token3]
124
+ result = '<a><s><c>a</c></s><s>simple</s><s>sentence</s></a>'
125
+ sentence.to_xml(['a', nil, 'c'], recursive: true).should == result
126
+ end
127
+
128
+ it "can include the id of an element, as @n attribute" do
129
+ dummy.xml_tag 's'
130
+ other_dummy.xml_tag 'w'
131
+
132
+ sentence = dummy.new('', 1)
133
+ token = other_dummy.new('word', 1)
134
+ sentence << token
135
+ result = '<s n="1"><w n="1">word</w></s>'
136
+ sentence.to_xml(indexing: true, recursive: true).should == result
137
+ end
138
+
139
+ it "recursive representation can be inlined" do
140
+ dummy.xml_tag 's'
141
+ other_dummy.xml_tag 'w'
142
+ third_dummy.xml_tag 'f'
143
+
144
+ sentence = dummy.new('', 1)
145
+ token1 = other_dummy.new('', 1)
146
+ token2 = other_dummy.new('', 2)
147
+ form1 = third_dummy.new('a', 1)
148
+ form2 = third_dummy.new('b', 2)
149
+ token1 << form1
150
+ token2 << form2
151
+ sentence << [token1, token2]
152
+ result = '<f s_n="1" w_n="1" n="1">a</f><f s_n="1" w_n="2" n="2">b</f>'
153
+ sentence.to_xml(indexing: true, recursive: true, inline: true).should == result
154
+ end
155
+ end
156
+ end
157
+
158
+ context "json handling" do
159
+ describe "#as_json" do
160
+ it "represent the json value that is used in #to_json, defaults to the string it has been initialized with" do
161
+ obj = dummy.new('test')
162
+ obj.as_json.should == 'test'
163
+ end
164
+ end
165
+
166
+ describe "#to_json" do
167
+ pending "Not implemented"
168
+ end
169
+ end
170
+
171
+ describe "#container" do
172
+ it "returns the contents of the container" do
173
+ instance.container.should == []
174
+ end
175
+ end
176
+
177
+ describe "#<<" do
178
+ it "adds an element to the container" do
179
+ instance << 1
180
+ instance.container.should == [1]
181
+ end
182
+
183
+ it "also takes an array, which is flattened" do
184
+ instance << [1,2]
185
+ instance.container.should == [1,2]
186
+ end
187
+ end
188
+
189
+ describe "#each" do
190
+ it "redirects Enumerable methods to the container" do
191
+ instance << [1,2]
192
+ instance.inject(:+).should == 3
193
+ end
194
+ end
195
+
196
+ describe "#all?" do
197
+ it "changes implementation of all, which returns false when empty!" do
198
+ instance.container.should be_empty
199
+ instance.all?.should be_false
200
+ end
201
+ end
202
+
203
+ describe "#include?" do
204
+ it "delegates to the container" do
205
+ instance << 1
206
+ instance.include?(1).should be_true
207
+ end
208
+ end
209
+
210
+ describe "#empty?" do
211
+ it "delegates to the container" do
212
+ instance << 1
213
+ instance.should_not be_empty
214
+ end
215
+ end
216
+
217
+ describe "#[]" do
218
+ it "delegates to the container" do
219
+ instance << 1
220
+ instance[0].should == 1
221
+ instance[1].should be_nil
222
+ end
223
+ end
224
+
225
+ describe ".container_alias" do
226
+ it "sets an alias to access the container for more idiomaticity" do
227
+ dummy.container_alias :tokens
228
+ sentence = instance
229
+ sentence << [:token, :token]
230
+ sentence.tokens.should == sentence.container
231
+ end
232
+ end
233
+ end
@@ -0,0 +1,185 @@
1
+ require 'spec_helper'
2
+
3
+ describe LLT::Core::Serviceable do
4
+ let(:dummy) do
5
+ Class.new do
6
+ include LLT::Core::Serviceable
7
+ attr_reader :a_service
8
+
9
+ def service_class
10
+ nil
11
+ end
12
+
13
+ def service_name
14
+ :dummy_service
15
+ end
16
+
17
+ def self.default_options
18
+ {
19
+ option1: false,
20
+ option2: true
21
+ }
22
+ end
23
+ end
24
+ end
25
+
26
+ let(:service_class) { double }
27
+
28
+ it "provides readers for used services" do
29
+ dummy.uses_a_service { 1 }
30
+ instance = dummy.new
31
+ instance.should respond_to(:a_service)
32
+ end
33
+
34
+ it "provides writers for used services" do
35
+ dummy.uses_a_service { 1 }
36
+
37
+ instance = dummy.new
38
+ instance.a_service.should == 1
39
+
40
+ instance.a_service = 2
41
+ instance.a_service.should == 2
42
+ end
43
+
44
+ it "provides a reader for the instance's default options" do
45
+ instance = dummy.new
46
+ instance.default_options.should == { option1: false, option2: true }
47
+ end
48
+
49
+ describe ".uses_***" do
50
+ it "provides including classes with the dynamic method .uses_***" do
51
+ dummy.should respond_to(:uses_a_service)
52
+ dummy.should respond_to(:uses_another_service)
53
+ end
54
+ end
55
+
56
+ describe ".used_services" do
57
+ it "returns service used by the Serviceable including class" do
58
+ dummy.uses_a_service { 1 }
59
+ dummy.used_services.should have(1).item
60
+ dummy.used_services[:a_service].call.should == 1
61
+ end
62
+ end
63
+
64
+ describe "#initialize" do
65
+ context "when the class is using a service" do
66
+ context "with options" do
67
+ it "sets service as given" do
68
+ dummy.uses_a_service { 2 }
69
+ instance = dummy.new(a_service: 1)
70
+ instance.a_service.should == 1
71
+ end
72
+ end
73
+
74
+ context "without options" do
75
+ # service class is usually LLT::Service or nothing
76
+ it "tries to obtain a service registered in the service class" do
77
+ service_class.stub(:fetch) { :registered_service }
78
+ service_class.stub(:registered?) { true }
79
+ dummy.any_instance.stub(:service_class) { service_class }
80
+
81
+ dummy.uses_a_service { 1 }
82
+ instance = dummy.new
83
+ instance.a_service.should == :registered_service
84
+ end
85
+
86
+ it "initializes with its default service when service class doesn't have anything" do
87
+ service_class.stub(:fetch) { nil }
88
+ service_class.stub(:registered?) { true }
89
+ dummy.any_instance.stub(:service_class) { service_class }
90
+
91
+ dummy.uses_a_service { 1 }
92
+ instance = dummy.new
93
+ instance.a_service.should == 1
94
+ end
95
+ end
96
+
97
+ it "tries to register itself in the service class" do
98
+ service_class.stub(:registered?) { false }
99
+ dummy.any_instance.stub(:service_class) { service_class }
100
+
101
+ service_class.should receive(:register).with(dummy_service: an_instance_of(dummy))
102
+
103
+ dummy.new
104
+ end
105
+
106
+ it "fails to register when such a service is already registered" do
107
+ service_class.stub(:registered?) { true }
108
+ dummy.any_instance.stub(:service_class) { service_class }
109
+
110
+ service_class.should_not receive(:register)
111
+
112
+ dummy.new
113
+ end
114
+ end
115
+
116
+ context "when the class is not using a service" do
117
+ it "doesn't instantiate a given service" do
118
+ dummy.uses_another_service { 2 }
119
+ instance = dummy.new(a_service: 1)
120
+ instance.a_service.should be_nil
121
+ end
122
+ end
123
+
124
+ context "with default options passed in" do
125
+ it "sets them only if they appear in Class.default_options" do
126
+ instance = dummy.new(option3: 3)
127
+ instance.default_options.should == { option1: false, option2: true }
128
+ end
129
+
130
+ it "strings as keys are valid as well" do
131
+ instance = dummy.new('option1' => 1)
132
+ instance.default_options.should == { option1: 1, option2: true }
133
+ end
134
+
135
+ it "services are not saved as default options" do
136
+ dummy.uses_a_service { 1 }
137
+ instance = dummy.new(a_service: 2)
138
+ instance.a_service.should == 2
139
+ instance.default_options.should == { option1: false, option2: true }
140
+ end
141
+ end
142
+ end
143
+
144
+ describe "#register!" do
145
+ it "registers self in the service class (if it's available), even if such a service is present" do
146
+ service_class.stub(:registered?) { true }
147
+ dummy.any_instance.stub(:service_class) { service_class }
148
+
149
+ service = dummy.new
150
+
151
+ service_class.should receive(:register).once
152
+ service.register!
153
+ end
154
+ end
155
+
156
+ describe "#fork_instance" do
157
+ it "returns a new service instance with the same default options as self" do
158
+ instance = dummy.new(option1: 1, option2: 2)
159
+ forked = instance.fork_instance
160
+ forked.should_not == instance
161
+ forked.default_options.should == instance.default_options
162
+ end
163
+ end
164
+
165
+ context "private unit tests" do
166
+ describe "#parse_option" do
167
+ context "parses a given option from a given options hash in the light of the default options" do
168
+ it "retains legitimate false values" do
169
+ instance = dummy.new
170
+ # just repeating here for clarification
171
+ instance.default_options.should == { option1: false, option2: true }
172
+
173
+ option = instance.send(:parse_option, :option1, { option3: 3 })
174
+ option.should == false
175
+ end
176
+
177
+ it "works with Symbols and Strings as keys in the options hash" do
178
+ instance = dummy.new
179
+ option = instance.send(:parse_option, :option2, { 'option2' => false })
180
+ option.should == false
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe LLT::Core do
4
+ it 'should have a version number' do
5
+ LLT::Core::VERSION.should_not be_nil
6
+ end
7
+ end
@@ -0,0 +1,27 @@
1
+ require 'simplecov'
2
+ require 'coveralls'
3
+
4
+ Coveralls.wear!
5
+
6
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
7
+ SimpleCov::Formatter::HTMLFormatter,
8
+ Coveralls::SimpleCov::Formatter
9
+ ]
10
+
11
+ SimpleCov.start do
12
+ add_filter '/spec/'
13
+ end
14
+
15
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
16
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
17
+ require 'llt/core'
18
+
19
+ if defined?(LLT::Logger)
20
+ LLT::Logger.level = nil
21
+ end
22
+
23
+ RSpec.configure do |config|
24
+ config.treat_symbols_as_metadata_keys_with_true_values = true
25
+ config.run_all_when_everything_filtered = true
26
+ config.filter_run :focus
27
+ end
metadata ADDED
@@ -0,0 +1,166 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: llt-core
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - LFDM
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rack-test
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.7'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.7'
83
+ - !ruby/object:Gem::Dependency
84
+ name: sinatra
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'
97
+ - !ruby/object:Gem::Dependency
98
+ name: sinatra-contrib
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: LLT::Core classes and modules
112
+ email:
113
+ - 1986gh@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".rspec"
120
+ - ".travis.yml"
121
+ - Gemfile
122
+ - LICENSE.txt
123
+ - README.md
124
+ - Rakefile
125
+ - lib/llt/core.rb
126
+ - lib/llt/core/api.rb
127
+ - lib/llt/core/api/helpers.rb
128
+ - lib/llt/core/containable.rb
129
+ - lib/llt/core/serviceable.rb
130
+ - lib/llt/core/version.rb
131
+ - llt-core.gemspec
132
+ - spec/lib/llt/core/api/helpers_spec.rb
133
+ - spec/lib/llt/core/containable_spec.rb
134
+ - spec/lib/llt/core/serviceable_spec.rb
135
+ - spec/lib/llt/core_spec.rb
136
+ - spec/spec_helper.rb
137
+ homepage: ''
138
+ licenses:
139
+ - MIT
140
+ metadata: {}
141
+ post_install_message:
142
+ rdoc_options: []
143
+ require_paths:
144
+ - lib
145
+ required_ruby_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ requirements: []
156
+ rubyforge_project:
157
+ rubygems_version: 2.1.5
158
+ signing_key:
159
+ specification_version: 4
160
+ summary: Contains classes and modules that are shared across several llt gems
161
+ test_files:
162
+ - spec/lib/llt/core/api/helpers_spec.rb
163
+ - spec/lib/llt/core/containable_spec.rb
164
+ - spec/lib/llt/core/serviceable_spec.rb
165
+ - spec/lib/llt/core_spec.rb
166
+ - spec/spec_helper.rb