angus 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/bin/angus +13 -0
  2. data/lib/angus.rb +6 -4
  3. data/lib/angus/base.rb +119 -0
  4. data/lib/angus/base_actions.rb +38 -0
  5. data/lib/angus/base_resource.rb +14 -0
  6. data/lib/angus/command.rb +27 -0
  7. data/lib/angus/generator.rb +141 -0
  8. data/lib/angus/generator/templates/Gemfile +5 -0
  9. data/lib/angus/generator/templates/README.md +0 -0
  10. data/lib/angus/generator/templates/config.ru.erb +10 -0
  11. data/lib/angus/generator/templates/definitions/messages.yml +0 -0
  12. data/lib/angus/generator/templates/definitions/operations.yml.erb +21 -0
  13. data/lib/angus/generator/templates/definitions/representations.yml +0 -0
  14. data/lib/angus/generator/templates/definitions/service.yml.erb +3 -0
  15. data/lib/angus/generator/templates/resources/resource.rb.erb +6 -0
  16. data/lib/angus/generator/templates/services/service.rb.erb +4 -0
  17. data/lib/angus/marshallings/base.rb +2 -0
  18. data/lib/angus/marshallings/marshalling.rb +136 -0
  19. data/lib/angus/marshallings/unmarshalling.rb +29 -0
  20. data/lib/angus/renders/base.rb +2 -0
  21. data/lib/angus/renders/html_render.rb +9 -0
  22. data/lib/angus/renders/json_render.rb +15 -0
  23. data/lib/angus/request_handler.rb +62 -0
  24. data/lib/angus/resource_definition.rb +78 -0
  25. data/lib/angus/response.rb +53 -0
  26. data/lib/angus/responses.rb +232 -0
  27. data/lib/angus/rspec/spec_helper.rb +3 -0
  28. data/lib/angus/rspec/support/examples.rb +64 -0
  29. data/lib/angus/rspec/support/examples/describe_errors.rb +36 -0
  30. data/lib/angus/rspec/support/matchers/operation_response_matchers.rb +117 -0
  31. data/lib/angus/rspec/support/operation_response.rb +57 -0
  32. data/lib/angus/utils.rb +2 -0
  33. data/lib/angus/utils/params.rb +24 -0
  34. data/lib/angus/utils/string.rb +27 -0
  35. data/lib/angus/version.rb +2 -2
  36. data/spec/angus/rspec/examples/describe_errors_spec.rb +64 -0
  37. data/spec/spec_helper.rb +27 -0
  38. metadata +181 -19
  39. data/.gitignore +0 -17
  40. data/Gemfile +0 -4
  41. data/LICENSE.txt +0 -22
  42. data/README.md +0 -29
  43. data/Rakefile +0 -1
  44. data/angus.gemspec +0 -23
data/bin/angus ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # resolve bin path, ignoring symlinks
5
+ require 'pathname'
6
+ bin_file = Pathname.new(__FILE__).realpath
7
+
8
+ # add self to libpath
9
+ $:.unshift File.expand_path('../../lib', bin_file)
10
+
11
+ require 'angus/command'
12
+
13
+ Angus::Command.start
data/lib/angus.rb CHANGED
@@ -1,5 +1,7 @@
1
- require "angus/version"
1
+ # Application external dependencies
2
+ require 'json'
3
+ require 'rack'
2
4
 
