abc 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.
Files changed (116) hide show
  1. data/.gitignore +24 -0
  2. data/.travis.yml +28 -0
  3. data/.yardopts +8 -0
  4. data/Gemfile +16 -0
  5. data/LICENSE +27 -0
  6. data/README.md +72 -0
  7. data/Rakefile +1 -0
  8. data/abc.gemspec +20 -0
  9. data/adapters/Gemfile +19 -0
  10. data/adapters/Rakefile +1 -0
  11. data/adapters/abc-adapters.gemspec +24 -0
  12. data/adapters/abc/adapters/persistence/repositories/base.rb +43 -0
  13. data/adapters/abc/adapters/persistence/repositories/page.rb +18 -0
  14. data/adapters/abc/adapters/persistence/repositories/text.rb +18 -0
  15. data/adapters/lib/abc-adapters.rb +17 -0
  16. data/adapters/lib/adapters/config.rb +29 -0
  17. data/adapters/spec/adapters/persistence/repositories/base_spec.rb +45 -0
  18. data/adapters/spec/adapters/persistence/repositories/page_spec.rb +15 -0
  19. data/adapters/spec/adapters/persistence/repositories/text_spec.rb +15 -0
  20. data/adapters/spec/lib/adapters/config_spec.rb +30 -0
  21. data/adapters/spec/spec_helper.rb +10 -0
  22. data/contributing.md +66 -0
  23. data/core/Gemfile +20 -0
  24. data/core/Guardfile +6 -0
  25. data/core/Rakefile +1 -0
  26. data/core/abc-core.gemspec +22 -0
  27. data/core/abc/entities/content/text.rb +19 -0
  28. data/core/abc/entities/menu/menu.rb +16 -0
  29. data/core/abc/entities/menu/menu_entry.rb +20 -0
  30. data/core/abc/entities/menu/menuable.rb +6 -0
  31. data/core/abc/entities/menu/path.rb +17 -0
  32. data/core/abc/entities/pages/page.rb +16 -0
  33. data/core/abc/entities/view/viewable.rb +7 -0
  34. data/core/abc/entities/view/viewable_presenter.rb +9 -0
  35. data/core/abc/interactors/creates_menu.rb +23 -0
  36. data/core/abc/interactors/pages/builds_page.rb +21 -0
  37. data/core/lib/abc-core.rb +1 -0
  38. data/core/spec/entities/content/text_spec.rb +37 -0
  39. data/core/spec/entities/menu/menu_entry_spec.rb +11 -0
  40. data/core/spec/entities/menu/menu_spec.rb +17 -0
  41. data/core/spec/entities/menu/menuable_spec.rb +7 -0
  42. data/core/spec/entities/menu/path_spec.rb +8 -0
  43. data/core/spec/entities/pages/page_spec.rb +19 -0
  44. data/core/spec/entities/view/viewable_presenter_spec.rb +7 -0
  45. data/core/spec/entities/view/viewable_spec.rb +7 -0
  46. data/core/spec/interactors/creates_menu_spec.rb +31 -0
  47. data/core/spec/interactors/pages/builds_page_spec.rb +15 -0
  48. data/core/spec/spec_helper.rb +10 -0
  49. data/delivery/backend/Gemfile +44 -0
  50. data/delivery/backend/Guardfile +6 -0
  51. data/delivery/backend/Rakefile +1 -0
  52. data/delivery/backend/abc-backend.gemspec +26 -0
  53. data/delivery/backend/app/controllers/abc/application_controller.rb +6 -0
  54. data/delivery/backend/app/controllers/abc/backend/base_controller.rb +8 -0
  55. data/delivery/backend/app/presenters/abc/html/menu_entry_presenter.rb +87 -0
  56. data/delivery/backend/app/presenters/abc/html/menu_presenter.rb +68 -0
  57. data/delivery/backend/app/views/abc/backend/base/index.html.erb +1 -0
  58. data/delivery/backend/config.ru +6 -0
  59. data/delivery/backend/config/routes.rb +3 -0
  60. data/delivery/backend/lib/abc-backend.rb +2 -0
  61. data/delivery/backend/lib/abc/backend/engine.rb +7 -0
  62. data/delivery/backend/spec/integration/backend_spec.rb +10 -0
  63. data/delivery/backend/spec/integration/menu_spec.rb +18 -0
  64. data/delivery/backend/spec/internal/config/database.yml +3 -0
  65. data/delivery/backend/spec/internal/config/routes.rb +5 -0
  66. data/delivery/backend/spec/internal/db/schema.rb +3 -0
  67. data/delivery/backend/spec/internal/log/.gitignore +1 -0
  68. data/delivery/backend/spec/internal/public/favicon.ico +0 -0
  69. data/delivery/backend/spec/presenters/html/menu_entry_presenter_spec.rb +49 -0
  70. data/delivery/backend/spec/presenters/html/menu_presenter_spec.rb +74 -0
  71. data/delivery/backend/spec/spec_helper.rb +14 -0
  72. data/delivery/backend/spec/tiny_spec_helper.rb +13 -0
  73. data/delivery/frontend/Gemfile +45 -0
  74. data/delivery/frontend/Guardfile +6 -0
  75. data/delivery/frontend/Rakefile +1 -0
  76. data/delivery/frontend/abc-frontend.gemspec +29 -0
  77. data/delivery/frontend/app/conductors/abc/frontend/conductors/shows_page.rb +69 -0
  78. data/delivery/frontend/app/controllers/abc/application_controller.rb +6 -0
  79. data/delivery/frontend/app/controllers/abc/frontend/base_controller.rb +8 -0
  80. data/delivery/frontend/app/controllers/abc/frontend/pages_controller.rb +12 -0
  81. data/delivery/frontend/app/presenters/abc/html/page_presenter.rb +13 -0
  82. data/delivery/frontend/app/views/abc/frontend/base/index.html.erb +1 -0
  83. data/delivery/frontend/app/views/abc/frontend/pages/show.html.haml +1 -0
  84. data/delivery/frontend/config.ru +6 -0
  85. data/delivery/frontend/config/routes.rb +5 -0
  86. data/delivery/frontend/lib/abc-frontend.rb +3 -0
  87. data/delivery/frontend/lib/abc/frontend/engine.rb +7 -0
  88. data/delivery/frontend/spec/conductors/abc/frontend/shows_page_spec.rb +41 -0
  89. data/delivery/frontend/spec/integration/backend_spec.rb +10 -0
  90. data/delivery/frontend/spec/integration/pages_spec.rb +11 -0
  91. data/delivery/frontend/spec/internal/config/database.yml +3 -0
  92. data/delivery/frontend/spec/internal/config/routes.rb +5 -0
  93. data/delivery/frontend/spec/internal/db/schema.rb +3 -0
  94. data/delivery/frontend/spec/internal/log/.gitignore +1 -0
  95. data/delivery/frontend/spec/internal/public/favicon.ico +0 -0
  96. data/delivery/frontend/spec/presenters/html/page_presenter_spec.rb +19 -0
  97. data/delivery/frontend/spec/spec_helper.rb +15 -0
  98. data/delivery/frontend/spec/tiny_spec_helper.rb +14 -0
  99. data/documentation/architecture.md +131 -0
  100. data/documentation/architecture.png +0 -0
  101. data/documentation/architecture.svg +1192 -0
  102. data/lib/abc.rb +7 -0
  103. data/lib/abc/base_conductor.rb +63 -0
  104. data/lib/abc/base_conductor_spec.rb +9 -0
  105. data/lib/abc/base_interactor.rb +17 -0
  106. data/lib/abc/package.rb +11 -0
  107. data/script/bundle +2 -0
  108. data/script/projects +2 -0
  109. data/script/rspec +2 -0
  110. data/script/run +8 -0
  111. data/spec/lib/abc/base_interactor_spec.rb +11 -0
  112. data/spec/shared/callable.rb +24 -0
  113. data/yard/setup.rb +10 -0
  114. data/yard/templates/default/fulldoc/html/css/common.css +109 -0
  115. data/yard/templates/default/layout/html/layout.erb +56 -0
  116. metadata +163 -0
