harbinger 0.0.1.pre → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.hound.yml +818 -0
  4. data/.travis.yml +20 -0
  5. data/Gemfile +23 -3
  6. data/README.md +8 -27
  7. data/Rakefile +47 -1
  8. data/app/controllers/harbinger/messages_controller.rb +24 -0
  9. data/app/models/harbinger/database_channel_message.rb +51 -0
  10. data/app/models/harbinger/database_channel_message_element.rb +19 -0
  11. data/app/views/harbinger/messages/index.html.erb +43 -0
  12. data/app/views/harbinger/messages/show.html.erb +24 -0
  13. data/config/routes.rb +3 -0
  14. data/db/migrate/20140310185338_create_harbinger_database_channel_message.rb +11 -0
  15. data/db/migrate/20140310185339_create_harbinger_database_channel_message_elements.rb +14 -0
  16. data/gemfiles/rails4.1.gemfile +12 -0
  17. data/gemfiles/rails4.gemfile +13 -0
  18. data/harbinger.gemspec +22 -7
  19. data/lib/generators/harbinger/install/install_generator.rb +23 -0
  20. data/lib/generators/harbinger/install/templates/harbinger_initializer.rb.erb +6 -0
  21. data/lib/harbinger.rb +100 -1
  22. data/lib/harbinger/channels.rb +25 -0
  23. data/lib/harbinger/channels/database_channel.rb +15 -0
  24. data/lib/harbinger/channels/logger_channel.rb +31 -0
  25. data/lib/harbinger/channels/null_channel.rb +7 -0
  26. data/lib/harbinger/configuration.rb +58 -0
  27. data/lib/harbinger/engine.rb +8 -1
  28. data/lib/harbinger/exceptions.rb +4 -0
  29. data/lib/harbinger/message.rb +20 -0
  30. data/lib/harbinger/reporters.rb +34 -0
  31. data/lib/harbinger/reporters/exception_reporter.rb +26 -0
  32. data/lib/harbinger/reporters/null_reporter.rb +14 -0
  33. data/lib/harbinger/reporters/request_reporter.rb +20 -0
  34. data/lib/harbinger/reporters/user_reporter.rb +20 -0
  35. data/lib/harbinger/version.rb +1 -1
  36. data/run_each_spec_in_isolation +9 -0
  37. data/script/fast_specs +20 -0
  38. data/spec/controllers/harbinger/messages_controller_spec.rb +26 -0
  39. data/spec/features/end_to_end_exception_handling_spec.rb +39 -0
  40. data/spec/lib/harbinger/channels/database_channel_spec.rb +18 -0
  41. data/spec/lib/harbinger/channels/logger_channel_spec.rb +21 -0
  42. data/spec/lib/harbinger/channels/null_channel_spec.rb +8 -0
  43. data/spec/lib/harbinger/channels_spec.rb +40 -0
  44. data/spec/lib/harbinger/configuration_spec.rb +53 -0
  45. data/spec/lib/harbinger/message_spec.rb +15 -0
  46. data/spec/lib/harbinger/reporters/exception_reporter_spec.rb +24 -0
  47. data/spec/lib/harbinger/reporters/null_reporter_spec.rb +21 -0
  48. data/spec/lib/harbinger/reporters/request_reporter_spec.rb +23 -0
  49. data/spec/lib/harbinger/reporters/user_reporter_spec.rb +17 -0
  50. data/spec/lib/harbinger/reporters_spec.rb +46 -0
  51. data/spec/lib/harbinger_spec.rb +60 -0
  52. data/spec/models/harbinger/database_channel_message_element_spec.rb +16 -0
  53. data/spec/models/harbinger/database_channel_message_spec.rb +68 -0
  54. data/spec/routing/harbinger/messages_routing_spec.rb +16 -0
  55. data/spec/spec_active_record_helper.rb +41 -0
  56. data/spec/spec_fast_helper.rb +70 -0
  57. data/spec/spec_slow_helper.rb +57 -0
  58. data/spec/spec_view_helper.rb +38 -0
  59. data/spec/test_app_templates/lib/generators/test_app_generator.rb +13 -0
  60. data/spec/views/harbinger/messages/index.html.erb_spec.rb +31 -0
  61. data/spec/views/harbinger/messages/show.html.erb_spec.rb +36 -0
  62. metadata +205 -20
  63. data/MIT-LICENSE +0 -20