3
- module Angus
4
- # Your code goes here...
5
- end
5
+ require_relative 'angus/version'
6
+ require_relative 'angus/utils'
7
+ require_relative 'angus/base'
data/lib/angus/base.rb ADDED
@@ -0,0 +1,119 @@
1
+ require 'json'
2
+ require 'logger'
3
+
4
+ require_relative 'resource_definition'
5
+ require_relative 'request_handler'
6
+ require_relative 'base_resource'
7
+ require_relative 'responses'
8
+
9
+ require_relative 'renders/base'
10
+ require_relative 'marshallings/base'
11
+ require_relative 'base_actions'
12
+
13
+ require 'angus/sdoc'
14
+
15
+ module Angus
16
+ class Base < RequestHandler
17
+ include BaseActions
18
+
19
+ FIRST_VERSION = '0.1'
20
+
21
+ def initialize
22
+ super
23
+
24
+ @resources_definitions = []
25
+ @version = FIRST_VERSION
26
+ @name = self.class.name.downcase
27
+ @configured = false
28
+ @definitions = nil
29
+ @logger = Logger.new(STDOUT)
30
+
31
+ configure!
32
+
33
+ register_base_routes
34
+ register_resources_routes
35
+ end
36
+
37
+ def register_resources_routes
38
+ @resources_definitions.each do |resource|
39
+ register_resource_routes(resource)
40
+ end
41
+ end
42
+
43
+ def configured?
44
+ @configured
45
+ end
46
+
47
+ # TODO ver que hacer
48
+ def configure
49
+ end
50
+
51
+ def configure!
52
+ raise 'Already configured' if configured?
53
+
54
+ # TODO ver como hacer configurable
55
+ @definitions = Angus::SDoc::DefinitionsReader.service_definition('definitions')
56
+
57
+ configure
58
+
59
+ @configured = true
60
+ end
61
+
62
+ def service_code_name
63
+ @definitions.code_name
64
+ end
65
+
66
+ def service_version
67
+ @definitions.version
68
+ end
69
+
70
+ def register(resource_name, options = {})
71
+ resource_definition = ResourceDefinition.new(resource_name, @definitions)
72
+
73
+ @resources_definitions << resource_definition
74
+ end
75
+
76
+ def base_path
77
+ "/#{service_code_name}"
78
+ end
79
+
80
+ def register_resource_routes(resource_definition)
81
+ resource_definition.operations.each do |operation|
82
+ method = operation.method.to_sym
83
+ op_path = "#{api_path}#{operation.path}"
84
+
85
+ response_metadata = resource_definition.build_response_metadata(operation.response_elements)
86
+
87
+ router.on(method, op_path) do |env, params|
88
+ request = Rack::Request.new(env)
89
+ params = Params.indifferent_params(params)
90
+
91
+ resource = resource_definition.resource_class.new(request, params)
92
+
93
+ begin
94
+ response = resource.send(operation.code_name)
95
+
96
+ response = {} unless response.is_a?(Hash)
97
+
98
+ messages = response.delete(:messages)
99
+
100
+ response = build_data_response(response, response_metadata, messages)
101
+
102
+ @response.write(response)
103
+ rescue Exception => error
104
+ status_code = get_error_status_code(error)
105
+ if status_code == Angus::Responses::HTTP_STATUS_CODE_INTERNAL_SERVER_ERROR
106
+ @logger.error("An exception occurs on #{resource.class.name}##{operation.code_name}")
107
+ @logger.error(error)
108
+ end
109
+ response = build_error_response(error)
110
+
111
+ @response.status = status_code
112
+ @response.write(response)
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ end
119
+ end
@@ -0,0 +1,38 @@
1
+ module Angus
2
+ module BaseActions
3
+
4
+ def discover_paths
5
+ {
6
+ 'doc' => doc_path,
7
+ 'api' => api_path
8
+ }
9
+ end
10
+
11
+ def register_base_routes
12
+ router.on(:get, '/') do
13
+ render discover_paths
14
+ end
15
+
16
+ router.on(:get, base_path) do
17
+ render discover_paths
18
+ end
19
+
20
+ router.on(:get, doc_path) do |env, params|
21
+ if params[:format] == 'json'
22
+ render(Angus::SDoc::JsonFormatter.format_service(@definitions), format: :json)
23
+ else
24
+ render(Angus::SDoc::HtmlFormatter.format_service(@definitions), format: :html)
25
+ end
26
+ end
27
+ end
28
+
29
+ def doc_path
30
+ "#{base_path}/doc/#{service_version}"
31
+ end
32
+
33
+ def api_path
34
+ "#{base_path}/api/#{service_version}"
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,14 @@
1
+ require 'yaml'
2
+
3
+ module Angus
4
+ class BaseResource
5
+
6
+ attr_reader :request, :params
7
+
8
+ def initialize(request, params)
9
+ @request = request
10
+ @params = params
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,27 @@
1
+ require 'erb'
2
+ require 'thor'
3
+
4
+ require_relative 'generator'
5
+
6
+ module Angus
7
+ class Command < Thor
8
+
9
+ desc 'new [NAME]', 'Generate a new service'
10
+ def new(name)
11
+ generator.new_service(name)
12
+ end
13
+
14
+ desc 'resource [NAME]', 'Generate a new resource'
15
+ method_option :actions, aliases: '-a', type: :array, desc: 'Generate the given actions for the resource'
16
+ def resource(name)
17
+ generator.resource(name)
18
+ end
19
+
20
+ private
21
+
22
+ def generator
23
+ @generator ||= Angus::Generator.new
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,141 @@
1
+ require 'erb'
2
+ require 'thor'
3
+ require 'thor/actions'
4
+
5
+ module Angus
6
+ class Generator < Thor
7
+ include Thor::Actions
8
+
9
+ RESOURCES_DIR = 'resources'
10
+ DEFINITIONS_DIR = 'definitions'
11
+ SERVICES_DIR = 'services'
12
+
13
+ NEW_APP_DIRECTORIES = %W(#{DEFINITIONS_DIR} #{RESOURCES_DIR} #{SERVICES_DIR})
14
+
15
+ NEW_APP_FILES = %w(
16
+ Gemfile
17
+ config.ru.erb
18
+ services/service.rb.erb
19
+ definitions/messages.yml
20
+ definitions/representations.yml
21
+ definitions/service.yml.erb
22
+ )
23
+
24
+ FILE_MAPPINGS = {
25
+ 'services/service.rb.erb' => -> command, app_name { File.join(SERVICES_DIR, "#{command.underscore(command.classify(app_name))}.rb") },
26
+ 'resources/resource.rb.erb' => -> command, name { "#{command.underscore(command.classify(name))}.rb" },
27
+ 'definitions/operations.yml.erb' => -> command, _ { File.join(command.resource_name, 'operations.yml') }
28
+ }
29
+
30
+ no_commands do
31
+ def new_service(name)
32
+ app_name(name)
33
+
34
+ empty_directory(app_name)
35
+
36
+ NEW_APP_DIRECTORIES.each do |directory|
37
+ empty_directory(File.join(app_name, directory))
38
+ end
39
+
40
+ NEW_APP_FILES.each do |file|
41
+ if is_erb?(file)
42
+ copy_erb_file(file, app_name)
43
+ else
44
+ copy_file(file, File.join(app_name, file))
45
+ end
46
+ end
47
+ end
48
+
49
+ def resource(name)
50
+ resource_name(name)
51
+ resource_actions(options[:actions])
52
+
53
+ empty_directory(RESOURCES_DIR)
54
+ empty_directory(DEFINITIONS_DIR)
55
+
56
+ copy_erb_file('resources/resource.rb.erb', resource_name, RESOURCES_DIR)
57
+ copy_erb_file('definitions/operations.yml.erb', resource_name, DEFINITIONS_DIR)
58
+ insert_into_services(" register :#{resource_name}\n")
59
+ end
60
+
61
+ def app_name(name = nil)
62
+ if name.nil?
63
+ @app_name
64
+ else
65
+ @app_name = name
66
+ end
67
+ end
68
+
69
+ def resource_name(name = nil)
70
+ if name.nil?
71
+ @resource_name
72
+ else
73
+ @resource_name = name
74
+ end
75
+ end
76
+
77
+ def resource_actions(actions = nil)
78
+ if actions.nil?
79
+ @resource_actions || []
80
+ else
81
+ @resource_actions = actions
82
+ end
83
+ end
84
+
85
+ def classify(string)
86
+ string.sub(/^[a-z\d]*/) { $&.capitalize }.gsub(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }.gsub('/', '::')
87
+ end
88
+
89
+ def underscore(camel_cased_word)
90
+ word = camel_cased_word.to_s.dup
91
+ word.gsub!(/::/, '/')
92
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
93
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
94
+ word.tr!('-', '_')
95
+ word.downcase!
96
+ word
97
+ end
98
+ end
99
+
100
+ private
101
+
102
+ def is_erb?(file)
103
+ file.end_with?('.erb')
104
+ end
105
+
106
+ def copy_erb_file(file, name, base_path = nil)
107
+ base_path = name if base_path.nil?
108
+
109
+ tmp_file = Tempfile.new(File.basename(file))
110
+
111
+ source = File.expand_path(find_in_source_paths(file.to_s))
112
+ content = ERB.new(File.binread(source)).result(binding)
113
+
114
+ File.open(tmp_file.path, 'w') { |f| f << content }
115
+ tmp_file.close
116
+
117
+ copy_file(tmp_file.path, File.join(base_path, filename_resolver(file, name)))
118
+ end
119
+
120
+ def insert_into_services(content)
121
+ config = {}
122
+ config.merge!(:after => /def configure\n|def configure .*\n/)
123
+
124
+ file = Dir[File.join(Dir.pwd, SERVICES_DIR, '*.*')].first
125
+
126
+ insert_into_file(file, *([content] << config))
127
+ end
128
+
129
+ def filename_resolver(file, app_name)
130
+ if FILE_MAPPINGS[file].nil?
131
+ file.gsub('.erb', '')
132
+ else
133
+ FILE_MAPPINGS[file].call(self, app_name)
134
+ end
135
+ end
136
+
137
+ end
138
+ end
139
+
140
+ Angus::Generator.source_root(File.join(File.dirname(File.expand_path(__FILE__)), 'generator',
141
+ 'templates'))
@@ -0,0 +1,5 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'rake'
4
+
5
+ gem 'angus', '~> 0.0'
File without changes
@@ -0,0 +1,10 @@
1
+ $: << (File.dirname(__FILE__))
2
+
3
+ require 'bundler'
4
+
5
+ Bundler.setup
6
+
7
+ require 'angus'
8
+ require 'services/<%= app_name %>'
9
+
10
+ run <%= classify(name) %>.new
@@ -0,0 +1,21 @@
1
+ <% resource_actions.each do |action_name| %>
2
+ <%= action_name%>:
3
+ name:
4
+ description: |
5
+
6
+ path:
7
+ method:
8
+ uri:
9
+ - element:
10
+ description:
11
+
12
+ response:
13
+ - element:
14
+ description:
15
+ required:
16
+ type:
17
+
18
+ messages:
19
+ - key:
20
+ description:
21
+ <% end %>
@@ -0,0 +1,3 @@
1
+ service: '<%= classify(app_name) %>'
2
+ code_name: '<%= app_name %>'
3
+ version: '0.1'
@@ -0,0 +1,6 @@
1
+ class <%= classify(resource_name) %> < Angus::BaseResource
2
+ <% resource_actions.each do |action_name| %>
3
+ def <%= action_name %>
4
+ end
5
+ <% end %>
6
+ end
@@ -0,0 +1,4 @@
1
+ class <%= classify(app_name) %> < Angus::Base
2
+ def configure
3
+ end
4
+ end
@@ -0,0 +1,2 @@
1
+ require_relative 'marshalling'
2
+ require_relative 'unmarshalling'