@@ -0,0 +1,74 @@
1
+ require 'tiny_spec_helper'
2
+ require 'presenters/abc/html/menu_presenter'
3
+
4
+ class MenuEntryMock
5
+ include ActionView::Helpers::TagHelper
6
+ def initialize(name); @name = name; end
7
+ def title; @title ||= rand(30).times.map{|i| ('A'..'Z').to_a.sample}.join end
8
+ attr_accessor :children
9
+ end
10
+
11
+ class MenuEntryPresenterMock
12
+ attr_accessor :menu_entry, :list_element_pair
13
+ def initialize(menu_entry, options)
14
+ @menu_entry = menu_entry
15
+ @list_element_pair = options[:list_element_pair]
16
+ end
17
+ def to_html; "<#{list_element_pair.last}>#{menu_entry.title}</#{list_element_pair.last}>"; end
18
+ end
19
+
20
+ class MenuMock
21
+ attr_accessor :entries
22
+ def initialize(options = {}); @entries = options[:entries] || []; end
23
+ end
24
+
25
+
26
+ module Abc
27
+ module Html
28
+ describe MenuPresenter do
29
+ let(:list_element_pair) { [:ul, :li] }
30
+ let(:entry1) { MenuEntryMock.new("node 1") }
31
+ let(:entry1_presenter) { MenuEntryPresenterMock.new(entry1, :list_element_pair => list_element_pair) }
32
+ let(:entry2) { MenuEntryMock.new("node 2") }
33
+ let(:entry2_presenter) { MenuEntryPresenterMock.new(entry2, :list_element_pair => list_element_pair) }
34
+ let(:menu) { MenuMock.new(:entries => [entry1, entry2]) }
35
+ let(:presenter_options) do
36
+ {
37
+ :menu_entry_presenter_class => MenuEntryPresenterMock,
38
+ :list_element_pair => list_element_pair
39
+ }
40
+ end
41
+ let(:presenter) { MenuPresenter.new(menu, presenter_options) }
42
+ # TODO: Add specs for list element pair squawks, or refactor these into
43
+ # two separate param. How do we handle co-dependence, then?
44
+ # i.e. since this is a ul and an li, what if people change
45
+ # the ul but not the li? Is this something that our API can make
46
+ # clearer than it is at the moment?
47
+
48
+ it "asks its entries to render themselves" do
49
+ presenter.to_html
50
+ end
51
+
52
+ it "draws its children in order" do
53
+ presenter.to_html.should == "<nav><ul>%s%s</ul></nav>" % [entry1_presenter.to_html, entry2_presenter.to_html]
54
+ end
55
+
56
+ it "is considered HTML safe" do
57
+ presenter.to_html.html_safe?.should be_true
58
+ end
59
+
60
+ it "allows an alternate root element" do
61
+ presenter.menu_element = :div
62
+ presenter.to_html.should match(/\A<div/)
63
+ end
64
+
65
+ context 'with alternate list element pair' do
66
+ let(:list_element_pair) { [:menu, :div] }
67
+
68
+ it "uses them properly" do
69
+ presenter.to_html.should match(/\A<nav><menu><div>/)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,14 @@
1
+ unless ENV['TRAVIS']
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ add_filter "/spec/"
5
+ end
6
+ end
7
+ require 'bundler/setup'
8
+
9
+ Bundler.require :default, :test
10
+
11
+ require 'capybara/rspec'
12
+
13
+ Combustion.initialize! :action_view, :active_model, :action_controller
14
+ require 'rspec/rails'
@@ -0,0 +1,13 @@
1
+ $LOAD_PATH.push File.expand_path('../../app', __FILE__)
2
+ %w(presenters conductors).each do |pattern|
3
+ $LOAD_PATH.push File.expand_path("../../app/#{pattern}", __FILE__)
4
+ end
5
+
6
+ unless ENV['TRAVIS']
7
+ require 'simplecov'
8
+ SimpleCov.start do
9
+ add_filter '/spec/'
10
+ end
11
+ end
12
+
13
+ require 'abc-core'
@@ -0,0 +1,45 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ git 'git://github.com/rails/rails.git' do
6
+ gem 'railties'
7
+ gem 'actionpack'
8
+ gem 'activemodel'
9
+ end
10
+
11
+ group :test do
12
+ gem 'rspec'
13
+ gem 'rspec-rails', :require => false
14
+ unless ENV['TRAVIS']
15
+ gem 'simplecov'
16
+ end
17
+ gem 'capybara'
18
+ platforms :jruby do
19
+ gem 'activerecord-jdbcsqlite3-adapter'
20
+ end
21
+
22
+ platforms :ruby do
23
+ gem 'sqlite3'
24
+ end
25
+ end
26
+
27
+ group :development, :test do
28
+ gem 'combustion', github: 'pat/combustion'
29
+ unless ENV['TRAVIS']
30
+ gem 'pry'
31
+ gem 'pry-nav'
32
+ gem 'guard-shell'
33
+ gem 'rb-fsevent', '~> 0.9', :platform => :ruby
34
+ end
35
+ end
36
+
37
+ group :development do
38
+ gem 'yard', "~> 0.8.4.1"
39
+ gem 'rdoc'
40
+ gem 'kramdown'
41
+ end
42
+
43
+ gem 'abc', :path => '../../'
44
+ gem 'abc-core', :path => '../../core'
45
+ gem 'abc-adapters', :path => '../../adapters'
@@ -0,0 +1,6 @@
1
+ guard :shell do
2
+ watch(/\A.*\.(rb|erb|haml)\z/) do |m|
3
+ system "rspec spec"
4
+ system "date"
5
+ end
6
+ end
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,29 @@
1
+ require File.expand_path('../../lib/abc/package', File.dirname(__FILE__))
2
+
3
+ # Describe your gem and declare its dependencies:
4
+ Gem::Specification.new do |s|
5
+ s.name = "abc-frontend"
6
+ s.version = Abc::VERSION
7
+ s.authors = Abc::AUTHORS
8
+ s.email = Abc::EMAILS
9
+ s.homepage = Abc::HOMEPAGE
10
+ s.summary = Abc::SUMMARY
11
+ s.description = Abc::DESCRIPTION
12
+
13
+ s.require_paths = ["lib"]
14
+
15
+ s.files = Dir['app/**/*', 'lib/**/*', 'config/**/*', 'spec/**/*']
16
+ s.test_files = s.files.grep(%r{^(spec)/})
17
+
18
+ s.required_ruby_version = '>= 1.9.3' # that's right.
19
+
20
+ s.add_dependency 'railties', Abc::RAILS_VERSION
21
+ s.add_dependency 'activesupport', Abc::RAILS_VERSION
22
+ s.add_dependency 'actionpack', Abc::RAILS_VERSION
23
+ s.add_dependency 'activemodel', Abc::RAILS_VERSION
24
+
25
+ s.add_dependency 'haml-rails'
26
+
27
+ s.add_dependency 'abc-core', Abc::VERSION
28
+ s.add_dependency 'abc-adapters', Abc::VERSION
29
+ end
@@ -0,0 +1,69 @@
1
+ require 'abc'
2
+ require 'abc/html/page_presenter'
3
+ require 'entities/pages/page'
4
+ require 'adapters/persistence/repositories/page'
5
+ require 'interactors/pages/builds_page'
6
+ require 'ostruct'
7
+
8
+ module Abc
9
+ module Frontend
10
+ module Conductors
11
+ class ShowsPage < ::Abc::BaseConductor
12
+
13
+ # Wraps and organizes response to controller.
14
+ def to_response
15
+ data.merge(data) do |key, value|
16
+ options[:presenter_classes][key.to_sym].new(value)
17
+ end
18
+ end
19
+
20
+ protected
21
+ attr_accessor :params, :options
22
+ attr_writer :data
23
+
24
+ def initialize(params, opts)
25
+ self.params = params
26
+ self.options = defaults.merge(opts)
27
+
28
+ # Make these a bit prettier.
29
+ @builders = OpenStruct.new(options[:builder_classes])
30
+ @presenters = OpenStruct.new(options[:presenter_classes])
31
+ @repository = options[:repository_class]
32
+
33
+ # Temporarily here, since we need to get the data from somewhere
34
+ @repository.store(:title => "Welcome to page #{params[:id]}")
35
+ end
36
+
37
+ # Transforms params into requests to the application, optionally
38
+ # hitting an adapter along the way.
39
+ def data
40
+ {}.merge(build_page)
41
+ end
42
+
43
+ def defaults
44
+ {
45
+ :repository_class => ::Abc::Adapters::Persistence::Repositories::Page,
46
+ :presenter_classes => { :page => ::Abc::Html::PagePresenter },
47
+ :builder_classes => { :page => ::Abc::Interactors::BuildsPage }
48
+ }.freeze
49
+ end
50
+
51
+ # Retrieve the required page from the database and construct it.j
52
+ def build_page
53
+ page_data = @repository.search.first
54
+
55
+ {:page => @builders.page.call(page_data)}
56
+ end
57
+
58
+ # We could also chain more methods to our data method. Each should
59
+ # return a hash, that we then wrap with a presenter, or pass on
60
+ # as straight data, depending on our our strategy in #to_response.
61
+ #
62
+ # def build_menu
63
+ # {}
64
+ # end
65
+
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,6 @@
1
+ require 'action_controller'
2
+
3
+ module Abc
4
+ class ApplicationController < ActionController::Base
5
+ end
6
+ end
@@ -0,0 +1,8 @@
1
+ module Abc
2
+ module Frontend
3
+ class BaseController < ApplicationController
4
+ def index
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+ require 'ostruct'
2
+ require 'abc/frontend/conductors/shows_page'
3
+
4
+ module Abc
5
+ module Frontend
6
+ class PagesController < BaseController
7
+ def show
8
+ @data = OpenStruct.new(::Abc::Frontend::Conductors::ShowsPage.call(params))
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module Abc
2
+ module Html
3
+ class PagePresenter
4
+ def initialize(page)
5
+ @page = page
6
+ end
7
+
8
+ def title
9
+ @page.title
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1 @@
1
+ Welcome to the Afterburner Frontend!
@@ -0,0 +1,6 @@
1
+ require 'bundler'
2
+
3
+ Bundler.require :default, :development
4
+
5
+ Combustion.initialize! :action_view, :active_model, :action_controller
6
+ run Combustion::Application
@@ -0,0 +1,5 @@
1
+ Abc::Frontend::Engine.routes.draw do
2
+ root to: 'base#index'
3
+
4
+ resources :pages, :only => [:show]
5
+ end
@@ -0,0 +1,3 @@
1
+ require 'rails'
2
+ require 'haml-rails'
3
+ require 'abc/frontend/engine'
@@ -0,0 +1,7 @@
1
+ module Abc
2
+ module Frontend
3
+ class Engine < Rails::Engine
4
+ isolate_namespace Abc::Frontend
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,41 @@
1
+ require 'tiny_spec_helper'
2
+ require 'abc/frontend/conductors/shows_page'
3
+
4
+ class MockPagePresenter
5
+ def initialize(vals); @vals = vals; end
6
+ def title; @vals.title; end
7
+ end
8
+
9
+ class MockRepository
10
+ def self.store(obj); @obj = obj.to_hash; end
11
+ def self.search; [@obj]; end
12
+ end
13
+
14
+ class MockPageBuilder
15
+ def self.call(hash); OpenStruct.new(hash); end
16
+ end
17
+
18
+
19
+ module Abc
20
+ module Frontend
21
+ module Conductors
22
+ describe ShowsPage do
23
+ let(:mocks) { { :repository_class => MockRepository,
24
+ :presenter_classes => { :page => MockPagePresenter },
25
+ :builder_classes => { :page => MockPageBuilder } } }
26
+
27
+ let(:result) { ShowsPage.call({:id => 1}, mocks) }
28
+ let(:instance) { ShowsPage.send(:new, {:id => 1}, mocks) }
29
+
30
+ it "returns a hash of presenters" do
31
+ expect(result).to be_kind_of Hash
32
+ end
33
+
34
+ it "should include a page presenter" do
35
+ result[:page].title.should == "Welcome to page 1"
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Frontend" do
4
+ describe "GET /" do
5
+ it "shows a welcome message" do
6
+ visit abc_frontend.root_path
7
+ page.should have_content("Welcome to the Afterburner Frontend!")
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Frontend" do
4
+ before(:each) { Abc::Adapters.enable_datastore! }
5
+ describe "GET /page/1" do
6
+ it "shows the page id" do
7
+ visit abc_frontend.page_path(:id => 1)
8
+ page.should have_content("Welcome to page 1")
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ test:
2
+ adapter: sqlite3
3
+ database: db/combustion_test.sqlite
@@ -0,0 +1,5 @@
1
+ require 'abc/frontend/engine'
2
+
3
+ Rails.application.routes.draw do
4
+ mount Abc::Frontend::Engine => '/'
5
+ end
@@ -0,0 +1,3 @@
1
+ ActiveRecord::Schema.define do
2
+ #
3
+ end
@@ -0,0 +1,19 @@
1
+ require 'tiny_spec_helper'
2
+ require 'presenters/abc/html/page_presenter'
3
+ require 'ostruct'
4
+
5
+ module Abc
6
+ module Html
7
+ describe PagePresenter do
8
+ let(:page) do
9
+ p = mock('page')
10
+ p.stub(:title).and_return('foo')
11
+ p
12
+ end
13
+
14
+ subject { PagePresenter.new(page) }
15
+
16
+ its(:title) { should == 'foo' }
17
+ end
18
+ end
19
+ end