@@ -0,0 +1,20 @@
1
+ language: ruby
2
+ rvm:
3
+ - "2.0.0"
4
+ - "2.1.1"
5
+ - "2.1.2"
6
+
7
+ gemfile:
8
+ - gemfiles/rails4.gemfile
9
+ - gemfiles/rails4.1.gemfile
10
+
11
+ env:
12
+ global:
13
+ - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
14
+
15
+ script: 'COVERAGE=true rake spec:travis'
16
+
17
+ bundler_args: --without headless debug
18
+
19
+ before_install:
20
+ - gem install bundler
data/Gemfile CHANGED
@@ -3,12 +3,32 @@ source "https://rubygems.org"
3
3
  # Declare your gem's dependencies in harbinger.gemspec.
4
4
  # Bundler will treat runtime dependencies like base dependencies, and
5
5
  # development dependencies will be added by default to the :development group.
6
- gemspec
6
+ gemspec path: File.expand_path('..', __FILE__)
7
7
 
8
8
  # Declare any dependencies that are still in development here instead of in
9
9
  # your gemspec. These might include edge Rails or gems from your path or
10
10
  # Git. Remember to move these dependencies to your gemspec before releasing
11
11
  # your gem to rubygems.org.
12
12
 
13
- # To use debugger
14
- # gem 'debugger'
13
+ gem 'capybara', require: false
14
+ gem 'coveralls', require: false
15
+ if ! ENV['TRAVIS']
16
+ gem 'simplecov', require: false
17
+ gem 'guard-rspec'
18
+ gem 'guard-bundler'
19
+ gem 'guard-rails'
20
+ gem 'rb-fsevent'
21
+ gem 'terminal-notifier-guard'
22
+ gem 'sexp_processor'
23
+ gem 'ruby_parser'
24
+ gem 'pry', '~> 0.9.7'
25
+ gem 'pry-nav'
26
+ gem 'byebug'
27
+ end
28
+
29
+ file = File.expand_path("Gemfile", ENV['ENGINE_CART_DESTINATION'] || ENV['RAILS_ROOT'] || File.expand_path("../spec/internal", __FILE__))
30
+
31
+ if File.exists?(file)
32
+ puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v`
33
+ instance_eval File.read(file)
34
+ end
data/README.md CHANGED
@@ -1,29 +1,10 @@
1
1
  # Harbinger
2
2
 
3
- TODO: Write a gem description
4
-
5
- ## Installation
6
-
7
- Add this line to your application's Gemfile:
8
-
9
- gem 'harbinger'
10
-
11
- And then execute:
12
-
13
- $ bundle
14
-
15
- Or install it yourself as:
16
-
17
- $ gem install harbinger
18
-
19
- ## Usage
20
-
21
- TODO: Write usage instructions here
22
-
23
- ## Contributing
24
-
25
- 1. Fork it ( http://github.com/<my-github-username>/harbinger/fork )
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
3
+ [![Version](https://badge.fury.io/rb/harbinger.png)](http://badge.fury.io/rb/harbinger)
4
+ [![Build Status](https://travis-ci.org/ndlib/harbinger.png?branch=master)](https://travis-ci.org/ndlib/harbinger)
5
+ [![Code Climate](https://codeclimate.com/github/ndlib/harbinger.png)](https://codeclimate.com/github/ndlib/harbinger)
6
+ [![Coverage Status](https://img.shields.io/coveralls/ndlib/harbinger.svg)](https://coveralls.io/r/ndlib/harbinger)
7
+ [![API Docs](http://img.shields.io/badge/API-docs-blue.svg)](http://rubydoc.info/github/ndlib/harbinger/master/frames/)
8
+ [![APACHE 2 License](http://img.shields.io/badge/APACHE2-license-blue.svg)](./LICENSE)
9
+
10
+ A Rails engine for arbitrary message creation and delivery.
data/Rakefile CHANGED
@@ -1 +1,47 @@
1
- require "bundler/gem_tasks"
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ Bundler::GemHelper.install_tasks
8
+
9
+ begin
10
+ APP_RAKEFILE = File.expand_path('../spec/internal/Rakefile', __FILE__)
11
+ load 'rails/tasks/engine.rake'
12
+ rescue LoadError
13
+ puts "Unable to load all app tasks for #{APP_RAKEFILE}"
14
+ end
15
+
16
+ require 'engine_cart/rake_task'
17
+ # http://stackoverflow.com/questions/23165506/rails-spring-breaking-generators
18
+ # https://github.com/cbeer/engine_cart/issues/15
19
+ EngineCart.rails_options = '--skip-spring'
20
+ require 'rspec/core/rake_task'
21
+
22
+ namespace :spec do
23
+ RSpec::Core::RakeTask.new(:all) do
24
+ ENV['COVERAGE'] = 'true'
25
+ end
26
+
27
+ desc 'Run the Travis CI specs'
28
+ task :travis do
29
+ ENV['RAILS_ENV'] = 'test'
30
+ spec_helper = File.expand_path('../spec/spec_slow_helper.rb', __FILE__)
31
+ ENV['SPEC_OPTS'] = "--profile 20 --require #{spec_helper}"
32
+ Rake::Task['engine_cart:clean'].invoke
33
+ Rake::Task['engine_cart:generate'].invoke
34
+ Rake::Task['spec:all'].invoke
35
+ end
36
+ end
37
+
38
+ begin
39
+ Rake::Task['default'].clear
40
+ rescue RuntimeError
41
+ puts 'Unable to find :default rake task; No worries.'
42
+ end
43
+
44
+ Rake::Task['spec'].clear
45
+
46
+ task spec: 'spec:all'
47
+ task default: 'spec:travis'
@@ -0,0 +1,24 @@
1
+ module Harbinger
2
+ class MessagesController < ActionController::Base
3
+
4
+ def index
5
+ messages
6
+ end
7
+
8
+ def show
9
+ message
10
+ end
11
+
12
+ protected
13
+
14
+ def messages
15
+ @messages ||= DatabaseChannelMessage.search(q: params[:q])
16
+ end
17
+
18
+ def message
19
+ @message ||= DatabaseChannelMessage.find(params[:id])
20
+ end
21
+
22
+ helper_method :message, :messages
23
+ end
24
+ end
@@ -0,0 +1,51 @@
1
+ require 'active_record'
2
+ require 'harbinger/database_channel_message_element'
3
+
4
+ module Harbinger
5
+ class DatabaseChannelMessage < ActiveRecord::Base
6
+ self.table_name = 'harbinger_messages'
7
+ has_many :elements, class_name: 'Harbinger::DatabaseChannelMessageElement', foreign_key: :message_id
8
+
9
+ def contexts=(values)
10
+ super(Array.wrap(values).join(','))
11
+ end
12
+
13
+ def contexts
14
+ super.split(',')
15
+ end
16
+
17
+ def self.store_message(message, storage = new)
18
+ storage.contexts = message.contexts
19
+ storage.state = 'new'
20
+ message.attributes.each do |key, value|
21
+ storage.elements.build(key: key, value: value)
22
+ end
23
+ storage.save!
24
+ end
25
+
26
+ def self.search(params = {})
27
+ search_text(params[:q]).
28
+ search_state(params[:state]).
29
+ ordered
30
+ end
31
+
32
+ # Search the message and its elements for the matching text.
33
+ scope :search_text, lambda { |text|
34
+ if text
35
+ where(
36
+ arel_table[:contexts].matches("#{text}%").
37
+ or(
38
+ arel_table[:id].
39
+ in(Arel::SqlLiteral.new(DatabaseChannelMessageElement.search_text(text).select(:message_id).to_sql))
40
+ )
41
+ )
42
+ else
43
+ all
44
+ end
45
+ }
46
+
47
+ scope :search_state, ->(state) { state ? where(arel_table[:state].eq(state)) : all }
48
+
49
+ scope :ordered, -> { order(arel_table[:created_at].desc) }
50
+ end
51
+ end
@@ -0,0 +1,19 @@
1
+ require 'active_record'
2
+ require 'harbinger/database_channel_message'
3
+
4
+ module Harbinger
5
+ class DatabaseChannelMessageElement < ActiveRecord::Base
6
+ self.table_name = 'harbinger_message_elements'
7
+ belongs_to :message, class_name: 'Harbinger::DatabaseChannelMessage', foreign_key: :message_id
8
+ serialize :value
9
+
10
+ scope :search_text, lambda { |text|
11
+ if text
12
+ # Using %text% because I am serializing the data.
13
+ where(arel_table[:value].matches("%#{text}%"))
14
+ else
15
+ self
16
+ end
17
+ }
18
+ end
19
+ end
@@ -0,0 +1,43 @@
1
+ <%= form_tag harbinger.messages_path, :method => :get, :class => "search-form" do %>
2
+ <fieldset>
3
+ <legend class="accessible-hidden">Search Messages</legend>
4
+ <%= label_tag :message_search, "Search Text", :class => "accessible-hidden" %>
5
+ <%= text_field_tag(
6
+ :q,
7
+ params[:q],
8
+ :class => "q search-query",
9
+ :id => "message_search",
10
+ :placeholder => "Search text of messages",
11
+ :size => "30",
12
+ :tabindex => "1",
13
+ :type => "search",
14
+ )%><button type="submit" class="search-submit btn btn-primary" id="keyword-search-submit" tabindex="2">
15
+ <i class="icon-search icon-white"></i><span class="accessible-hidden">Search</span>
16
+ </button>
17
+ </fieldset>
18
+ <% end %>
19
+
20
+ <table>
21
+ <caption>Messages</caption>
22
+ <thead>
23
+ <tr>
24
+ <th>Created At</th>
25
+ <th>Contexts</th>
26
+ <th>State</th>
27
+ <th>Actions</th>
28
+ </tr>
29
+ </thead>
30
+ <tbody>
31
+ <% messages.each do |message| %>
32
+ <tr class="message">
33
+ <td class="detail message-created-at-detail"><a href="<%= harbinger.message_path(message.to_param)%>"><time><%= message.created_at %></time></a></td>
34
+ <td>
35
+ <ul><% message.contexts.each do |context| %>
36
+ <li class="detail message-contexts-detail"><%= context %></li>
37
+ <% end %></ul>
38
+ </td>
39
+ <td class="detail message-state-detail"><%= message.state %></td>
40
+ <td class="actions">&nbsp;</td>
41
+ <% end %>
42
+ </tbody>
43
+ </table>
@@ -0,0 +1,24 @@
1
+ <article class="message">
2
+ <header class="message-header">
3
+ <h2>Message</h2>
4
+ <dl>
5
+ <dt class="term message-contexts-term">Contexts</dt>
6
+ <% message.contexts.each do |context| %>
7
+ <dd class="detail message-contexts-detail"><%= context %></dd>
8
+ <% end %>
9
+ <dt class="term message-state-term">State</dt>
10
+ <dd class="detail message-state-detail"><%= message.state %></dd>
11
+ <dt class="term message-created-at-term">Created at</dt>
12
+ <dd class="detail message-created-at-detail"><time><%= message.created_at %></time></dd>
13
+ </dl>
14
+ </header>
15
+ <section class="message-body">
16
+ <dl class="message-elements">
17
+ <% message.elements.each do |element| %>
18
+ <% dom_class_prefix = element.key.gsub(/_+/, '-') %>
19
+ <dt class="term <%= dom_class_prefix %>-term"><%= element.key %></dt>
20
+ <dd class="detail <%= dom_class_prefix %>-detail"><%= element.value %></dd>
21
+ <% end %>
22
+ </dl>
23
+ </section>
24
+ </article>
@@ -1,2 +1,5 @@
1
1
  Harbinger::Engine.routes.draw do
2
+ scope module: 'harbinger' do
3
+ resources :messages, only: [:index, :show]
4
+ end
2
5
  end
@@ -0,0 +1,11 @@
1
+ class CreateHarbingerDatabaseChannelMessage < ActiveRecord::Migration
2
+ def change
3
+ create_table :harbinger_messages do |t|
4
+ t.string :contexts
5
+ t.string :state, limit: 32
6
+ t.timestamps
7
+ end
8
+ add_index :harbinger_messages, :state
9
+ add_index :harbinger_messages, :contexts
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ class CreateHarbingerDatabaseChannelMessageElements < ActiveRecord::Migration
2
+ def change
3
+ create_table :harbinger_message_elements do |t|
4
+ t.integer :message_id
5
+ t.string :key
6
+ t.text :value, limit: 2147483647
7
+ t.timestamps
8
+ end
9
+ add_index :harbinger_message_elements, :message_id
10
+ add_index :harbinger_message_elements, :key
11
+ add_index :harbinger_message_elements, [:message_id, :key]
12
+ add_index :harbinger_message_elements, [:message_id, :value]
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ source 'http://rubygems.org'
2
+
3
+ file = File.expand_path("../../Gemfile", __FILE__)
4
+
5
+ if File.exists?(file)
6
+ puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v`
7
+ instance_eval File.read(file)
8
+ end
9
+ gem 'sass', '~> 3.2.15'
10
+ gem 'sprockets', '~> 2.11.0'
11
+
12
+ gem 'rails', '4.1.0'
@@ -0,0 +1,13 @@
1
+ source 'http://rubygems.org'
2
+
3
+ file = File.expand_path("../../Gemfile", __FILE__)
4
+
5
+ if File.exists?(file)
6
+ puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v`
7
+ instance_eval File.read(file)
8
+ end
9
+
10
+ gem 'sass', '~> 3.2.15'
11
+ gem 'sprockets', '~> 2.11.0'
12
+
13
+ gem 'rails', '4.0.3'
@@ -6,18 +6,33 @@ require 'harbinger/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "harbinger"
8
8
  spec.version = Harbinger::VERSION
9
- spec.authors = ["Jeremy Friesen"]
10
- spec.email = ["jeremy.n.friesen@gmail.com"]
11
- spec.summary = %q{An exception tracking Rails engine}
12
- spec.description = %q{An exception tracking Rails engine}
13
- spec.homepage = ""
9
+ spec.authors = [
10
+ "Jeremy Friesen"
11
+ ]
12
+ spec.email = [
13
+ "jeremy.n.friesen@gmail.com"
14
+ ]
15
+ spec.summary = %q{A Rails engine for arbitrary message creation and delivery.}
16
+ spec.description = %q{A Rails engine for arbitrary message creation and delivery.}
17
+ spec.homepage = "https://github.com/ndlib/harbinger"
14
18
  spec.license = "Apache2"
15
19
 
16
20
  spec.files = `git ls-files -z`.split("\x0")
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
+ spec.executables = spec.files.grep(%r{^bin/}) do |f|
22
+ f == 'bin/rails' ? nil : File.basename(f)
23
+ end.compact
18
24
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
25
  spec.require_paths = ["lib"]
20
26
 
21
27
  spec.add_development_dependency "bundler", "~> 1.5"
22
- spec.add_development_dependency "rake"
28
+ spec.add_development_dependency "rake", '~> 10.3'
29
+ spec.add_development_dependency "rspec-given", '~> 3.5'
30
+ spec.add_development_dependency 'rspec-rails', '~> 3.0'
31
+ spec.add_development_dependency 'rspec-html-matchers', '~>0.6'
32
+ spec.add_development_dependency "engine_cart", '~> 0.3'
33
+ spec.add_development_dependency "rails", "~> 4.0"
34
+ spec.add_development_dependency 'sqlite3', '~> 1.3'
35
+ spec.add_development_dependency 'database_cleaner', '~> 1.3'
36
+ spec.add_development_dependency 'capybara', '~> 2.4'
37
+
23
38
  end
@@ -0,0 +1,23 @@
1
+ require 'rails/generators'
2
+ module Harbinger
3
+ class InstallGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ class_option :skip_database_channel, default: false, type: :boolean
7
+
8
+ def install_database_channel
9
+ if ! options[:skip_database_channel]
10
+ rake 'harbinger:install:migrations'
11
+ end
12
+ end
13
+
14
+ def install_configuration_file
15
+ template "harbinger_initializer.rb.erb", "config/initializers/harbinger_initializer.rb"
16
+ end
17
+
18
+ def install_routes
19
+ route 'mount Harbinger::Engine => "/harbinger"'
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,6 @@
1
+ Harbinger.configure do |config|
2
+
3
+ # See Harbinger::Channels for more information
4
+ config.default_channels = [:logger, :database]
5
+
6
+ end