From 5cbb5e96a1c5a232d2a665c1a1bcef2386f6f91d Mon Sep 17 00:00:00 2001 From: dblock Date: Mon, 6 Mar 2017 14:54:39 -0500 Subject: [PATCH] Added PostgreSQL support, closes #7. --- .travis.yml | 17 +- CHANGELOG.md | 3 +- Gemfile | 14 ++ README.md | 12 +- lib/slack-ruby-bot-server.rb | 11 +- .../api/endpoints/teams_endpoint.rb | 2 +- .../api/helpers/cursor_helpers.rb | 49 ++-- .../api/helpers/error_helpers.rb | 22 +- .../api/helpers/sort_helpers.rb | 6 +- lib/slack-ruby-bot-server/api/middleware.rb | 7 +- .../api/presenters/status_presenter.rb | 8 +- lib/slack-ruby-bot-server/app.rb | 27 +-- lib/slack-ruby-bot-server/config.rb | 16 ++ .../config/database_adapters/activerecord.rb | 27 +++ .../config/database_adapters/mongoid.rb | 24 ++ lib/slack-ruby-bot-server/models/team.rb | 68 ------ .../models/team/activerecord.rb | 13 ++ .../models/team/methods.rb | 55 +++++ .../models/team/mongoid.rb | 22 ++ lib/slack-ruby-bot-server/version.rb | 2 +- sample_app/.env | 3 - {sample_app => sample_apps}/.rspec | 0 .../sample_app_activerecord}/Gemfile | 5 +- .../sample_app_activerecord}/Procfile | 0 .../sample_app_activerecord}/Rakefile | 0 .../sample_app_activerecord}/commands.rb | 0 .../sample_app_activerecord}/commands/help.rb | 0 .../commands/whoami.rb | 0 sample_apps/sample_app_activerecord/config.ru | 21 ++ .../config/newrelic.yml | 0 .../config/postgresql.yml | 22 ++ .../spec/commands/help_spec.rb | 0 .../spec/commands/whoami_spec.rb | 0 .../spec/spec_helper.rb | 13 ++ sample_apps/sample_app_mongoid/Gemfile | 18 ++ sample_apps/sample_app_mongoid/Procfile | 1 + .../sample_app_mongoid}/README.md | 0 sample_apps/sample_app_mongoid/Rakefile | 10 + sample_apps/sample_app_mongoid/commands.rb | 2 + .../sample_app_mongoid/commands/help.rb | 19 ++ .../sample_app_mongoid/commands/whoami.rb | 6 + .../sample_app_mongoid}/config.ru | 0 .../sample_app_mongoid}/config/mongoid.yml | 0 .../sample_app_mongoid/config/newrelic.yml | 217 ++++++++++++++++++ .../spec/commands/help_spec.rb | 14 ++ .../spec/commands/whoami_spec.rb | 14 ++ .../sample_app_mongoid}/spec/spec_helper.rb | 0 slack-ruby-bot-server.gemspec | 1 - spec/api/endpoints/teams_endpoint_spec.rb | 4 +- .../activerecord/activerecord.rb | 3 + spec/database_adapters/activerecord/schema.rb | 13 ++ spec/database_adapters/mongoid/mongoid.rb | 2 + .../mongoid/rspec.rb} | 4 + spec/models/team_spec.rb | 10 +- spec/spec_helper.rb | 13 +- .../endpoints/it_behaves_like_a_cursor_api.rb | 6 +- spec/support/database_cleaner.rb | 4 - 57 files changed, 667 insertions(+), 163 deletions(-) create mode 100644 lib/slack-ruby-bot-server/config/database_adapters/activerecord.rb create mode 100644 lib/slack-ruby-bot-server/config/database_adapters/mongoid.rb delete mode 100644 lib/slack-ruby-bot-server/models/team.rb create mode 100644 lib/slack-ruby-bot-server/models/team/activerecord.rb create mode 100644 lib/slack-ruby-bot-server/models/team/methods.rb create mode 100644 lib/slack-ruby-bot-server/models/team/mongoid.rb delete mode 100644 sample_app/.env rename {sample_app => sample_apps}/.rspec (100%) rename {sample_app => sample_apps/sample_app_activerecord}/Gemfile (67%) rename {sample_app => sample_apps/sample_app_activerecord}/Procfile (100%) rename {sample_app => sample_apps/sample_app_activerecord}/Rakefile (100%) rename {sample_app => sample_apps/sample_app_activerecord}/commands.rb (100%) rename {sample_app => sample_apps/sample_app_activerecord}/commands/help.rb (100%) rename {sample_app => sample_apps/sample_app_activerecord}/commands/whoami.rb (100%) create mode 100644 sample_apps/sample_app_activerecord/config.ru rename {sample_app => sample_apps/sample_app_activerecord}/config/newrelic.yml (100%) create mode 100644 sample_apps/sample_app_activerecord/config/postgresql.yml rename {sample_app => sample_apps/sample_app_activerecord}/spec/commands/help_spec.rb (100%) rename {sample_app => sample_apps/sample_app_activerecord}/spec/commands/whoami_spec.rb (100%) create mode 100644 sample_apps/sample_app_activerecord/spec/spec_helper.rb create mode 100644 sample_apps/sample_app_mongoid/Gemfile create mode 100644 sample_apps/sample_app_mongoid/Procfile rename {sample_app => sample_apps/sample_app_mongoid}/README.md (100%) create mode 100644 sample_apps/sample_app_mongoid/Rakefile create mode 100644 sample_apps/sample_app_mongoid/commands.rb create mode 100644 sample_apps/sample_app_mongoid/commands/help.rb create mode 100644 sample_apps/sample_app_mongoid/commands/whoami.rb rename {sample_app => sample_apps/sample_app_mongoid}/config.ru (100%) rename {sample_app => sample_apps/sample_app_mongoid}/config/mongoid.yml (100%) create mode 100644 sample_apps/sample_app_mongoid/config/newrelic.yml create mode 100644 sample_apps/sample_app_mongoid/spec/commands/help_spec.rb create mode 100644 sample_apps/sample_app_mongoid/spec/commands/whoami_spec.rb rename {sample_app => sample_apps/sample_app_mongoid}/spec/spec_helper.rb (100%) create mode 100644 spec/database_adapters/activerecord/activerecord.rb create mode 100644 spec/database_adapters/activerecord/schema.rb create mode 100644 spec/database_adapters/mongoid/mongoid.rb rename spec/{support/mongoid.rb => database_adapters/mongoid/rspec.rb} (67%) diff --git a/.travis.yml b/.travis.yml index 9da2b8b..52457d7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,22 +2,21 @@ language: ruby cache: bundler -services: - - mongodb - matrix: include: - rvm: 2.3.1 script: - bundle exec danger - rvm: 2.3.1 - - rvm: 2.3.0 - - rvm: ruby-head - - rvm: jruby-head - allow_failures: - - rvm: ruby-head - - rvm: jruby-head + env: DATABASE_ADAPTER=activerecord + services: + - postgresql + - rvm: 2.3.1 + env: DATABASE_ADAPTER=mongoid + services: + - mongodb before_install: - "export DISPLAY=:99.0" - "sh -e /etc/init.d/xvfb start" + diff --git a/CHANGELOG.md b/CHANGELOG.md index e4f8c1d..6e15d9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ ### Changelog -#### 0.5.1 (Next) +#### 0.6.0 (Next) +* [#38](https://github.com/slack-ruby/slack-ruby-bot-server/issues/7): Added ActiveRecord support - [@zachfeldman](https://github.com/zachfeldman), [@spencerldixon](https://github.com/spencerldixon), [@dblock](https://github.com/dblock). * [#45](https://github.com/slack-ruby/slack-ruby-bot-server/pull/45): Updated grape-roar to 0.4.0 - [@swalberg](https://github.com/swalberg). * Your contribution here. diff --git a/Gemfile b/Gemfile index 2dc51c9..d2646b2 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,19 @@ source 'https://rubygems.org' +case ENV['DATABASE_ADAPTER'] +when 'mongoid' then + gem 'mongoid' + gem 'kaminari-mongoid' + gem 'mongoid-scroll' +when 'activerecord' then + gem 'pg' + gem 'activerecord' + gem 'otr-activerecord' + gem 'cursor_pagination' +else + raise "Invalid DATABASE_ADAPTER #{database_adapter}." +end + gemspec group :development, :test do diff --git a/README.md b/README.md index aa60dc0..b01d646 100644 --- a/README.md +++ b/README.md @@ -27,9 +27,17 @@ Once a bot is registered, you can invite to a channel with `/invite @slackbotser ### Run Your Own -You can use the [sample application](sample_app) to bootstrap your project and start adding slack command handlers on top of this code. +You can use the [sample application](sample_app) to bootstrap your project and start adding slack command handlers on top of this code. A database is required to store teams. -Install [MongoDB](https://www.mongodb.org/downloads), required to store teams. We would like your help with [supporting other databases](https://github.com/slack-ruby/slack-ruby-bot-server/issues/12). +### MongoDB + +Use MongoDB with [Mongoid](https://github.com/mongodb/mongoid) as ODM. Configure the database connection in `mongoid.yml`. See the [MongoDB example](sample_apps/sample_app_mongoid) for more information. + +### ActiveRecord + +Use ActiveRecord with, for example, PostgreSQL via [pg](https://github.com/ged/ruby-pg). Configure the database connection in `postgresql.yml`. See the [ActiveRecord example](sample_apps/sample_app_activerecord) for more information. + +### Usage [Create a New Application](https://api.slack.com/applications/new) on Slack. diff --git a/lib/slack-ruby-bot-server.rb b/lib/slack-ruby-bot-server.rb index 3d5f8b9..5e130f8 100644 --- a/lib/slack-ruby-bot-server.rb +++ b/lib/slack-ruby-bot-server.rb @@ -1,15 +1,16 @@ require 'celluloid/current' -require 'kaminari/grape' -require 'mongoid-scroll' + require 'grape-swagger' require 'slack-ruby-bot' +require 'slack-ruby-bot-server/server' +require 'slack-ruby-bot-server/config' require 'slack-ruby-bot-server/ext' require 'slack-ruby-bot-server/version' require 'slack-ruby-bot-server/info' -require 'slack-ruby-bot-server/models' + +require "slack-ruby-bot-server/config/database_adapters/#{SlackRubyBotServer::Config.database_adapter}.rb" + require 'slack-ruby-bot-server/api' require 'slack-ruby-bot-server/app' -require 'slack-ruby-bot-server/server' -require 'slack-ruby-bot-server/config' require 'slack-ruby-bot-server/service' diff --git a/lib/slack-ruby-bot-server/api/endpoints/teams_endpoint.rb b/lib/slack-ruby-bot-server/api/endpoints/teams_endpoint.rb index 9e6f8f3..b1d6e41 100644 --- a/lib/slack-ruby-bot-server/api/endpoints/teams_endpoint.rb +++ b/lib/slack-ruby-bot-server/api/endpoints/teams_endpoint.rb @@ -26,7 +26,7 @@ class TeamsEndpoint < Grape::API get do teams = Team.all teams = teams.active if params[:active] - teams = paginate_and_sort_by_cursor(teams, default_sort_order: '-_id') + teams = paginate_and_sort_by_cursor(teams, default_sort_order: '-id') present teams, with: Presenters::TeamsPresenter end diff --git a/lib/slack-ruby-bot-server/api/helpers/cursor_helpers.rb b/lib/slack-ruby-bot-server/api/helpers/cursor_helpers.rb index 060b01f..d914639 100644 --- a/lib/slack-ruby-bot-server/api/helpers/cursor_helpers.rb +++ b/lib/slack-ruby-bot-server/api/helpers/cursor_helpers.rb @@ -8,28 +8,41 @@ module CursorHelpers # returns a hash: # results: (paginated collection subset) # next: (cursor to the next page) - def paginate_by_cursor(coll, &_block) - raise 'Both cursor and offset parameters are present, these are mutually exclusive.' if params.key?(:offset) && params.key?(:cursor) - results = { results: [], next: nil } - size = (params[:size] || 10).to_i - if params.key?(:offset) - skip = params[:offset].to_i - coll = coll.skip(skip) + if SlackRubyBotServer::Config.mongoid? + def paginate_by_cursor(coll, _options) + raise 'Both cursor and offset parameters are present, these are mutually exclusive.' if params.key?(:offset) && params.key?(:cursor) + results = { results: [], next: nil } + coll = coll.skip(params[:offset].to_i) if params.key?(:offset) + size = (params[:size] || 10).to_i + coll = coll.limit(size) + coll.scroll(params[:cursor]) do |record, next_cursor| + results[:results] << record if record + results[:next] = next_cursor.to_s + break if results[:results].count >= size + end + results[:total_count] = coll.count if params[:total_count] && coll.respond_to?(:count) + results end - # some items may be skipped with a block - query = block_given? ? coll : coll.limit(size) - query.scroll(params[:cursor]) do |record, next_cursor| - record = yield(record) if block_given? - results[:results] << record if record - results[:next] = next_cursor.to_s - break if results[:results].count >= size + elsif SlackRubyBotServer::Config.activerecord? + def paginate_by_cursor(coll, options) + raise 'Both cursor and offset parameters are present, these are mutually exclusive.' if params.key?(:offset) && params.key?(:cursor) + results = { results: [], next: nil } + size = (params[:size] || 10).to_i + results[:total_count] = coll.count(:all) if params[:total_count] + coll = coll.offset(params[:offset].to_i) if params.key?(:offset) + sort_options = {} + sort_order(options).each do |order| + sort_options[order[:column]] = { reverse: true } if order[:direction] == :desc + end + coll = coll.cursor(params[:cursor], columns: sort_options).per(size) + results[:results] = coll.to_a + results[:next] = coll.next_cursor.to_s unless coll.last_page? + results end - results[:total_count] = coll.count if params[:total_count] && coll.respond_to?(:count) - results end - def paginate_and_sort_by_cursor(coll, options = {}, &block) - Hashie::Mash.new(paginate_by_cursor(sort(coll, options), &block)) + def paginate_and_sort_by_cursor(coll, options = {}) + Hashie::Mash.new(paginate_by_cursor(sort(coll, options), options)) end end end diff --git a/lib/slack-ruby-bot-server/api/helpers/error_helpers.rb b/lib/slack-ruby-bot-server/api/helpers/error_helpers.rb index 4e93b46..2f12606 100644 --- a/lib/slack-ruby-bot-server/api/helpers/error_helpers.rb +++ b/lib/slack-ruby-bot-server/api/helpers/error_helpers.rb @@ -13,16 +13,18 @@ module ErrorHelpers rack_response(error.to_json, 400) end # rescue document validation errors into detail json - rescue_from Mongoid::Errors::Validations do |e| - backtrace = e.backtrace[0..5].join("\n ") - Middleware.logger.warn "#{e.class.name}: #{e.message}\n #{backtrace}" - rack_response({ - type: 'param_error', - message: e.document.errors.full_messages.uniq.join(', ') + '.', - detail: e.document.errors.messages.each_with_object({}) do |(k, v), h| - h[k] = v.uniq - end - }.to_json, 400) + if SlackRubyBotServer::Config.mongoid? + rescue_from Mongoid::Errors::Validations do |e| + backtrace = e.backtrace[0..5].join("\n ") + Middleware.logger.warn "#{e.class.name}: #{e.message}\n #{backtrace}" + rack_response({ + type: 'param_error', + message: e.document.errors.full_messages.uniq.join(', ') + '.', + detail: e.document.errors.messages.each_with_object({}) do |(k, v), h| + h[k] = v.uniq + end + }.to_json, 400) + end end rescue_from Grape::Exceptions::Validation do |e| backtrace = e.backtrace[0..5].join("\n ") diff --git a/lib/slack-ruby-bot-server/api/helpers/sort_helpers.rb b/lib/slack-ruby-bot-server/api/helpers/sort_helpers.rb index 5e5a2f8..cde680d 100644 --- a/lib/slack-ruby-bot-server/api/helpers/sort_helpers.rb +++ b/lib/slack-ruby-bot-server/api/helpers/sort_helpers.rb @@ -37,7 +37,11 @@ def route_sort def sort(coll, options = {}) sort_order = sort_order(options) unless sort_order.empty? - if coll.respond_to?(:asc) && coll.respond_to?(:desc) + if coll.respond_to?(:order) + sort_order.each do |s| + coll = coll.order(s[:column] => s[:direction]) + end + elsif coll.respond_to?(:asc) && coll.respond_to?(:desc) sort_order.each do |s| coll = coll.send(s[:direction], s[:column]) end diff --git a/lib/slack-ruby-bot-server/api/middleware.rb b/lib/slack-ruby-bot-server/api/middleware.rb index 4aececf..00f7bc0 100644 --- a/lib/slack-ruby-bot-server/api/middleware.rb +++ b/lib/slack-ruby-bot-server/api/middleware.rb @@ -1,4 +1,7 @@ -%w(rack/cors rack-rewrite rack-server-pages).each { |l| require l } +require 'rack/cors' +require 'rack-rewrite' +require 'rack-server-pages' +require 'otr-activerecord' if SlackRubyBotServer::Config.activerecord? module SlackRubyBotServer module Api @@ -12,6 +15,8 @@ def self.logger def self.instance @instance ||= Rack::Builder.new do + use OTR::ActiveRecord::ConnectionManagement if SlackRubyBotServer::Config.activerecord? + use Rack::Cors do allow do origins '*' diff --git a/lib/slack-ruby-bot-server/api/presenters/status_presenter.rb b/lib/slack-ruby-bot-server/api/presenters/status_presenter.rb index 75b8d97..fe4651a 100644 --- a/lib/slack-ruby-bot-server/api/presenters/status_presenter.rb +++ b/lib/slack-ruby-bot-server/api/presenters/status_presenter.rb @@ -15,7 +15,13 @@ module StatusPresenter property :ping def ping - team = Team.asc(:_id).first + if SlackRubyBotServer::Config.mongoid? + team = Team.asc(:_id).first + elsif SlackRubyBotServer::Config.activerecord? + team = Team.last + else + raise 'Unsupported database driver.' + end return unless team team.ping! end diff --git a/lib/slack-ruby-bot-server/app.rb b/lib/slack-ruby-bot-server/app.rb index 7a802c7..22aaed7 100644 --- a/lib/slack-ruby-bot-server/app.rb +++ b/lib/slack-ruby-bot-server/app.rb @@ -1,10 +1,8 @@ module SlackRubyBotServer class App def prepare! - silence_loggers! - check_mongodb_provider! check_database! - create_indexes! + init_database! mark_teams_active! migrate_from_single_team! update_team_name_and_id! @@ -25,29 +23,12 @@ def logger end end - def silence_loggers! - Mongoid.logger.level = Logger::INFO - Mongo::Logger.logger.level = Logger::INFO - end - - def check_mongodb_provider! - return unless ENV['RACK_ENV'] == 'production' - unless ENV['MONGO_URL'] || ENV['MONGOHQ_URI'] || ENV['MONGODB_URI'] || ENV['MONGOLAB_URI'] - raise "Missing ENV['MONGO_URL'], ENV['MONGOHQ_URI'], ENV['MONGODB_URI'], or ENV['MONGOLAB_URI']." - end - end - def check_database! - rc = Mongoid.default_client.command(ping: 1) - return if rc && rc.ok? - raise rc.documents.first['error'] || 'Unexpected error.' - rescue Exception => e - warn "Error connecting to MongoDB: #{e.message}" - raise e + SlackRubyBotServer::DatabaseAdapter.check! end - def create_indexes! - ::Mongoid::Tasks::Database.create_indexes + def init_database! + SlackRubyBotServer::DatabaseAdapter.init! end def mark_teams_active! diff --git a/lib/slack-ruby-bot-server/config.rb b/lib/slack-ruby-bot-server/config.rb index c1059c9..827b85e 100644 --- a/lib/slack-ruby-bot-server/config.rb +++ b/lib/slack-ruby-bot-server/config.rb @@ -3,9 +3,25 @@ module Config extend self attr_accessor :server_class + attr_accessor :database_adapter def reset! self.server_class = SlackRubyBotServer::Server + self.database_adapter = if defined?(::Mongoid) + :mongoid + elsif defined?(::ActiveRecord) + :activerecord + else + raise 'One of "mongoid" or "activerecord" is required.' + end + end + + def activerecord? + database_adapter == :activerecord + end + + def mongoid? + database_adapter == :mongoid end reset! diff --git a/lib/slack-ruby-bot-server/config/database_adapters/activerecord.rb b/lib/slack-ruby-bot-server/config/database_adapters/activerecord.rb new file mode 100644 index 0000000..a760341 --- /dev/null +++ b/lib/slack-ruby-bot-server/config/database_adapters/activerecord.rb @@ -0,0 +1,27 @@ +require 'slack-ruby-bot-server/models/team/activerecord.rb' + +module SlackRubyBotServer + module DatabaseAdapter + def self.check! + ActiveRecord::Base.connection_pool.with_connection(&:active?) + raise 'Unexpected error.' unless ActiveRecord::Base.connected? + rescue StandardError => e + warn "Error connecting to PostgreSQL: #{e.message}" + raise e + end + + def self.init! + return if ActiveRecord::Base.connection.tables.include?('teams') + ActiveRecord::Base.connection.create_table :teams do |t| + t.string :team_id + t.string :name + t.string :domain + t.string :token + t.boolean :active, default: true + t.timestamps + end + end + end +end + +::Boolean = Virtus::Attribute::Boolean diff --git a/lib/slack-ruby-bot-server/config/database_adapters/mongoid.rb b/lib/slack-ruby-bot-server/config/database_adapters/mongoid.rb new file mode 100644 index 0000000..717ba9c --- /dev/null +++ b/lib/slack-ruby-bot-server/config/database_adapters/mongoid.rb @@ -0,0 +1,24 @@ +require 'slack-ruby-bot-server/models/team/mongoid.rb' +require 'kaminari/grape' +require 'mongoid-scroll' + +module SlackRubyBotServer + module DatabaseAdapter + def self.check! + rc = Mongoid.default_client.command(ping: 1) + return if rc && rc.ok? + raise rc.documents.first['error'] || 'Unexpected error.' + rescue StandardError => e + warn "Error connecting to MongoDB: #{e.message}" + raise e + end + + def self.init! + # create indexes + ::Mongoid::Tasks::Database.create_indexes + # silence loggers + Mongoid.logger.level = Logger::INFO + Mongo::Logger.logger.level = Logger::INFO + end + end +end diff --git a/lib/slack-ruby-bot-server/models/team.rb b/lib/slack-ruby-bot-server/models/team.rb deleted file mode 100644 index cd28503..0000000 --- a/lib/slack-ruby-bot-server/models/team.rb +++ /dev/null @@ -1,68 +0,0 @@ -class Team - include Mongoid::Document - include Mongoid::Timestamps - - SORT_ORDERS = ['created_at', '-created_at', 'updated_at', '-updated_at'].freeze - - field :team_id, type: String - field :name, type: String - field :domain, type: String - field :token, type: String - field :active, type: Boolean, default: true - - attr_accessor :server # server at runtime - - scope :active, -> { where(active: true) } - - validates_uniqueness_of :token, message: 'has already been used' - validates_presence_of :token - validates_presence_of :team_id - - def deactivate! - update_attributes!(active: false) - end - - def activate!(token) - update_attributes!(active: true, token: token) - end - - def to_s - { - name: name, - domain: domain, - id: team_id - }.map do |k, v| - "#{k}=#{v}" if v - end.compact.join(', ') - end - - def ping! - client = Slack::Web::Client.new(token: token) - auth = client.auth_test - { - auth: auth, - presence: client.users_getPresence(user: auth['user_id']) - } - end - - def self.find_or_create_from_env! - token = ENV['SLACK_API_TOKEN'] - return unless token - team = Team.where(token: token).first - team ||= Team.new(token: token) - info = Slack::Web::Client.new(token: token).team_info - team.team_id = info['team']['id'] - team.name = info['team']['name'] - team.domain = info['team']['domain'] - team.save! - team - end - - def self.purge! - # destroy teams inactive for two weeks - Team.where(active: false, :updated_at.lte => 2.weeks.ago).each do |team| - Mongoid.logger.info "Destroying #{team}, inactive since #{team.updated_at}, over two weeks ago." - team.destroy - end - end -end diff --git a/lib/slack-ruby-bot-server/models/team/activerecord.rb b/lib/slack-ruby-bot-server/models/team/activerecord.rb new file mode 100644 index 0000000..7e41015 --- /dev/null +++ b/lib/slack-ruby-bot-server/models/team/activerecord.rb @@ -0,0 +1,13 @@ +require_relative 'methods' + +class Team < ActiveRecord::Base + include Methods + + def self.purge! + # destroy teams inactive for two weeks + Team.where(active: false).where('updated_at <= ?', 2.weeks.ago).each do |team| + puts "Destroying #{team}, inactive since #{team.updated_at}, over two weeks ago." + team.destroy + end + end +end diff --git a/lib/slack-ruby-bot-server/models/team/methods.rb b/lib/slack-ruby-bot-server/models/team/methods.rb new file mode 100644 index 0000000..f3679f9 --- /dev/null +++ b/lib/slack-ruby-bot-server/models/team/methods.rb @@ -0,0 +1,55 @@ +module Methods + extend ActiveSupport::Concern + + included do + attr_accessor :server # server at runtime + + SORT_ORDERS = ['created_at', '-created_at', 'updated_at', '-updated_at'].freeze + + scope :active, -> { where(active: true) } + + validates_uniqueness_of :token, message: 'has already been used' + validates_presence_of :token + validates_presence_of :team_id + + def deactivate! + update_attributes!(active: false) + end + + def activate!(token) + update_attributes!(active: true, token: token) + end + + def to_s + { + name: name, + domain: domain, + id: team_id + }.map do |k, v| + "#{k}=#{v}" if v + end.compact.join(', ') + end + + def ping! + client = Slack::Web::Client.new(token: token) + auth = client.auth_test + { + auth: auth, + presence: client.users_getPresence(user: auth['user_id']) + } + end + + def self.find_or_create_from_env! + token = ENV['SLACK_API_TOKEN'] + return unless token + team = Team.where(token: token).first + team ||= Team.new(token: token) + info = Slack::Web::Client.new(token: token).team_info + team.team_id = info['team']['id'] + team.name = info['team']['name'] + team.domain = info['team']['domain'] + team.save! + team + end + end +end diff --git a/lib/slack-ruby-bot-server/models/team/mongoid.rb b/lib/slack-ruby-bot-server/models/team/mongoid.rb new file mode 100644 index 0000000..883032b --- /dev/null +++ b/lib/slack-ruby-bot-server/models/team/mongoid.rb @@ -0,0 +1,22 @@ +require_relative 'methods' + +class Team + include Mongoid::Document + include Mongoid::Timestamps + + field :team_id, type: String + field :name, type: String + field :domain, type: String + field :token, type: String + field :active, type: Boolean, default: true + + include Methods + + def self.purge! + # destroy teams inactive for two weeks + Team.where(active: false, :updated_at.lte => 2.weeks.ago).each do |team| + Mongoid.logger.info "Destroying #{team}, inactive since #{team.updated_at}, over two weeks ago." + team.destroy + end + end +end diff --git a/lib/slack-ruby-bot-server/version.rb b/lib/slack-ruby-bot-server/version.rb index 9323967..beb8d41 100644 --- a/lib/slack-ruby-bot-server/version.rb +++ b/lib/slack-ruby-bot-server/version.rb @@ -1,3 +1,3 @@ module SlackRubyBotServer - VERSION = '0.5.1'.freeze + VERSION = '0.6.0'.freeze end diff --git a/sample_app/.env b/sample_app/.env deleted file mode 100644 index 6b07bb2..0000000 --- a/sample_app/.env +++ /dev/null @@ -1,3 +0,0 @@ -SLACK_CLIENT_ID= -SLACK_CLIENT_SECRET= -PORT=9292 diff --git a/sample_app/.rspec b/sample_apps/.rspec similarity index 100% rename from sample_app/.rspec rename to sample_apps/.rspec diff --git a/sample_app/Gemfile b/sample_apps/sample_app_activerecord/Gemfile similarity index 67% rename from sample_app/Gemfile rename to sample_apps/sample_app_activerecord/Gemfile index a90a0ec..bdb8470 100644 --- a/sample_app/Gemfile +++ b/sample_apps/sample_app_activerecord/Gemfile @@ -1,7 +1,10 @@ source 'https://rubygems.org' -gem 'slack-ruby-bot-server', path: '../' +gem 'slack-ruby-bot-server', path: '../../' gem 'newrelic-slack-ruby-bot' +gem 'rack-server-pages' +gem 'pg' +gem 'activerecord' group :test do gem 'rake' diff --git a/sample_app/Procfile b/sample_apps/sample_app_activerecord/Procfile similarity index 100% rename from sample_app/Procfile rename to sample_apps/sample_app_activerecord/Procfile diff --git a/sample_app/Rakefile b/sample_apps/sample_app_activerecord/Rakefile similarity index 100% rename from sample_app/Rakefile rename to sample_apps/sample_app_activerecord/Rakefile diff --git a/sample_app/commands.rb b/sample_apps/sample_app_activerecord/commands.rb similarity index 100% rename from sample_app/commands.rb rename to sample_apps/sample_app_activerecord/commands.rb diff --git a/sample_app/commands/help.rb b/sample_apps/sample_app_activerecord/commands/help.rb similarity index 100% rename from sample_app/commands/help.rb rename to sample_apps/sample_app_activerecord/commands/help.rb diff --git a/sample_app/commands/whoami.rb b/sample_apps/sample_app_activerecord/commands/whoami.rb similarity index 100% rename from sample_app/commands/whoami.rb rename to sample_apps/sample_app_activerecord/commands/whoami.rb diff --git a/sample_apps/sample_app_activerecord/config.ru b/sample_apps/sample_app_activerecord/config.ru new file mode 100644 index 0000000..dfe10ec --- /dev/null +++ b/sample_apps/sample_app_activerecord/config.ru @@ -0,0 +1,21 @@ +ENV['RACK_ENV'] ||= 'development' + +Bundler.require :default + +require_relative 'commands' +require 'yaml' + +ActiveRecord::Base.establish_connection(YAML.load_file('config/postgresql.yml')[ENV['RACK_ENV']]) + +if ENV['RACK_ENV'] == 'development' + puts 'Loading NewRelic in developer mode ...' + require 'new_relic/rack/developer_mode' + use NewRelic::Rack::DeveloperMode +end + +NewRelic::Agent.manual_start + +SlackRubyBotServer::App.instance.prepare! +SlackRubyBotServer::Service.start! + +run SlackRubyBotServer::Api::Middleware.instance diff --git a/sample_app/config/newrelic.yml b/sample_apps/sample_app_activerecord/config/newrelic.yml similarity index 100% rename from sample_app/config/newrelic.yml rename to sample_apps/sample_app_activerecord/config/newrelic.yml diff --git a/sample_apps/sample_app_activerecord/config/postgresql.yml b/sample_apps/sample_app_activerecord/config/postgresql.yml new file mode 100644 index 0000000..ab42837 --- /dev/null +++ b/sample_apps/sample_app_activerecord/config/postgresql.yml @@ -0,0 +1,22 @@ +default: &default + adapter: postgresql + pool: 10 + timeout: 5000 + encoding: unicode + +development: + <<: *default + database: slack_ruby_bot_server_development + username: slack_ruby_bot_server + password: + host: localhost + port: 5432 + + +test: + <<: *default + database: slack_ruby_bot_server_test + +production: + <<: *default + database: slack_ruby_bot_server_production diff --git a/sample_app/spec/commands/help_spec.rb b/sample_apps/sample_app_activerecord/spec/commands/help_spec.rb similarity index 100% rename from sample_app/spec/commands/help_spec.rb rename to sample_apps/sample_app_activerecord/spec/commands/help_spec.rb diff --git a/sample_app/spec/commands/whoami_spec.rb b/sample_apps/sample_app_activerecord/spec/commands/whoami_spec.rb similarity index 100% rename from sample_app/spec/commands/whoami_spec.rb rename to sample_apps/sample_app_activerecord/spec/commands/whoami_spec.rb diff --git a/sample_apps/sample_app_activerecord/spec/spec_helper.rb b/sample_apps/sample_app_activerecord/spec/spec_helper.rb new file mode 100644 index 0000000..cc41539 --- /dev/null +++ b/sample_apps/sample_app_activerecord/spec/spec_helper.rb @@ -0,0 +1,13 @@ +$LOAD_PATH.unshift File.expand_path('..', __dir__) + +ENV['RACK_ENV'] = 'test' + +require 'slack-ruby-bot-server/rspec' + +RSpec.configure do |config| + config.around :each do |example| + DatabaseCleaner.cleaning do + example.run + end + end +end diff --git a/sample_apps/sample_app_mongoid/Gemfile b/sample_apps/sample_app_mongoid/Gemfile new file mode 100644 index 0000000..1e89db1 --- /dev/null +++ b/sample_apps/sample_app_mongoid/Gemfile @@ -0,0 +1,18 @@ +source 'https://rubygems.org' + +gem 'slack-ruby-bot-server', path: '../../' +gem 'newrelic-slack-ruby-bot' + +gem 'mongoid' +gem 'kaminari-mongoid' +gem 'mongoid-scroll' + +group :test do + gem 'rake' + gem 'rspec' + gem 'fabrication' + gem 'faker' + gem 'vcr' + gem 'webmock' + gem 'database_cleaner' +end diff --git a/sample_apps/sample_app_mongoid/Procfile b/sample_apps/sample_app_mongoid/Procfile new file mode 100644 index 0000000..5784a17 --- /dev/null +++ b/sample_apps/sample_app_mongoid/Procfile @@ -0,0 +1 @@ +web: bundle exec unicorn -p $PORT diff --git a/sample_app/README.md b/sample_apps/sample_app_mongoid/README.md similarity index 100% rename from sample_app/README.md rename to sample_apps/sample_app_mongoid/README.md diff --git a/sample_apps/sample_app_mongoid/Rakefile b/sample_apps/sample_app_mongoid/Rakefile new file mode 100644 index 0000000..9bad493 --- /dev/null +++ b/sample_apps/sample_app_mongoid/Rakefile @@ -0,0 +1,10 @@ +require 'rubygems' + +require 'rspec/core' +require 'rspec/core/rake_task' + +RSpec::Core::RakeTask.new(:spec) do |spec| + spec.pattern = FileList['spec/**/*_spec.rb'] +end + +task default: [:spec] diff --git a/sample_apps/sample_app_mongoid/commands.rb b/sample_apps/sample_app_mongoid/commands.rb new file mode 100644 index 0000000..0b84935 --- /dev/null +++ b/sample_apps/sample_app_mongoid/commands.rb @@ -0,0 +1,2 @@ +require_relative 'commands/help' +require_relative 'commands/whoami' diff --git a/sample_apps/sample_app_mongoid/commands/help.rb b/sample_apps/sample_app_mongoid/commands/help.rb new file mode 100644 index 0000000..3f8b652 --- /dev/null +++ b/sample_apps/sample_app_mongoid/commands/help.rb @@ -0,0 +1,19 @@ +class Help < SlackRubyBot::Commands::Base + HELP = <<-EOS.freeze +``` +I am your friendly slack-ruby-bot-server, here to help. + +General +------- + +help - get this helpful message +whoami - print your username + +``` +EOS + def self.call(client, data, _match) + client.say(channel: data.channel, text: [HELP, SlackRubyBotServer::INFO].join("\n")) + client.say(channel: data.channel, gif: 'help') + logger.info "HELP: #{client.owner}, user=#{data.user}" + end +end diff --git a/sample_apps/sample_app_mongoid/commands/whoami.rb b/sample_apps/sample_app_mongoid/commands/whoami.rb new file mode 100644 index 0000000..d111f4d --- /dev/null +++ b/sample_apps/sample_app_mongoid/commands/whoami.rb @@ -0,0 +1,6 @@ +class Whoami < SlackRubyBot::Commands::Base + def self.call(client, data, _match) + client.say(channel: data.channel, text: "<@#{data.user}>") + logger.info "UNAME: #{client.owner}, user=#{data.user}" + end +end diff --git a/sample_app/config.ru b/sample_apps/sample_app_mongoid/config.ru similarity index 100% rename from sample_app/config.ru rename to sample_apps/sample_app_mongoid/config.ru diff --git a/sample_app/config/mongoid.yml b/sample_apps/sample_app_mongoid/config/mongoid.yml similarity index 100% rename from sample_app/config/mongoid.yml rename to sample_apps/sample_app_mongoid/config/mongoid.yml diff --git a/sample_apps/sample_app_mongoid/config/newrelic.yml b/sample_apps/sample_app_mongoid/config/newrelic.yml new file mode 100644 index 0000000..eb91df8 --- /dev/null +++ b/sample_apps/sample_app_mongoid/config/newrelic.yml @@ -0,0 +1,217 @@ +# Here are the settings that are common to all environments +common: &default_settings + # ============================== LICENSE KEY =============================== + + # You must specify the license key associated with your New Relic + # account. This key binds your Agent's data to your account in the + # New Relic service. + license_key: '<%= ENV["NEW_RELIC_LICENSE_KEY"] %>' + + # Application Name Set this to be the name of your application as + # you'd like it show up in New Relic. The service will then auto-map + # instances of your application into an "application" on your + # dashboard page. If you want to map this instance into multiple + # apps, like "AJAX Requests" and "All UI" then specify a semicolon + # separated list of up to three distinct names, or a yaml list. + app_name: <%= ENV["NEW_RELIC_APP_NAME"] || 'SlackRubyBotServer' %> + + # When "true", the agent collects performance data about your + # application and reports this data to the New Relic service at + # newrelic.com. This global switch is normally overridden for each + # environment below. (formerly called 'enabled') + monitor_mode: true + + # Developer mode should be off in every environment but + # development as it has very high overhead in memory. + developer_mode: false + + # The newrelic agent generates its own log file to keep its logging + # information separate from that of your application. Specify its + # log level here. + log_level: info + + # Optionally set the path to the log file This is expanded from the + # root directory (may be relative or absolute, e.g. 'log/' or + # '/var/log/') The agent will attempt to create this directory if it + # does not exist. + # log_file_path: 'log' + + # Optionally set the name of the log file, defaults to 'newrelic_agent.log' + # log_file_name: 'newrelic_agent.log' + + # The newrelic agent communicates with the service via http by + # default. If you want to communicate via https to increase + # security, then turn on SSL by setting this value to true. Note, + # this will result in increased CPU overhead to perform the + # encryption involved in SSL communication, but this work is done + # asynchronously to the threads that process your application code, + # so it should not impact response times. + ssl: false + + # EXPERIMENTAL: enable verification of the SSL certificate sent by + # the server. This setting has no effect unless SSL is enabled + # above. This may block your application. Only enable it if the data + # you send us needs end-to-end verified certificates. + # + # This means we cannot cache the DNS lookup, so each request to the + # service will perform a lookup. It also means that we cannot + # use a non-blocking lookup, so in a worst case, if you have DNS + # problems, your app may block indefinitely. + # verify_certificate: true + + # Set your application's Apdex threshold value with the 'apdex_t' + # setting, in seconds. The apdex_t value determines the buckets used + # to compute your overall Apdex score. + # Requests that take less than apdex_t seconds to process will be + # classified as Satisfying transactions; more than apdex_t seconds + # as Tolerating transactions; and more than four times the apdex_t + # value as Frustrating transactions. + # For more about the Apdex standard, see + # http://newrelic.com/docs/general/apdex + + apdex_t: 0.5 + + #============================== Browser Monitoring =============================== + # New Relic Real User Monitoring gives you insight into the performance real users are + # experiencing with your website. This is accomplished by measuring the time it takes for + # your users' browsers to download and render your web pages by injecting a small amount + # of JavaScript code into the header and footer of each page. + browser_monitoring: + # By default the agent automatically injects the monitoring JavaScript + # into web pages. Set this attribute to false to turn off this behavior. + auto_instrument: true + + # Proxy settings for connecting to the service. + # + # If a proxy is used, the host setting is required. Other settings + # are optional. Default port is 8080. + # + # proxy_host: hostname + # proxy_port: 8080 + # proxy_user: + # proxy_pass: + + + # Tells transaction tracer and error collector (when enabled) + # whether or not to capture HTTP params. When true, frameworks can + # exclude HTTP parameters from being captured. + # Rails: the RoR filter_parameter_logging excludes parameters + # Java: create a config setting called "ignored_params" and set it to + # a comma separated list of HTTP parameter names. + # ex: ignored_params: credit_card, ssn, password + capture_params: true + + + # Transaction tracer captures deep information about slow + # transactions and sends this to the service once a + # minute. Included in the transaction is the exact call sequence of + # the transactions including any SQL statements issued. + transaction_tracer: + + # Transaction tracer is enabled by default. Set this to false to + # turn it off. This feature is only available at the Professional + # and above product levels. + enabled: true + + # Threshold in seconds for when to collect a transaction + # trace. When the response time of a controller action exceeds + # this threshold, a transaction trace will be recorded and sent to + # the service. Valid values are any float value, or (default) + # "apdex_f", which will use the threshold for an dissatisfying + # Apdex controller action - four times the Apdex T value. + transaction_threshold: apdex_f + + # When transaction tracer is on, SQL statements can optionally be + # recorded. The recorder has three modes, "off" which sends no + # SQL, "raw" which sends the SQL statement in its original form, + # and "obfuscated", which strips out numeric and string literals + record_sql: obfuscated + + # Threshold in seconds for when to collect stack trace for a SQL + # call. In other words, when SQL statements exceed this threshold, + # then capture and send the current stack trace. This is + # helpful for pinpointing where long SQL calls originate from + stack_trace_threshold: 0.500 + + # Determines whether the agent will capture query plans for slow + # SQL queries. Only supported in mysql and postgres. Should be + # set to false when using other adapters. + # explain_enabled: true + + # Threshold for query execution time below which query plans will not + # not be captured. Relevant only when `explain_enabled` is true. + # explain_threshold: 0.5 + + # Error collector captures information about uncaught exceptions and + # sends them to the service for viewing + error_collector: + + # Error collector is enabled by default. Set this to false to turn + # it off. This feature is only available at the Professional and above + # product levels + enabled: true + + # Rails Only - tells error collector whether or not to capture a + # source snippet around the place of the error when errors are View + # related. + capture_source: true + + # To stop specific errors from reporting to New Relic, set this property + # to comma separated values. Default is to ignore routing errors + # which are how 404's get triggered. + # + ignore_errors: ActionController::RoutingError + + # (Advanced) Uncomment this to ensure the cpu and memory samplers + # won't run. Useful when you are using the agent to monitor an + # external resource + # disable_samplers: true + + # If you aren't interested in visibility in these areas, you can + # disable the instrumentation to reduce overhead. + # + # disable_view_instrumentation: true + # disable_activerecord_instrumentation: true + # disable_memcache_instrumentation: true + # disable_dj: true + + # If you're interested in capturing memcache keys as though they + # were SQL uncomment this flag. Note that this does increase + # overhead slightly on every memcached call, and can have security + # implications if your memcached keys are sensitive + # capture_memcache_keys: true + + # Certain types of instrumentation such as GC stats will not work if + # you are running multi-threaded. Please let us know. + # multi_threaded = false + +# Application Environments +# ------------------------------------------ + +development: + <<: *default_settings + # Turn off communication to New Relic service in development mode (also + # 'enabled'). + # NOTE: for initial evaluation purposes, you may want to temporarily + # turn the agent on in development mode. + monitor_mode: false + + # Rails Only - when running in Developer Mode, the New Relic Agent will + # present performance information on the last 100 transactions you have + # executed since starting the mongrel. + # NOTE: There is substantial overhead when running in developer mode. + # Do not use for production or load testing. + developer_mode: true + + # Enable textmate links + # textmate: true + +test: + <<: *default_settings + # It almost never makes sense to turn on the agent when running + # unit, functional or integration tests or the like. + monitor_mode: false + +production: + <<: *default_settings + monitor_mode: true diff --git a/sample_apps/sample_app_mongoid/spec/commands/help_spec.rb b/sample_apps/sample_app_mongoid/spec/commands/help_spec.rb new file mode 100644 index 0000000..a8d8914 --- /dev/null +++ b/sample_apps/sample_app_mongoid/spec/commands/help_spec.rb @@ -0,0 +1,14 @@ +require 'spec_helper' +require 'commands/help' + +describe Help do + let!(:team) { Fabricate(:team) } + let(:app) { SlackRubyBotServer::Server.new(team: team) } + let(:client) { app.send(:client) } + let(:message_hook) { SlackRubyBot::Hooks::Message.new } + it 'default' do + expect(client).to receive(:say).with(channel: 'channel', text: [Help::HELP, SlackRubyBotServer::INFO].join("\n")) + expect(client).to receive(:say).with(channel: 'channel', gif: 'help') + message_hook.call(client, Hashie::Mash.new(channel: 'channel', text: "#{SlackRubyBot.config.user} help")) + end +end diff --git a/sample_apps/sample_app_mongoid/spec/commands/whoami_spec.rb b/sample_apps/sample_app_mongoid/spec/commands/whoami_spec.rb new file mode 100644 index 0000000..757a592 --- /dev/null +++ b/sample_apps/sample_app_mongoid/spec/commands/whoami_spec.rb @@ -0,0 +1,14 @@ +require 'spec_helper' +require 'commands/whoami' + +describe Whoami do + let(:team) { Fabricate(:team) } + let(:app) { SlackRubyBotServer::Server.new(team: team) } + context 'whoami' do + it 'returns username' do + expect(message: "#{SlackRubyBot.config.user} whoami", channel: 'channel', user: 'user').to respond_with_slack_message( + '<@user>' + ) + end + end +end diff --git a/sample_app/spec/spec_helper.rb b/sample_apps/sample_app_mongoid/spec/spec_helper.rb similarity index 100% rename from sample_app/spec/spec_helper.rb rename to sample_apps/sample_app_mongoid/spec/spec_helper.rb diff --git a/slack-ruby-bot-server.gemspec b/slack-ruby-bot-server.gemspec index 8a98525..058b1b9 100644 --- a/slack-ruby-bot-server.gemspec +++ b/slack-ruby-bot-server.gemspec @@ -17,7 +17,6 @@ Gem::Specification.new do |spec| spec.add_dependency 'slack-ruby-bot' spec.add_dependency 'celluloid-io' - spec.add_dependency 'mongoid' spec.add_dependency 'unicorn' spec.add_dependency 'grape' spec.add_dependency 'grape-swagger' diff --git a/spec/api/endpoints/teams_endpoint_spec.rb b/spec/api/endpoints/teams_endpoint_spec.rb index dfbb8af..79288bc 100644 --- a/spec/api/endpoints/teams_endpoint_spec.rb +++ b/spec/api/endpoints/teams_endpoint_spec.rb @@ -9,7 +9,7 @@ let(:existing_team) { Fabricate(:team) } it 'returns a team' do team = client.team(id: existing_team.id) - expect(team.id).to eq existing_team.id.to_s + expect(team.id.to_s).to eq existing_team.id.to_s expect(team._links.self._url).to eq "http://example.org/api/teams/#{existing_team.id}" end end @@ -34,7 +34,7 @@ let(:existing_team) { Fabricate(:team) } it 'returns a team' do team = client.team(id: existing_team.id) - expect(team.id).to eq existing_team.id.to_s + expect(team.id.to_s).to eq existing_team.id.to_s end it 'requires code' do diff --git a/spec/database_adapters/activerecord/activerecord.rb b/spec/database_adapters/activerecord/activerecord.rb new file mode 100644 index 0000000..e4cc87b --- /dev/null +++ b/spec/database_adapters/activerecord/activerecord.rb @@ -0,0 +1,3 @@ +db_config = YAML.load(File.read(File.expand_path('../../../sample_apps/sample_app_activerecord/config/postgresql.yml', __dir__)))[ENV['RACK_ENV']] +ActiveRecord::Tasks::DatabaseTasks.create(db_config) +ActiveRecord::Base.establish_connection(db_config) diff --git a/spec/database_adapters/activerecord/schema.rb b/spec/database_adapters/activerecord/schema.rb new file mode 100644 index 0000000..a28e2fa --- /dev/null +++ b/spec/database_adapters/activerecord/schema.rb @@ -0,0 +1,13 @@ +ActiveRecord::Schema.define do + self.verbose = false + + create_table :teams, force: true do |t| + t.string :team_id + t.string :name + t.boolean :active, default: true + t.string :domain + t.string :token + + t.timestamps + end +end diff --git a/spec/database_adapters/mongoid/mongoid.rb b/spec/database_adapters/mongoid/mongoid.rb new file mode 100644 index 0000000..166129a --- /dev/null +++ b/spec/database_adapters/mongoid/mongoid.rb @@ -0,0 +1,2 @@ +Mongo::Logger.logger.level = Logger::INFO +Mongoid.load!(File.expand_path('../../../sample_apps/sample_app_mongoid/config/mongoid.yml', __dir__), ENV['RACK_ENV']) diff --git a/spec/support/mongoid.rb b/spec/database_adapters/mongoid/rspec.rb similarity index 67% rename from spec/support/mongoid.rb rename to spec/database_adapters/mongoid/rspec.rb index de8200a..bda0cd5 100644 --- a/spec/support/mongoid.rb +++ b/spec/database_adapters/mongoid/rspec.rb @@ -2,4 +2,8 @@ config.before :suite do Mongoid::Tasks::Database.create_indexes end + + config.after :suite do + Mongoid.purge! + end end diff --git a/spec/models/team_spec.rb b/spec/models/team_spec.rb index 62ada79..6f8b2a4 100644 --- a/spec/models/team_spec.rb +++ b/spec/models/team_spec.rb @@ -29,11 +29,11 @@ expect do Team.purge! end.to change(Team, :count).by(-2) - expect(Team.find(active_team.id)).to eq active_team - expect(Team.find(inactive_team.id)).to eq inactive_team - expect(Team.find(inactive_team_a_week_ago.id)).to eq inactive_team_a_week_ago - expect(Team.find(inactive_team_two_weeks_ago.id)).to be nil - expect(Team.find(inactive_team_a_month_ago.id)).to be nil + expect(Team.where(id: active_team.id).first).to eq active_team + expect(Team.where(id: inactive_team.id).first).to eq inactive_team + expect(Team.where(id: inactive_team_a_week_ago.id).first).to eq inactive_team_a_week_ago + expect(Team.where(id: inactive_team_two_weeks_ago.id).first).to be nil + expect(Team.where(id: inactive_team_a_month_ago.id).first).to be nil end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e2bff5a..8502534 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,15 +1,18 @@ ENV['RACK_ENV'] = 'test' +ENV['DATABASE_ADAPTER'] ||= 'mongoid' + +Bundler.require require 'hyperclient' require 'webmock/rspec' - require 'slack-ruby-bot-server/rspec' -SlackRubyBotServer::Service.logger.level = Logger::WARN +Dir[File.join(__dir__, 'support', '**/*.rb')].each do |file| + require file +end -Mongo::Logger.logger.level = Logger::INFO -Mongoid.load!(File.expand_path('../sample_app/config/mongoid.yml', __dir__), ENV['RACK_ENV']) +SlackRubyBotServer::Service.logger.level = Logger::WARN -Dir[File.join(__dir__, 'support', '**/*.rb')].each do |file| +Dir[File.join(__dir__, 'database_adapters', SlackRubyBotServer::Config.database_adapter.to_s, '**/*.rb')].each do |file| require file end diff --git a/spec/support/api/endpoints/it_behaves_like_a_cursor_api.rb b/spec/support/api/endpoints/it_behaves_like_a_cursor_api.rb index bd3c619..60d2c3e 100644 --- a/spec/support/api/endpoints/it_behaves_like_a_cursor_api.rb +++ b/spec/support/api/endpoints/it_behaves_like_a_cursor_api.rb @@ -20,7 +20,11 @@ response = client.send(model_ps, cursor_params.merge(size: 2)) expect(response._links.self._url).to eq "http://example.org/api/#{model_ps}/?#{cursor_params.merge(size: 2).to_query}" expect(response._links.next._url).to start_with "http://example.org/api/#{model_ps}/?" - expect(response._links.next._url).to match(/cursor\=.*%3A\h*/) + if SlackRubyBotServer::Config.activerecord? + expect(response._links.next._url).to match(/cursor\=\h*/) + elsif SlackRubyBotServer::Config.mongoid? + expect(response._links.next._url).to match(/cursor\=.*%3A\h*/) + end end it 'paginates over the entire collection' do diff --git a/spec/support/database_cleaner.rb b/spec/support/database_cleaner.rb index 348130b..312b7b3 100644 --- a/spec/support/database_cleaner.rb +++ b/spec/support/database_cleaner.rb @@ -6,10 +6,6 @@ DatabaseCleaner.clean_with :truncation end - config.after :suite do - Mongoid.purge! - end - config.around :each do |example| DatabaseCleaner.cleaning do example.run