├── .gitignore ├── .rspec ├── Gemfile ├── Gemfile.lock ├── MIT-LICENSE ├── README.md ├── Rakefile ├── bin └── notify_me ├── lib ├── notifyor.rb └── notifyor │ ├── cli.rb │ ├── configuration.rb │ ├── growl.rb │ ├── growl │ └── adapters │ │ ├── libnotify_notifier.rb │ │ └── terminal_notifier.rb │ ├── plugin.rb │ ├── remote │ └── connection.rb │ ├── util │ ├── formatter.rb │ └── os_analyzer.rb │ └── version.rb ├── notifyor.gemspec └── spec └── spec_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | .bundle/ 2 | log/*.log 3 | pkg/ 4 | spec/test_app 5 | .idea 6 | .ruby-gemset 7 | .ruby-version 8 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --require spec_helper 3 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Declare your gem's dependencies in notifyor.gemspec. 4 | # Bundler will treat runtime dependencies like base dependencies, and 5 | # development dependencies will be added by default to the :development group. 6 | gemspec 7 | 8 | # Declare any dependencies that are still in development here instead of in 9 | # your gemspec. These might include edge Rails or gems from your path or 10 | # Git. Remember to move these dependencies to your gemspec before releasing 11 | # your gem to rubygems.org. 12 | 13 | # To use a debugger 14 | # gem 'byebug', group: [:development, :test] 15 | 16 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | notifyor (0.8.1) 5 | connection_pool 6 | net-ssh 7 | net-ssh-gateway 8 | redis 9 | terminal-notifier 10 | 11 | GEM 12 | remote: https://rubygems.org/ 13 | specs: 14 | connection_pool (2.2.0) 15 | diff-lcs (1.2.5) 16 | net-ssh (3.1.1) 17 | net-ssh-gateway (1.2.0) 18 | net-ssh (>= 2.6.5) 19 | redis (3.2.2) 20 | rspec (3.4.0) 21 | rspec-core (~> 3.4.0) 22 | rspec-expectations (~> 3.4.0) 23 | rspec-mocks (~> 3.4.0) 24 | rspec-core (3.4.4) 25 | rspec-support (~> 3.4.0) 26 | rspec-expectations (3.4.0) 27 | diff-lcs (>= 1.2.0, < 2.0) 28 | rspec-support (~> 3.4.0) 29 | rspec-mocks (3.4.1) 30 | diff-lcs (>= 1.2.0, < 2.0) 31 | rspec-support (~> 3.4.0) 32 | rspec-support (3.4.1) 33 | sqlite3 (1.3.11) 34 | terminal-notifier (1.6.3) 35 | 36 | PLATFORMS 37 | ruby 38 | 39 | DEPENDENCIES 40 | notifyor! 41 | rspec (~> 3.4.0) 42 | sqlite3 43 | 44 | BUNDLED WITH 45 | 1.11.2 46 | -------------------------------------------------------------------------------- /MIT-LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2016 Erwin Schens 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Notifyor 2 | ## [![](http://i.imgur.com/FrRacwt.png)]() 3 | Get realtime notifications (growl messages) on your desktop if something happens in your rails app. 4 | Notifyor publishes changes to a redis channel. Subscription is performed from your local machine via a ssh tunnel. 5 | 6 | Simply put: 7 | Very growl. Such notifications. Much Notifyor. 8 | 9 | ## Installation 10 | 11 | Add this line to your Gemfile: 12 | 13 | ```ruby 14 | gem 'notifyor', '~> 0.8.1' 15 | ``` 16 | 17 | Or install it via rubygems if you just need the CLI. 18 | 19 | ```bash 20 | gem install notifyor 21 | ``` 22 | 23 | And then execute: 24 | 25 | $ bundle install 26 | 27 | ## Getting started 28 | Run the bundle command to install it. 29 | After you install Notifyor create a new file **config/initializers/notifyor.rb** (a rails generator will be available soon for this task). Add the following content to your initializer. 30 | ```ruby 31 | Notifyor.configure do |config| 32 | #config.redis_connection = Redis.new 33 | end 34 | ``` 35 | 36 | ### Linux 37 | If you want to receive growl notifications on a linux system you have to install the *libnotify-bin*. 38 | 39 | ```bash 40 | sudo apt-get install libnotify-bin 41 | ``` 42 | 43 | ### Mac OS X 44 | Notifyor runs out of the box on Mac OS X. Lucky you. 45 | 46 | ### Windows 47 | Currently not supported (see roadmap) 48 | 49 | ## Usage 50 | 51 | ### Plugin 52 | Notifyor can be plugged into your models by adding the *notifyor* method to your class. 53 | ```ruby 54 | class SomeClass < ActiveRecord::Base 55 | notifyor 56 | end 57 | ``` 58 | By just including the method without options, notifyor will send notifications for the following events: *create*, *update* and *destroy*. The default message is the i18n key **notifyor.model.[create | update | destroy]** you have to provide in your application. 59 | If you want to customize this message you can provide the following option to the notifyor method: 60 | ```ruby 61 | class SomeClass < ActiveRecord::Base 62 | notifyor messages: { 63 | create: -> (model) { "My Message for model #{model.id}." }, 64 | update: -> (model) { "My Message for model #{model.id}." }, 65 | destroy: -> (model) { "My Message for model #{model.id}." } 66 | } 67 | end 68 | ``` 69 | 70 | If you dont want to receive a notification for a certain action just add the **only** option to notifyor. 71 | ```ruby 72 | class SomeClass < ActiveRecord::Base 73 | notifyor only: [:create] 74 | end 75 | ``` 76 | 77 | The default channel on which notifyor publishes messages is 'notifyor'. This can be changed via the **channel** option. 78 | You can provide multiple channels and notifyor will publish messages on them. (See the channel option on the CLI to subscribe to those channels). 79 | ```ruby 80 | class SomeClass < ActiveRecord::Base 81 | notifyor channels: ['channel1', 'channel2'] 82 | end 83 | ``` 84 | 85 | ### CLI 86 | The CLI can be used independently just install the gem and run following command. 87 | 88 | ```bash 89 | notify_me --ssh-host some_host --ssh-port some_port --ssh-user some_user 90 | ``` 91 | #### Arguments for the CLI 92 | - **ssh-host** Provide the ssh host to which notifyor should connect to. (Default is localhost) 93 | - **ssh-port** Provide the ssh port on which notifyor should connect to. (Default is 22) 94 | - **ssh-user** Provide the ssh user for your remote server. (Please use ssh keys so that you just have to provide the *ssh-host*. -> Security reasons) 95 | - **tunnel-port** The tunnel port on which ssh will establish the connection. (Default is 2000) 96 | - **redis-port** The port of your redis server (Default is 6379) 97 | - **channel** Listen on another channel. Every message received on this channel will be displayed in a growl notification. (Default is notifyor) 98 | 99 | **If you dont provide a ssh host notifyor will subscribe from your local redis and display them.** 100 | 101 | Every notify_me instance is an individual subscriber so multiple users can receive growl messages. 102 | 103 | ## Roadmap 104 | - Notifications for multiple OS (currently only Mac OS X and Linux systems with libnotify-lib installed.) 105 | - Provide own logo in the growl notification 106 | - Specs 107 | - Documentation 108 | 109 | ## Development 110 | 111 | After checking out the repo, run `bundle install` to install dependencies. 112 | 113 | To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). 114 | 115 | ## Contributing 116 | 117 | 1. Fork it ( https://github.com/[my-github-username]/notifyor/fork ) 118 | 2. Create your feature branch (`git checkout -b my-new-feature`) 119 | 3. Commit your changes (`git commit -am 'Add some feature'`) 120 | 4. Push to the branch (`git push origin my-new-feature`) 121 | 5. Create a new Pull Request 122 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 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 | require 'rdoc/task' 8 | 9 | RDoc::Task.new(:rdoc) do |rdoc| 10 | rdoc.rdoc_dir = 'rdoc' 11 | rdoc.title = 'Notifyor' 12 | rdoc.options << '--line-numbers' 13 | rdoc.rdoc_files.include('README.rdoc') 14 | rdoc.rdoc_files.include('lib/**/*.rb') 15 | end 16 | 17 | 18 | 19 | 20 | 21 | 22 | Bundler::GemHelper.install_tasks 23 | 24 | require 'rake/testtask' 25 | 26 | Rake::TestTask.new(:test) do |t| 27 | t.libs << 'lib' 28 | t.libs << 'test' 29 | t.pattern = 'test/**/*_test.rb' 30 | t.verbose = false 31 | end 32 | 33 | 34 | task default: :test 35 | -------------------------------------------------------------------------------- /bin/notify_me: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env ruby 2 | require 'notifyor/cli' 3 | require 'notifyor/remote/connection' 4 | 5 | begin 6 | cli = ::Notifyor::CLI.new 7 | cli.parse 8 | cli.check_notifications 9 | rescue => e 10 | STDERR.puts e.message 11 | STDERR.puts e.backtrace.join("\n") 12 | exit 1 13 | end -------------------------------------------------------------------------------- /lib/notifyor.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift(File.dirname(__FILE__)) 2 | 3 | require 'notifyor/plugin' 4 | require 'notifyor/configuration' 5 | 6 | module Notifyor 7 | class << self 8 | attr_accessor :configuration 9 | end 10 | 11 | def self.configure 12 | self.configuration ||= Configuration.new 13 | yield(configuration) if block_given? 14 | end 15 | 16 | ActiveRecord::Base.send(:include, ::Notifyor::Plugin) if defined?(ActiveRecord) 17 | end -------------------------------------------------------------------------------- /lib/notifyor/cli.rb: -------------------------------------------------------------------------------- 1 | require 'notifyor/version' 2 | require 'optparse' 3 | 4 | module Notifyor 5 | class CLI 6 | 7 | def parse 8 | # Default configuration. 9 | ENV['ssh_host'] = 'localhost' 10 | ENV['ssh_port'] = '22' 11 | ENV['ssh_tunnel_port'] = '2000' 12 | ENV['ssh_redis_port'] = '6379' 13 | 14 | ::OptionParser.new do |opts| 15 | opts.banner = 'Usage: notify_me [options]' 16 | 17 | opts.on('-v', '--version', 18 | 'Show the current version of this gem') do 19 | puts "Notifyor Version: #{::Notifyor::VERSION}"; exit 20 | end 21 | 22 | opts.on('--ssh-host host', 'Provide the host address to your deployment/remote server') do |host| 23 | ENV['ssh_host'] = host 24 | end 25 | 26 | opts.on('--ssh-port port', 'Provide the ssh port for the deployment/remote server') do |port| 27 | ENV['ssh_port'] = port 28 | end 29 | 30 | opts.on('--ssh-user user', 'Provide the ssh user for the deployment/remote server') do |user| 31 | ENV['ssh_user'] = user 32 | end 33 | 34 | opts.on('--tunnel-port tunnel_port', 'Provide the ssh user for the deployment/remote server') do |tunnel_port| 35 | ENV['ssh_tunnel_port'] = tunnel_port 36 | end 37 | 38 | opts.on('--redis-port redis_port', 'Provide the ssh user for the deployment/remote server') do |redis_port| 39 | ENV['ssh_redis_port'] = redis_port 40 | end 41 | 42 | opts.on('--channel [channel]', 'Provide channel on which notifyor should listen.') do |channel| 43 | ENV['channel'] = channel 44 | end 45 | end.parse! 46 | end 47 | 48 | def check_notifications 49 | connection = Notifyor::Remote::Connection.new 50 | begin 51 | connection.build_tunnel 52 | connection.build_redis_tunnel_connection 53 | connection.subscribe_to_redis 54 | rescue => e 55 | STDOUT.write "Could not establish SSH tunnel. Reason: #{e.message}" 56 | end 57 | end 58 | 59 | end 60 | end -------------------------------------------------------------------------------- /lib/notifyor/configuration.rb: -------------------------------------------------------------------------------- 1 | require 'redis' 2 | require 'connection_pool' 3 | module Notifyor 4 | class Configuration 5 | attr_accessor :redis_connection 6 | 7 | def initialize 8 | @redis_connection = ::Redis.new 9 | end 10 | end 11 | end -------------------------------------------------------------------------------- /lib/notifyor/growl.rb: -------------------------------------------------------------------------------- 1 | require 'notifyor/util/os_analyzer' 2 | module Notifyor 3 | module Growl 4 | extend self 5 | 6 | def adapter 7 | return @adapter if @adapter 8 | self.adapter = 9 | case ::Notifyor::Util::OSAnalyzer.os 10 | when :macosx 11 | :terminal_notifier 12 | when :linux 13 | :libnotify_notifier 14 | when :unix 15 | :libnotify_notifier 16 | else 17 | raise 'Operating system not recognized.' 18 | end 19 | @adapter 20 | end 21 | 22 | def adapter=(adapter_name) 23 | case adapter_name 24 | when Symbol, String 25 | require "notifyor/growl/adapters/#{adapter_name}" 26 | @adapter = Notifyor::Growl::Adapters.const_get("#{adapter_name.to_s.split('_').collect(&:capitalize).join}") 27 | else 28 | raise "Missing adapter #{adapter_name}" 29 | end 30 | end 31 | 32 | def create_growl(title, message) 33 | adapter.create_growl(title, message) 34 | end 35 | 36 | end 37 | end -------------------------------------------------------------------------------- /lib/notifyor/growl/adapters/libnotify_notifier.rb: -------------------------------------------------------------------------------- 1 | module Notifyor 2 | module Growl 3 | module Adapters 4 | module LibnotifyNotifier 5 | extend self 6 | 7 | def create_growl(title, message) 8 | %x(notify-send '#{title}' '#{message}') 9 | end 10 | 11 | end 12 | end 13 | end 14 | end -------------------------------------------------------------------------------- /lib/notifyor/growl/adapters/terminal_notifier.rb: -------------------------------------------------------------------------------- 1 | require 'terminal-notifier' 2 | module Notifyor 3 | module Growl 4 | module Adapters 5 | module TerminalNotifier 6 | extend self 7 | 8 | def create_growl(title, message) 9 | ::TerminalNotifier.notify(message, :title => title) 10 | end 11 | 12 | end 13 | end 14 | end 15 | end -------------------------------------------------------------------------------- /lib/notifyor/plugin.rb: -------------------------------------------------------------------------------- 1 | require 'active_support' 2 | require 'redis' 3 | 4 | module Notifyor 5 | module Plugin 6 | extend ::ActiveSupport::Concern 7 | 8 | included do 9 | end 10 | 11 | module ClassMethods 12 | def notifyor(options = {}) 13 | configure_plugin(options) 14 | end 15 | 16 | def configure_plugin(options = {}) 17 | configuration = default_configuration.deep_merge(options) 18 | publish_channels = configuration[:channels] || ['notifyor'] 19 | append_callbacks(configuration, publish_channels) 20 | end 21 | 22 | def append_callbacks(configuration, publish_channels) 23 | publish_channels.each do |channel| 24 | configuration[:only].each do |action| 25 | case action 26 | when :create 27 | self.after_commit -> { ::Notifyor.configuration.redis_connection.publish channel, configuration[:messages][:create].call(self) }, on: :create, if: -> { configuration[:only].include? :create } 28 | when :update 29 | self.after_commit -> { ::Notifyor.configuration.redis_connection.publish channel, configuration[:messages][:update].call(self) }, on: :update, if: -> { configuration[:only].include? :update } 30 | when :destroy 31 | self.before_destroy -> { ::Notifyor.configuration.redis_connection.publish channel, configuration[:messages][:destroy].call(self) }, if: -> { configuration[:only].include? :destroy } 32 | else 33 | #nop 34 | end 35 | end 36 | end 37 | end 38 | 39 | def default_configuration 40 | { 41 | only: [:create, :destroy, :update], 42 | messages: { 43 | create: -> (model) { I18n.t('notifyor.model.create') }, 44 | update: -> (model) { I18n.t('notifyor.model.update') }, 45 | destroy: -> (model) { I18n.t('notifyor.model.destroy') } 46 | } 47 | } 48 | end 49 | 50 | end 51 | end 52 | end -------------------------------------------------------------------------------- /lib/notifyor/remote/connection.rb: -------------------------------------------------------------------------------- 1 | require 'json' 2 | require 'redis' 3 | require 'notifyor/growl' 4 | require 'notifyor/util/formatter' 5 | require 'net/ssh/gateway' 6 | module Notifyor 7 | module Remote 8 | class Connection 9 | 10 | def initialize 11 | @ssh_host = ENV['ssh_host'] || 'localhost' 12 | @ssh_port = ENV['ssh_port'] || '22' 13 | @ssh_user = ENV['ssh_user'] 14 | @tunnel_port = ENV['ssh_tunnel_port'] || '2000' 15 | @redis_port = ENV['ssh_redis_port'] || '6379' 16 | @redis_channel = ENV['channel'] || 'notifyor' 17 | @ssh_gateway = nil 18 | @redis_tunnel_connection = nil 19 | end 20 | 21 | def build_tunnel 22 | unless ['127.0.0.1', 'localhost'].include? @ssh_host 23 | @ssh_gateway = Net::SSH::Gateway.new(@ssh_host, @ssh_user, port: @ssh_port) 24 | @ssh_gateway.open('127.0.0.1', @redis_port, @tunnel_port) 25 | end 26 | end 27 | 28 | def build_redis_tunnel_connection 29 | redis_port = (['127.0.0.1', 'localhost'].include? @ssh_host) ? @redis_port : @tunnel_port 30 | @redis_tunnel_connection = Redis.new(port: redis_port) 31 | end 32 | 33 | def subscribe_to_redis 34 | @redis_tunnel_connection.subscribe(@redis_channel) do |on| 35 | on.message do |channel, msg| 36 | STDERR.write "INFO - Message received on channel: #{channel} \n" 37 | growl_message(msg) 38 | end 39 | end 40 | end 41 | 42 | def growl_message(message) 43 | ::Notifyor::Growl.create_growl("Notifyor", message) unless Notifyor::Util::Formatter.squish!(message).empty? 44 | end 45 | end 46 | end 47 | end -------------------------------------------------------------------------------- /lib/notifyor/util/formatter.rb: -------------------------------------------------------------------------------- 1 | module Notifyor 2 | module Util 3 | module Formatter 4 | extend self 5 | 6 | def squish!(string) 7 | string.gsub!(/\A[[:space:]]+/, '') 8 | string.gsub!(/[[:space:]]+\z/, '') 9 | string.gsub!(/[[:space:]]+/, ' ') 10 | string 11 | end 12 | 13 | end 14 | end 15 | end -------------------------------------------------------------------------------- /lib/notifyor/util/os_analyzer.rb: -------------------------------------------------------------------------------- 1 | require 'rbconfig' 2 | module Notifyor 3 | module Util 4 | module OSAnalyzer 5 | extend self 6 | def os 7 | host_os = RbConfig::CONFIG['host_os'] 8 | case host_os 9 | when /mswin|msys|mingw|cygwin|bccwin|wince|emc/ 10 | :windows 11 | when /darwin|mac os/ 12 | :macosx 13 | when /linux/ 14 | :linux 15 | when /solaris|bsd/ 16 | :unix 17 | else 18 | raise "unknown os: #{host_os.inspect}" 19 | end 20 | end 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/notifyor/version.rb: -------------------------------------------------------------------------------- 1 | module Notifyor 2 | VERSION = "0.8.1" 3 | end 4 | -------------------------------------------------------------------------------- /notifyor.gemspec: -------------------------------------------------------------------------------- 1 | $:.push File.expand_path("../lib", __FILE__) 2 | 3 | require "notifyor/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "notifyor" 7 | s.version = Notifyor::VERSION 8 | 9 | s.authors = ["Erwin Schens"] 10 | s.email = ["erwin.schens@qurasoft.de"] 11 | s.homepage = "https://github.com/ndea/notifyer" 12 | s.summary = "Get realtime notifications on your desktop if something happens in your Rails app." 13 | s.description = "Notifyer creates growl notifications on your desktop if something happens in your Rails app." 14 | s.license = "MIT" 15 | s.executables = ["notify_me"] 16 | s.require_paths = ["lib"] 17 | 18 | s.files = Dir["{app,config,db,lib,bin}/**/*", "MIT-LICENSE", "Rakefile", "README.rdoc"] 19 | s.test_files = Dir["spec/**/*"] 20 | 21 | s.add_dependency 'redis' 22 | s.add_dependency 'connection_pool' 23 | s.add_dependency 'terminal-notifier' 24 | s.add_dependency 'net-ssh' 25 | s.add_dependency 'net-ssh-gateway' 26 | 27 | s.add_development_dependency "sqlite3" 28 | s.add_development_dependency "rspec", "~> 3.4.0" 29 | end 30 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # This file was generated by the `rspec --init` command. Conventionally, all 2 | # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. 3 | # The generated `.rspec` file contains `--require spec_helper` which will cause 4 | # this file to always be loaded, without a need to explicitly require it in any 5 | # files. 6 | # 7 | # Given that it is always loaded, you are encouraged to keep this file as 8 | # light-weight as possible. Requiring heavyweight dependencies from this file 9 | # will add to the boot time of your test suite on EVERY test run, even for an 10 | # individual file that may not need all of that loaded. Instead, consider making 11 | # a separate helper file that requires the additional dependencies and performs 12 | # the additional setup, and require it from the spec files that actually need 13 | # it. 14 | # 15 | # The `.rspec` file also contains a few flags that are not defaults but that 16 | # users commonly want. 17 | # 18 | # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration 19 | RSpec.configure do |config| 20 | # rspec-expectations config goes here. You can use an alternate 21 | # assertion/expectation library such as wrong or the stdlib/minitest 22 | # assertions if you prefer. 23 | config.expect_with :rspec do |expectations| 24 | # This option will default to `true` in RSpec 4. It makes the `description` 25 | # and `failure_message` of custom matchers include text for helper methods 26 | # defined using `chain`, e.g.: 27 | # be_bigger_than(2).and_smaller_than(4).description 28 | # # => "be bigger than 2 and smaller than 4" 29 | # ...rather than: 30 | # # => "be bigger than 2" 31 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true 32 | end 33 | 34 | # rspec-mocks config goes here. You can use an alternate test double 35 | # library (such as bogus or mocha) by changing the `mock_with` option here. 36 | config.mock_with :rspec do |mocks| 37 | # Prevents you from mocking or stubbing a method that does not exist on 38 | # a real object. This is generally recommended, and will default to 39 | # `true` in RSpec 4. 40 | mocks.verify_partial_doubles = true 41 | end 42 | 43 | # The settings below are suggested to provide a good initial experience 44 | # with RSpec, but feel free to customize to your heart's content. 45 | =begin 46 | # These two settings work together to allow you to limit a spec run 47 | # to individual examples or groups you care about by tagging them with 48 | # `:focus` metadata. When nothing is tagged with `:focus`, all examples 49 | # get run. 50 | config.filter_run :focus 51 | config.run_all_when_everything_filtered = true 52 | 53 | # Allows RSpec to persist some state between runs in order to support 54 | # the `--only-failures` and `--next-failure` CLI options. We recommend 55 | # you configure your source control system to ignore this file. 56 | config.example_status_persistence_file_path = "spec/examples.txt" 57 | 58 | # Limits the available syntax to the non-monkey patched syntax that is 59 | # recommended. For more details, see: 60 | # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ 61 | # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ 62 | # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode 63 | config.disable_monkey_patching! 64 | 65 | # This setting enables warnings. It's recommended, but in some cases may 66 | # be too noisy due to issues in dependencies. 67 | config.warnings = true 68 | 69 | # Many RSpec users commonly either run the entire suite or an individual 70 | # file, and it's useful to allow more verbose output when running an 71 | # individual spec file. 72 | if config.files_to_run.one? 73 | # Use the documentation formatter for detailed output, 74 | # unless a formatter has already been configured 75 | # (e.g. via a command-line flag). 76 | config.default_formatter = 'doc' 77 | end 78 | 79 | # Print the 10 slowest examples and example groups at the 80 | # end of the spec run, to help surface which specs are running 81 | # particularly slow. 82 | config.profile_examples = 10 83 | 84 | # Run specs in random order to surface order dependencies. If you find an 85 | # order dependency and want to debug it, you can fix the order by providing 86 | # the seed, which is printed after each run. 87 | # --seed 1234 88 | config.order = :random 89 | 90 | # Seed global randomization in this process using the `--seed` CLI option. 91 | # Setting this allows you to use `--seed` to deterministically reproduce 92 | # test failures related to randomization by passing the same `--seed` value 93 | # as the one that triggered the failure. 94 | Kernel.srand config.seed 95 | =end 96 | end 97 | --------------------------------------------------------------------------------