├── spec ├── dummy │ ├── log │ │ └── .keep │ ├── tmp │ │ └── .keep │ ├── lib │ │ └── assets │ │ │ └── .keep │ ├── public │ │ ├── favicon.ico │ │ ├── apple-touch-icon.png │ │ ├── apple-touch-icon-precomposed.png │ │ ├── 500.html │ │ ├── 422.html │ │ └── 404.html │ ├── app │ │ ├── assets │ │ │ ├── images │ │ │ │ └── .keep │ │ │ ├── javascripts │ │ │ │ ├── channels │ │ │ │ │ └── .keep │ │ │ │ ├── cable.js │ │ │ │ └── application.js │ │ │ ├── config │ │ │ │ └── manifest.js │ │ │ └── stylesheets │ │ │ │ └── application.css │ │ ├── models │ │ │ ├── concerns │ │ │ │ └── .keep │ │ │ └── application_record.rb │ │ ├── controllers │ │ │ ├── concerns │ │ │ │ └── .keep │ │ │ └── application_controller.rb │ │ ├── views │ │ │ └── layouts │ │ │ │ ├── mailer.text.erb │ │ │ │ ├── mailer.html.erb │ │ │ │ └── application.html.erb │ │ ├── helpers │ │ │ └── application_helper.rb │ │ ├── jobs │ │ │ └── application_job.rb │ │ ├── channels │ │ │ └── application_cable │ │ │ │ ├── channel.rb │ │ │ │ └── connection.rb │ │ └── mailers │ │ │ └── application_mailer.rb │ ├── bin │ │ ├── rake │ │ ├── bundle │ │ ├── rails │ │ ├── update │ │ └── setup │ ├── config │ │ ├── routes.rb │ │ ├── spring.rb │ │ ├── environment.rb │ │ ├── cable.yml │ │ ├── initializers │ │ │ ├── session_store.rb │ │ │ ├── mime_types.rb │ │ │ ├── application_controller_renderer.rb │ │ │ ├── filter_parameter_logging.rb │ │ │ ├── cookies_serializer.rb │ │ │ ├── backtrace_silencers.rb │ │ │ ├── assets.rb │ │ │ ├── wrap_parameters.rb │ │ │ ├── inflections.rb │ │ │ └── new_framework_defaults.rb │ │ ├── boot.rb │ │ ├── database.yml │ │ ├── locales │ │ │ └── en.yml │ │ ├── application.rb │ │ ├── secrets.yml │ │ ├── environments │ │ │ ├── test.rb │ │ │ ├── development.rb │ │ │ └── production.rb │ │ └── puma.rb │ ├── config.ru │ └── Rakefile ├── support │ ├── test_config.yml │ └── test_target.rb ├── spec_helper.rb ├── lib │ └── okuribito_rails │ │ ├── observe_method_spec.rb │ │ ├── start_observer_spec.rb │ │ └── regist_method_spec.rb ├── factories.rb ├── features │ ├── method_call_logs_page_spec.rb │ └── method_call_situations_page_spec.rb └── models │ ├── method_call_log_spec.rb │ └── method_call_situation_spec.rb ├── app ├── assets │ ├── images │ │ └── okuribito_rails │ │ │ ├── .keep │ │ │ └── logo.png │ ├── javascripts │ │ └── okuribito_rails │ │ │ └── application.js │ └── stylesheets │ │ └── okuribito_rails │ │ ├── application.css │ │ ├── header.css │ │ └── method_call_info.css ├── helpers │ └── okuribito_rails │ │ └── application_helper.rb ├── controllers │ └── okuribito_rails │ │ ├── application_controller.rb │ │ ├── method_call_logs_controller.rb │ │ └── method_call_situations_controller.rb ├── views │ ├── layouts │ │ └── okuribito_rails │ │ │ ├── _header.html.erb │ │ │ └── application.html.erb │ └── okuribito_rails │ │ ├── kaminari │ │ ├── _last_page.html.erb │ │ ├── _first_page.html.erb │ │ ├── _next_page.html.erb │ │ ├── _prev_page.html.erb │ │ ├── _page.html.erb │ │ └── _paginator.html.erb │ │ ├── method_call_logs │ │ └── index.html.erb │ │ └── method_call_situations │ │ └── index.html.erb └── models │ └── okuribito_rails │ ├── method_call_log.rb │ └── method_call_situation.rb ├── .rspec ├── lib ├── okuribito_rails │ ├── version.rb │ ├── railtie.rb │ ├── config.rb │ ├── engine.rb │ ├── observe_method.rb │ ├── start_observer.rb │ └── regist_method.rb ├── okuribito_rails.rb ├── generators │ └── okuribito_rails │ │ ├── templates │ │ └── initializer.erb │ │ └── install_generator.rb └── tasks │ └── okuribito_rails_tasks.rake ├── doc ├── method_call_logs.png └── method_call_situations.png ├── config ├── routes.rb ├── database.yml.ci └── initializers │ └── okuribito_rails │ └── migration.rb ├── .gitignore ├── Rakefile ├── circle.yml ├── Gemfile ├── db └── migrate │ ├── 20161027145839_create_okuribito_rails_method_call_situations.rb │ └── 20161027150000_create_okuribito_rails_method_call_logs.rb ├── .rubocop.yml ├── MIT-LICENSE ├── CHANGELOG.md ├── okuribito_rails.gemspec └── README.md /spec/dummy/log/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/dummy/tmp/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/dummy/lib/assets/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/dummy/public/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/dummy/app/assets/images/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/dummy/app/models/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/dummy/public/apple-touch-icon.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/images/okuribito_rails/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/dummy/app/controllers/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --require spec_helper 3 | -------------------------------------------------------------------------------- /spec/dummy/app/assets/javascripts/channels/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/dummy/public/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/dummy/app/views/layouts/mailer.text.erb: -------------------------------------------------------------------------------- 1 | <%= yield %> 2 | -------------------------------------------------------------------------------- /spec/dummy/app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /spec/dummy/app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | class ApplicationJob < ActiveJob::Base 2 | end 3 | -------------------------------------------------------------------------------- /lib/okuribito_rails/version.rb: -------------------------------------------------------------------------------- 1 | module OkuribitoRails 2 | VERSION = "0.2.4".freeze 3 | end 4 | -------------------------------------------------------------------------------- /spec/support/test_config.yml: -------------------------------------------------------------------------------- 1 | TestTarget: 2 | - ".deprecated_self_method" 3 | - "#deprecated_method" 4 | -------------------------------------------------------------------------------- /doc/method_call_logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakemurasan/okuribito_rails/HEAD/doc/method_call_logs.png -------------------------------------------------------------------------------- /app/helpers/okuribito_rails/application_helper.rb: -------------------------------------------------------------------------------- 1 | module OkuribitoRails 2 | module ApplicationHelper 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /doc/method_call_situations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakemurasan/okuribito_rails/HEAD/doc/method_call_situations.png -------------------------------------------------------------------------------- /spec/dummy/bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative '../config/boot' 3 | require 'rake' 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /spec/dummy/app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | class ApplicationRecord < ActiveRecord::Base 2 | self.abstract_class = true 3 | end 4 | -------------------------------------------------------------------------------- /spec/dummy/config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | mount OkuribitoRails::Engine => "/okuribito_rails" 3 | end 4 | -------------------------------------------------------------------------------- /spec/support/test_target.rb: -------------------------------------------------------------------------------- 1 | class TestTarget 2 | def self.deprecated_self_method; end 3 | 4 | def deprecated_method; end 5 | end 6 | -------------------------------------------------------------------------------- /app/assets/images/okuribito_rails/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakemurasan/okuribito_rails/HEAD/app/assets/images/okuribito_rails/logo.png -------------------------------------------------------------------------------- /spec/dummy/app/channels/application_cable/channel.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Channel < ActionCable::Channel::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /spec/dummy/app/channels/application_cable/connection.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Connection < ActionCable::Connection::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /spec/dummy/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | protect_from_forgery with: :exception 3 | end 4 | -------------------------------------------------------------------------------- /spec/dummy/app/mailers/application_mailer.rb: -------------------------------------------------------------------------------- 1 | class ApplicationMailer < ActionMailer::Base 2 | default from: 'from@example.com' 3 | layout 'mailer' 4 | end 5 | -------------------------------------------------------------------------------- /spec/dummy/bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /spec/dummy/config/spring.rb: -------------------------------------------------------------------------------- 1 | %w( 2 | .ruby-version 3 | .rbenv-vars 4 | tmp/restart.txt 5 | tmp/caching-dev.txt 6 | ).each { |path| Spring.watch(path) } 7 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | OkuribitoRails::Engine.routes.draw do 2 | resources :method_call_logs, only: [:index] 3 | resources :method_call_situations, only: [:index] 4 | end 5 | -------------------------------------------------------------------------------- /spec/dummy/config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require_relative 'config/environment' 4 | 5 | run Rails.application 6 | -------------------------------------------------------------------------------- /spec/dummy/bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../config/application', __dir__) 3 | require_relative '../config/boot' 4 | require 'rails/commands' 5 | -------------------------------------------------------------------------------- /spec/dummy/config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative 'application' 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /config/database.yml.ci: -------------------------------------------------------------------------------- 1 | test: 2 | adapter: mysql2 3 | encoding: utf8 4 | reconnect: false 5 | database: okuribito_rails_test 6 | pool: 5 7 | timeout: 10000 8 | username: ubuntu -------------------------------------------------------------------------------- /spec/dummy/config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: async 3 | 4 | test: 5 | adapter: async 6 | 7 | production: 8 | adapter: redis 9 | url: redis://localhost:6379/1 10 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.session_store :cookie_store, key: '_dummy_session' 4 | -------------------------------------------------------------------------------- /lib/okuribito_rails.rb: -------------------------------------------------------------------------------- 1 | require "kaminari" 2 | 3 | require "okuribito_rails/engine" 4 | require "okuribito_rails/railtie" 5 | require "okuribito_rails/config" 6 | 7 | module OkuribitoRails 8 | end 9 | -------------------------------------------------------------------------------- /spec/dummy/app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | 2 | //= link_tree ../images 3 | //= link_directory ../javascripts .js 4 | //= link_directory ../stylesheets .css 5 | //= link okuribito_rails_manifest.js 6 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/bundle 2 | .bundle/ 3 | log/*.log 4 | pkg/ 5 | test/dummy/db/*.sqlite3 6 | test/dummy/db/*.sqlite3-journal 7 | test/dummy/log/*.log 8 | test/dummy/tmp/ 9 | test/dummy/.sass-cache 10 | Gemfile.lock 11 | .idea/ 12 | .ruby-version -------------------------------------------------------------------------------- /spec/dummy/config/initializers/application_controller_renderer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # ApplicationController.renderer.defaults.merge!( 4 | # http_host: 'example.org', 5 | # https: false 6 | # ) 7 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /spec/dummy/Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require_relative 'config/application' 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /spec/dummy/config/boot.rb: -------------------------------------------------------------------------------- 1 | # Set up gems listed in the Gemfile. 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../Gemfile', __dir__) 3 | 4 | require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) 5 | $LOAD_PATH.unshift File.expand_path('../../../lib', __dir__) 6 | -------------------------------------------------------------------------------- /lib/okuribito_rails/railtie.rb: -------------------------------------------------------------------------------- 1 | require "okuribito_rails/start_observer" 2 | 3 | module OkuribitoRails 4 | class Railtie < ::Rails::Railtie 5 | config.after_initialize do 6 | StartObserver.new.start if ActiveRecord::Base.connected? 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Specify a serializer for the signed and encrypted cookie jars. 4 | # Valid options are :json, :marshal, and :hybrid. 5 | Rails.application.config.action_dispatch.cookies_serializer = :json 6 | -------------------------------------------------------------------------------- /config/initializers/okuribito_rails/migration.rb: -------------------------------------------------------------------------------- 1 | module OkuribitoRails 2 | if Rails::VERSION::MAJOR >= 5 3 | puts Rails::VERSION::MINOR 4 | class Migration < ActiveRecord::Migration["#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}"];end 5 | else 6 | class Migration < ActiveRecord::Migration;end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /spec/dummy/app/views/layouts/mailer.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | begin 2 | require 'bundler/setup' 3 | end 4 | 5 | Bundler::GemHelper.install_tasks 6 | 7 | require 'rspec/core/rake_task' 8 | RSpec::Core::RakeTask.new(:spec) 9 | task default: :spec 10 | 11 | APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__) 12 | load 'rails/tasks/engine.rake' 13 | load 'rails/tasks/statistics.rake' 14 | -------------------------------------------------------------------------------- /app/controllers/okuribito_rails/application_controller.rb: -------------------------------------------------------------------------------- 1 | module OkuribitoRails 2 | class ApplicationController < ActionController::Base 3 | protect_from_forgery 4 | 5 | before_action -> { head :forbidden }, if: -> { prohibited_env? } 6 | 7 | private 8 | 9 | def prohibited_env? 10 | OkuribitoRails.config.prohibit_webui.include?(ENV["RAILS_ENV"]) 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/views/layouts/okuribito_rails/_header.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= image_tag "okuribito_rails/logo.png", class: "header-logo" %> 3 | 9 |
10 | -------------------------------------------------------------------------------- /spec/dummy/app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dummy 5 | <%= csrf_meta_tags %> 6 | 7 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> 8 | <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> 9 | 10 | 11 | 12 | <%= yield %> 13 | 14 | 15 | -------------------------------------------------------------------------------- /spec/dummy/app/assets/javascripts/cable.js: -------------------------------------------------------------------------------- 1 | // Action Cable provides the framework to deal with WebSockets in Rails. 2 | // You can generate new channels where WebSocket features live using the rails generate channel command. 3 | // 4 | //= require action_cable 5 | //= require_self 6 | //= require_tree ./channels 7 | 8 | (function() { 9 | this.App || (this.App = {}); 10 | 11 | App.cable = ActionCable.createConsumer(); 12 | 13 | }).call(this); 14 | -------------------------------------------------------------------------------- /app/views/layouts/okuribito_rails/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | OkuribitoRails 5 | <%= stylesheet_link_tag "okuribito_rails/application", media: "all" %> 6 | <%= javascript_include_tag "okuribito_rails/application" %> 7 | <%= csrf_meta_tags %> 8 | 9 | 10 | 11 | <%= render 'layouts/okuribito_rails/header' %> 12 |
13 | <%= yield %> 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | machine: 2 | timezone: Asia/Tokyo 3 | ruby: 4 | version: 5 | 2.2.2 6 | dependencies: 7 | override: 8 | - bundle install: 9 | timeout: 180 10 | database: 11 | pre: 12 | - mv config/database.yml.ci config/database.yml 13 | override: 14 | - bundle exec rake db:create RAILS_ENV=test 15 | - bundle exec rake db:migrate RAILS_ENV=test 16 | test: 17 | override: 18 | - bundle exec rspec spec/ 19 | - bundle exec codeclimate-test-reporter 20 | -------------------------------------------------------------------------------- /app/views/okuribito_rails/kaminari/_last_page.html.erb: -------------------------------------------------------------------------------- 1 | <%# Link to the "Last" page 2 | - available local variables 3 | url: url to the last page 4 | current_page: a page object for the currently displayed page 5 | total_pages: total number of pages 6 | per_page: number of items to fetch per page 7 | remote: data-remote 8 | -%> 9 | 10 | <%= link_to_unless current_page.last?, t('views.pagination.last').html_safe, url, :remote => remote %> 11 | 12 | -------------------------------------------------------------------------------- /app/views/okuribito_rails/kaminari/_first_page.html.erb: -------------------------------------------------------------------------------- 1 | <%# Link to the "First" page 2 | - available local variables 3 | url: url to the first page 4 | current_page: a page object for the currently displayed page 5 | total_pages: total number of pages 6 | per_page: number of items to fetch per page 7 | remote: data-remote 8 | -%> 9 | 10 | <%= link_to_unless current_page.first?, t('views.pagination.first').html_safe, url, :remote => remote %> 11 | 12 | -------------------------------------------------------------------------------- /app/views/okuribito_rails/kaminari/_next_page.html.erb: -------------------------------------------------------------------------------- 1 | <%# Link to the "Next" page 2 | - available local variables 3 | url: url to the next page 4 | current_page: a page object for the currently displayed page 5 | total_pages: total number of pages 6 | per_page: number of items to fetch per page 7 | remote: data-remote 8 | -%> 9 | 10 | <%= link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, :rel => 'next', :remote => remote %> 11 | 12 | -------------------------------------------------------------------------------- /app/views/okuribito_rails/kaminari/_prev_page.html.erb: -------------------------------------------------------------------------------- 1 | <%# Link to the "Previous" page 2 | - available local variables 3 | url: url to the previous page 4 | current_page: a page object for the currently displayed page 5 | total_pages: total number of pages 6 | per_page: number of items to fetch per page 7 | remote: data-remote 8 | -%> 9 | 10 | <%= link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, :rel => 'prev', :remote => remote %> 11 | 12 | -------------------------------------------------------------------------------- /lib/okuribito_rails/config.rb: -------------------------------------------------------------------------------- 1 | module OkuribitoRails 2 | class Config 3 | include ActiveSupport::Configurable 4 | 5 | config_accessor :once_detect do 6 | true 7 | end 8 | 9 | config_accessor :setting_path do 10 | "config/okuribito.yml" 11 | end 12 | 13 | config_accessor :prohibit_webui do 14 | ["test"] 15 | end 16 | 17 | config_accessor :prohibit_observe do 18 | ["test"] 19 | end 20 | 21 | config_accessor :force_eager_load do 22 | ["test"] 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = '1.0' 5 | 6 | # Add additional assets to the asset load path 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | 9 | # Precompile additional assets. 10 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. 11 | # Rails.application.config.assets.precompile += %w( search.js ) 12 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | # Declare your gem's dependencies in okuribito_rails.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 debugger 14 | # gem 'debugger' 15 | -------------------------------------------------------------------------------- /app/controllers/okuribito_rails/method_call_logs_controller.rb: -------------------------------------------------------------------------------- 1 | require_dependency "okuribito_rails/application_controller" 2 | 3 | module OkuribitoRails 4 | class MethodCallLogsController < ApplicationController 5 | def index 6 | @method_call_logs = MethodCallLog 7 | .search(search_params) 8 | .page(params[Kaminari.config.param_name]) 9 | end 10 | 11 | private 12 | 13 | def search_params 14 | params.slice( 15 | :class_name, 16 | :method_name 17 | ).presence || {} 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /app/views/okuribito_rails/kaminari/_page.html.erb: -------------------------------------------------------------------------------- 1 | <%# Link showing page number 2 | - available local variables 3 | page: a page object for "this" page 4 | url: url to this page 5 | current_page: a page object for the currently displayed page 6 | total_pages: total number of pages 7 | per_page: number of items to fetch per page 8 | remote: data-remote 9 | -%> 10 | 11 | <%= link_to_unless page.current?, page, url, {:remote => remote, :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil} %> 12 | 13 | -------------------------------------------------------------------------------- /db/migrate/20161027145839_create_okuribito_rails_method_call_situations.rb: -------------------------------------------------------------------------------- 1 | class CreateOkuribitoRailsMethodCallSituations < OkuribitoRails::Migration 2 | def change 3 | create_table :okuribito_rails_method_call_situations do |t| 4 | t.string :class_name, null: false 5 | t.string :method_symbol, null: false 6 | t.string :method_name, null: false 7 | t.integer :called_num, null: false, default: 0 8 | 9 | t.timestamps 10 | end 11 | add_index :okuribito_rails_method_call_situations, :class_name 12 | add_index :okuribito_rails_method_call_situations, :method_name 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20161027150000_create_okuribito_rails_method_call_logs.rb: -------------------------------------------------------------------------------- 1 | class CreateOkuribitoRailsMethodCallLogs < OkuribitoRails::Migration 2 | def change 3 | create_table :okuribito_rails_method_call_logs do |t| 4 | t.integer :method_call_situation_id, null: false 5 | t.string :class_name, null: false 6 | t.string :method_symbol, null: false 7 | t.string :method_name, null: false 8 | t.text :back_trace 9 | 10 | t.timestamps 11 | end 12 | add_index :okuribito_rails_method_call_logs, :class_name 13 | add_index :okuribito_rails_method_call_logs, :method_name 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/okuribito_rails/engine.rb: -------------------------------------------------------------------------------- 1 | module OkuribitoRails 2 | class Engine < ::Rails::Engine 3 | isolate_namespace OkuribitoRails 4 | 5 | initializer "okuribito_rails.assets.precompile", group: :all do |app| 6 | app.config.assets.precompile += %w( 7 | okuribito_rails/logo.png 8 | okuribito_rails/application.css 9 | okuribito_rails/header.css 10 | okuribito_rails/method_call_info.css 11 | ) 12 | end 13 | end 14 | 15 | class << self 16 | def config 17 | @config ||= Config.new 18 | end 19 | 20 | def configure 21 | yield config 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /spec/dummy/config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite version 3.x 2 | # gem install sqlite3 3 | # 4 | # Ensure the SQLite 3 gem is defined in your Gemfile 5 | # gem 'sqlite3' 6 | # 7 | default: &default 8 | adapter: sqlite3 9 | pool: 5 10 | timeout: 5000 11 | 12 | development: 13 | <<: *default 14 | database: db/development.sqlite3 15 | 16 | # Warning: The database defined as "test" will be erased and 17 | # re-generated from your development database when you run "rake". 18 | # Do not set this db to the same as development or production. 19 | test: 20 | <<: *default 21 | database: db/test.sqlite3 22 | 23 | production: 24 | <<: *default 25 | database: db/production.sqlite3 26 | -------------------------------------------------------------------------------- /app/assets/javascripts/okuribito_rails/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, 5 | // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // compiled file. 9 | // 10 | // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require_tree . 14 | -------------------------------------------------------------------------------- /lib/generators/okuribito_rails/templates/initializer.erb: -------------------------------------------------------------------------------- 1 | OkuribitoRails.configure do |config| 2 | # The path of the yaml file that describes the method you want to monitor. 3 | config.setting_path = "config/okuribito.yml" 4 | 5 | # Detecting method calls only once during application running. 6 | config.once_detect = true 7 | 8 | # You will not be able to access the Web UI in the specified environment. 9 | config.prohibit_webui = ["test"] 10 | 11 | # It will not monitor method calls in the specified environment. 12 | config.prohibit_observe = ["test"] 13 | 14 | # OkuribitoRails run `Rails.application.eager_load!` in the specified environment. 15 | config.force_eager_load = ["test"] 16 | 17 | end 18 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /spec/dummy/config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # To learn more, please read the Rails Internationalization guide 20 | # available at http://guides.rubyonrails.org/i18n.html. 21 | 22 | en: 23 | hello: "Hello world" 24 | -------------------------------------------------------------------------------- /spec/dummy/app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, 5 | // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // compiled file. JavaScript code in this file should be added after the last require_* statement. 9 | // 10 | // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require_tree . 14 | -------------------------------------------------------------------------------- /spec/dummy/config/application.rb: -------------------------------------------------------------------------------- 1 | require_relative 'boot' 2 | 3 | # Pick the frameworks you want: 4 | require "active_record/railtie" 5 | require "action_controller/railtie" 6 | require "action_view/railtie" 7 | require "action_mailer/railtie" 8 | require "active_job/railtie" 9 | require "action_cable/engine" 10 | # require "rails/test_unit/railtie" 11 | require "sprockets/railtie" 12 | 13 | Bundler.require(*Rails.groups) 14 | require "okuribito_rails" 15 | 16 | module Dummy 17 | class Application < Rails::Application 18 | # Settings in config/environments/* take precedence over those specified here. 19 | # Application configuration should go into files in config/initializers 20 | # -- all .rb files in that directory are automatically loaded. 21 | end 22 | end 23 | 24 | -------------------------------------------------------------------------------- /app/assets/stylesheets/okuribito_rails/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, 6 | * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the top of the 9 | * compiled file, but it's generally better to create a new file per style scope. 10 | * 11 | *= require_self 12 | *= require_tree . 13 | */ 14 | 15 | body { 16 | margin: 0; 17 | padding: 0; 18 | } 19 | 20 | .main { 21 | width: 98%; 22 | margin-left: auto; 23 | margin-right: auto; 24 | } -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require "simplecov" 2 | 3 | SimpleCov.start do 4 | add_filter "/vendor/" 5 | add_filter "/spec/" 6 | end 7 | 8 | # Configure Rails Envinronment 9 | ENV["RAILS_ENV"] = "test" 10 | require File.expand_path("../dummy/config/environment.rb", __FILE__) 11 | 12 | require "rspec/rails" 13 | require "factory_girl" 14 | require "factories" 15 | require "capybara/rspec" 16 | require "database_cleaner" 17 | 18 | RSpec.configure do |config| 19 | config.include OkuribitoRails::Engine.routes.url_helpers 20 | end 21 | 22 | RSpec.configure do |config| 23 | config.before(:suite) do 24 | DatabaseCleaner.strategy = :truncation 25 | end 26 | 27 | config.before(:each) do 28 | DatabaseCleaner.start 29 | end 30 | 31 | config.after(:each) do 32 | DatabaseCleaner.clean 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /app/controllers/okuribito_rails/method_call_situations_controller.rb: -------------------------------------------------------------------------------- 1 | require_dependency "okuribito_rails/application_controller" 2 | 3 | module OkuribitoRails 4 | class MethodCallSituationsController < ApplicationController 5 | def index 6 | @method_call_situations = MethodCallSituation 7 | .search(search_params) 8 | .page(params[Kaminari.config.param_name]) 9 | .order(class_name: :asc, method_symbol: :asc, method_name: :asc) 10 | end 11 | 12 | private 13 | 14 | def search_params 15 | params.slice( 16 | :class_name, 17 | :method_name, 18 | :x_days_passed, 19 | :uncalled_method, 20 | :called_method 21 | ).presence || {} 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /spec/dummy/app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, 6 | * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the 9 | * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS 10 | * files in this directory. Styles in this file should be added after the last require_* statement. 11 | * It is generally better to create a new file per style scope. 12 | * 13 | *= require_tree . 14 | *= require_self 15 | */ 16 | -------------------------------------------------------------------------------- /app/assets/stylesheets/okuribito_rails/header.css: -------------------------------------------------------------------------------- 1 | .header { 2 | width: 100%; 3 | background-color: #000; 4 | padding-top: 7px; 5 | padding-bottom: 8px; 6 | margin-bottom: 10px; 7 | display:inline-block; 8 | } 9 | .header-logo { 10 | float: left; 11 | } 12 | .global-nav { 13 | text-align: right; 14 | } 15 | .global-nav .nav-item { 16 | float: right; 17 | margin: 0 20px; 18 | } 19 | .global-nav .nav-item a { 20 | display: inline-block; 21 | width: 160px; 22 | height: 30px; 23 | line-height: 30px; 24 | text-align: center; 25 | border-radius: 8px; 26 | color: #fff; 27 | font-size: 1.3rem; 28 | letter-spacing: 1px; 29 | transition: 0.15s; 30 | text-decoration: none; 31 | } 32 | .global-nav .nav-item.active a, 33 | .global-nav .nav-item a:hover { 34 | background-color: #d03c56; 35 | color: #fff; 36 | } 37 | -------------------------------------------------------------------------------- /app/views/okuribito_rails/kaminari/_paginator.html.erb: -------------------------------------------------------------------------------- 1 | <%# The container tag 2 | - available local variables 3 | current_page: a page object for the currently displayed page 4 | total_pages: total number of pages 5 | per_page: number of items to fetch per page 6 | remote: data-remote 7 | paginator: the paginator that renders the pagination tags inside 8 | -%> 9 | <%= paginator.render do -%> 10 | 21 | <% end -%> 22 | -------------------------------------------------------------------------------- /spec/lib/okuribito_rails/observe_method_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | require "support/test_target" 3 | 4 | describe OkuribitoRails::ObserveMethod do 5 | let(:setting_path) { "spec/support/test_config.yml" } 6 | 7 | describe "create MethodCallLog" do 8 | before do 9 | FactoryGirl.create(:method_call_situation) 10 | okuribito = OkuribitoRails::ObserveMethod.new.patch_okuribito 11 | okuribito.apply(setting_path) 12 | end 13 | 14 | subject { OkuribitoRails::MethodCallLog.count } 15 | 16 | context "call patched method" do 17 | before do 18 | TestTarget.new.deprecated_method 19 | end 20 | 21 | it { is_expected.to eq 1 } 22 | end 23 | 24 | context "call unpatched method" do 25 | before do 26 | TestTarget.deprecated_self_method 27 | end 28 | 29 | it { is_expected.to eq 0 } 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /app/models/okuribito_rails/method_call_log.rb: -------------------------------------------------------------------------------- 1 | module OkuribitoRails 2 | class MethodCallLog < ActiveRecord::Base 3 | belongs_to :method_call_situation, counter_cache: :called_num 4 | 5 | validates :class_name, presence: true, length: { minimum: 1, maximum: 255 } 6 | validates :method_symbol, presence: true, inclusion: { in: %w(. #) } 7 | validates :method_name, presence: true, length: { minimum: 1, maximum: 255 } 8 | 9 | scope :with_class_name, ->(class_name) { where("class_name LIKE ?", "%#{class_name}%") } 10 | scope :with_method_name, ->(method_name) { where("method_name LIKE ?", "%#{method_name}%") } 11 | 12 | def self.search(args) 13 | mcl = self 14 | mcl = mcl.with_class_name(args[:class_name]) if args[:class_name].present? 15 | mcl = mcl.with_method_name(args[:method_name]) if args[:method_name].present? 16 | mcl 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /spec/dummy/bin/update: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'pathname' 3 | require 'fileutils' 4 | include FileUtils 5 | 6 | # path to your application root. 7 | APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) 8 | 9 | def system!(*args) 10 | system(*args) || abort("\n== Command #{args} failed ==") 11 | end 12 | 13 | chdir APP_ROOT do 14 | # This script is a way to update your development environment automatically. 15 | # Add necessary update steps to this file. 16 | 17 | puts '== Installing dependencies ==' 18 | system! 'gem install bundler --conservative' 19 | system('bundle check') || system!('bundle install') 20 | 21 | puts "\n== Updating database ==" 22 | system! 'bin/rails db:migrate' 23 | 24 | puts "\n== Removing old logs and tempfiles ==" 25 | system! 'bin/rails log:clear tmp:clear' 26 | 27 | puts "\n== Restarting application server ==" 28 | system! 'bin/rails restart' 29 | end 30 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | AllCops: 2 | Exclude: 3 | - "okuribito_rails.gemspec" 4 | - "Rakefile" 5 | - "vendor/**/*" 6 | - "spec/dummy/**/*" 7 | - "spec/spec_helper.rb" 8 | 9 | Documentation: 10 | Enabled: false 11 | 12 | LineLength: 13 | Max: 100 14 | Exclude: 15 | - "spec/**/*" 16 | 17 | Style/StringLiterals: 18 | EnforcedStyle: double_quotes 19 | SupportedStyles: 20 | - double_quotes 21 | 22 | Metrics/CyclomaticComplexity: 23 | Max: 10 24 | 25 | Metrics/PerceivedComplexity: 26 | Max: 9 27 | 28 | Metrics/MethodLength: 29 | Max: 20 30 | 31 | Metrics/AbcSize: 32 | Max: 30 33 | 34 | Rails: 35 | Enabled: true 36 | 37 | Rails/Output: 38 | Exclude: 39 | - "lib/generators/okuribito_rails/install_generator.rb" 40 | 41 | RedundantReturn: 42 | Exclude: 43 | - "app/controllers/**/*" 44 | 45 | GuardClause: 46 | MinBodyLength: 4 47 | 48 | Style/ActionFilter: 49 | Exclude: 50 | - "app/controllers/okuribito_rails/application_controller.rb" 51 | -------------------------------------------------------------------------------- /spec/dummy/config/secrets.yml: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Your secret key is used for verifying the integrity of signed cookies. 4 | # If you change this key, all old signed cookies will become invalid! 5 | 6 | # Make sure the secret is at least 30 characters and all random, 7 | # no regular words or you'll be exposed to dictionary attacks. 8 | # You can use `rails secret` to generate a secure secret key. 9 | 10 | # Make sure the secrets in this file are kept private 11 | # if you're sharing your code publicly. 12 | 13 | development: 14 | secret_key_base: 9c06b4723be7f4af2382aeb1c8efda81700293184935a61689b56058fdb247c87128f450b1e3b48c49ea2f087cd568fda0206450c8d2108ced3f018b47df31fa 15 | 16 | test: 17 | secret_key_base: 14eba1b673bdd34ee4ab92b7894698702de930c494f425fcdddd4499e36aeb69c579bb7019b5f26bd963e59a7a2c91fb12cfd5f30f4f798781a55ffa0ed3abdf 18 | 19 | # Do not keep production secrets in the repository, 20 | # instead read values from the environment. 21 | production: 22 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> 23 | -------------------------------------------------------------------------------- /spec/dummy/bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'pathname' 3 | require 'fileutils' 4 | include FileUtils 5 | 6 | # path to your application root. 7 | APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) 8 | 9 | def system!(*args) 10 | system(*args) || abort("\n== Command #{args} failed ==") 11 | end 12 | 13 | chdir APP_ROOT do 14 | # This script is a starting point to setup your application. 15 | # Add necessary setup steps to this file. 16 | 17 | puts '== Installing dependencies ==' 18 | system! 'gem install bundler --conservative' 19 | system('bundle check') || system!('bundle install') 20 | 21 | # puts "\n== Copying sample files ==" 22 | # unless File.exist?('config/database.yml') 23 | # cp 'config/database.yml.sample', 'config/database.yml' 24 | # end 25 | 26 | puts "\n== Preparing database ==" 27 | system! 'bin/rails db:setup' 28 | 29 | puts "\n== Removing old logs and tempfiles ==" 30 | system! 'bin/rails log:clear tmp:clear' 31 | 32 | puts "\n== Restarting application server ==" 33 | system! 'bin/rails restart' 34 | end 35 | -------------------------------------------------------------------------------- /lib/tasks/okuribito_rails_tasks.rake: -------------------------------------------------------------------------------- 1 | namespace :okuribito_rails do 2 | desc "Integrate multiple method_call_situations records" 3 | task integrate_method_call_situations: :environment do 4 | puts "Integrate multiple method_call_situations records...." 5 | 6 | OkuribitoRails::MethodCallSituation.group_by_method.each do |situation| 7 | puts "#{situation.class_name}#{situation.method_symbol}#{situation.method_name}" 8 | situations = OkuribitoRails::MethodCallSituation.where(class_name: situation.class_name, 9 | method_symbol: situation.method_symbol, 10 | method_name: situation.method_name) 11 | if situations.size > 1 12 | sum = situations.pluck(:called_num).inject(0) { |a, e| a + e } 13 | situations[0].update(called_num: sum) 14 | situations[1..-1].each(&:destroy) 15 | puts " integrate #{situations.size} records..." 16 | else 17 | puts " nothing to do..." 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /MIT-LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2016 YOURNAME 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 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | ## [0.2.4](https://github.com/muramurasan/okuribito_rails/releases/tag/v0.2.4) (March 1, 2017) 3 | * Fix the following issue: 4 | ** Provide rake task to integrate multiple method_call_situations records #51 5 | ** method_call_situation don't allow duplicated registration #52 6 | 7 | ## [0.2.3](https://github.com/muramurasan/okuribito_rails/releases/tag/v0.2.3) (January 26, 2017) 8 | * Fix the following issue: 9 | ** Search: Add called method query #48 10 | ** Search matches perfect match. (Like search is better) #47 11 | 12 | ## [0.2.2](https://github.com/muramurasan/okuribito_rails/releases/tag/v0.2.2) (January 23, 2017) 13 | * Fix pagination (Specify okuribito_rails template) 14 | 15 | ## [0.2.1](https://github.com/muramurasan/okuribito_rails/releases/tag/v0.2.1) (December 31, 2016) 16 | * Add `force_eager_load` config 17 | 18 | ## [0.2.0](https://github.com/muramurasan/okuribito_rails/releases/tag/v0.2.0) (December 25, 2016) 19 | * Implementation of search function in Web UI 20 | 21 | ## [0.1.0](https://github.com/muramurasan/okuribito_rails/releases/tag/v0.1.0) (December 24, 2016) 22 | * The first stable release 23 | -------------------------------------------------------------------------------- /lib/okuribito_rails/observe_method.rb: -------------------------------------------------------------------------------- 1 | require "okuribito" 2 | 3 | module OkuribitoRails 4 | class ObserveMethod 5 | def patch_okuribito 6 | Okuribito::OkuribitoPatch.new( 7 | once_detect: config_once_detect 8 | ) do |method_name, _obj_name, caller_info, class_name, method_symbol| 9 | ActiveRecord::Base.transaction do 10 | situation = MethodCallSituation.find_by(class_name: class_name, 11 | method_symbol: method_symbol, 12 | method_name: method_name) 13 | if situation.present? 14 | MethodCallLog.create(method_call_situation: situation, 15 | class_name: class_name, 16 | method_symbol: method_symbol, 17 | method_name: method_name, 18 | back_trace: caller_info[0]) 19 | end 20 | end 21 | end 22 | end 23 | 24 | private 25 | 26 | def config_once_detect 27 | OkuribitoRails.config.once_detect 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /spec/factories.rb: -------------------------------------------------------------------------------- 1 | FactoryGirl.define do 2 | factory :method_call_situation, class: OkuribitoRails::MethodCallSituation do 3 | class_name "TestTarget" 4 | method_symbol "#" 5 | method_name "deprecated_method" 6 | called_num 0 7 | 8 | trait :user_feed do 9 | class_name "User" 10 | method_symbol "#" 11 | method_name "feed" 12 | end 13 | 14 | trait :user_profile do 15 | class_name "User" 16 | method_symbol "#" 17 | method_name "profile" 18 | end 19 | 20 | trait :with_method_call_log do 21 | after(:create) do |method_call_situation| 22 | FactoryGirl.create(:method_call_log, 23 | method_call_situation: method_call_situation, 24 | class_name: method_call_situation.class_name, 25 | method_symbol: method_call_situation.method_symbol, 26 | method_name: method_call_situation.method_name) 27 | end 28 | end 29 | end 30 | 31 | factory :method_call_log, class: OkuribitoRails::MethodCallLog do 32 | class_name "TestTarget" 33 | method_symbol "#" 34 | method_name "deprecated_method" 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/new_framework_defaults.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | # 3 | # This file contains migration options to ease your Rails 5.0 upgrade. 4 | # 5 | # Read the Rails 5.0 release notes for more info on each option. 6 | 7 | # Enable per-form CSRF tokens. Previous versions had false. 8 | Rails.application.config.action_controller.per_form_csrf_tokens = true 9 | 10 | # Enable origin-checking CSRF mitigation. Previous versions had false. 11 | Rails.application.config.action_controller.forgery_protection_origin_check = true 12 | 13 | # Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`. 14 | # Previous versions had false. 15 | ActiveSupport.to_time_preserves_timezone = true 16 | 17 | # Require `belongs_to` associations by default. Previous versions had false. 18 | Rails.application.config.active_record.belongs_to_required_by_default = true 19 | 20 | # Do not halt callback chains when a callback returns false. Previous versions had true. 21 | ActiveSupport.halt_callback_chains_on_return_false = false 22 | 23 | # Configure SSL options to enable HSTS with subdomains. Previous versions had false. 24 | Rails.application.config.ssl_options = { hsts: { subdomains: true } } 25 | -------------------------------------------------------------------------------- /app/views/okuribito_rails/method_call_logs/index.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= form_tag(method_call_logs_path, method: "get") do %> 3 | 16 | <% end %> 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | <% @method_call_logs.each do |method_call_log| %> 27 | 28 | 31 | 34 | 37 | 38 | <% end %> 39 | 40 |
Method nameBacktraceRecording date
29 | <%= method_call_log.class_name %><%= method_call_log.method_symbol %><%= method_call_log.method_name %> 30 | 32 | <%= method_call_log.back_trace %> 33 | 35 | <%= method_call_log.created_at %> 36 |
41 | 42 | <%= paginate @method_call_logs, views_prefix: 'okuribito_rails' %> 43 | -------------------------------------------------------------------------------- /lib/okuribito_rails/start_observer.rb: -------------------------------------------------------------------------------- 1 | require "okuribito_rails/regist_method" 2 | require "okuribito_rails/observe_method" 3 | 4 | module OkuribitoRails 5 | class StartObserver 6 | def start 7 | return if prohibit_env? || before_migrate? 8 | return unless File.exist?(yaml_path = setting_path) 9 | 10 | Rails.application.eager_load! if force_eager_load? 11 | 12 | regist_method(yaml_path) 13 | start_observer(yaml_path) 14 | end 15 | 16 | private 17 | 18 | def prohibit_env? 19 | OkuribitoRails.config.prohibit_observe.include?(ENV["RAILS_ENV"]) 20 | end 21 | 22 | def force_eager_load? 23 | OkuribitoRails.config.force_eager_load.include?(ENV["RAILS_ENV"]) 24 | end 25 | 26 | def before_migrate? 27 | !ActiveRecord::Base.connection.table_exists? "okuribito_rails_method_call_situations" 28 | end 29 | 30 | def setting_path 31 | OkuribitoRails.config.setting_path 32 | end 33 | 34 | def regist_method(yaml_path) 35 | # Update database by observed methods. 36 | RegistMethod.new.update_observe_methods(yaml_path) 37 | end 38 | 39 | def start_observer(yaml_path) 40 | # Define behavior that when method called. 41 | okuribito = ObserveMethod.new.patch_okuribito 42 | okuribito.apply(yaml_path) 43 | end 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /okuribito_rails.gemspec: -------------------------------------------------------------------------------- 1 | $:.push File.expand_path("../lib", __FILE__) 2 | 3 | require "okuribito_rails/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "okuribito_rails" 7 | s.version = OkuribitoRails::VERSION 8 | s.authors = ["Yasuhiro Matsumura"] 9 | s.email = ["ym.contributor@gmail.com"] 10 | s.homepage = "https://github.com/muramurasan/okuribito_rails" 11 | s.summary = "OkuribitoRails is an engine for Rails that aims to manage method call status. And you can identify uncalled methods." 12 | s.description = "OkuribitoRails is an engine for Rails that aims to manage method call status. And you can identify uncalled methods." 13 | 14 | s.files = Dir["{app,db,lib}/**/*", "config/routes.rb", "MIT-LICENSE", "Rakefile", "README.md"] 15 | s.test_files = Dir["spec/**/*"] 16 | 17 | s.add_dependency "okuribito" 18 | s.add_dependency "rails", ['>= 4.0', '< 6'] 19 | s.add_dependency "kaminari" 20 | 21 | s.add_development_dependency "sqlite3" 22 | s.add_development_dependency "rspec" 23 | s.add_development_dependency "rspec-rails" 24 | s.add_development_dependency "capybara" 25 | s.add_development_dependency "factory_girl_rails" 26 | s.add_development_dependency "database_cleaner" 27 | s.add_development_dependency "rubocop" 28 | s.add_development_dependency "simplecov" 29 | s.add_development_dependency "codeclimate-test-reporter", "~> 1.0.0" 30 | end 31 | -------------------------------------------------------------------------------- /lib/generators/okuribito_rails/install_generator.rb: -------------------------------------------------------------------------------- 1 | require "rails/generators" 2 | 3 | module OkuribitoRails 4 | class InstallGenerator < Rails::Generators::Base 5 | class_option "with-migrate", type: :boolean 6 | 7 | def start 8 | puts "Start installing okuribito_rails..." 9 | puts "*" * 80 + "\n" 10 | end 11 | 12 | def install_migrations 13 | puts "Copying over OkuribitoRails migrations..." 14 | Dir.chdir(Rails.root) do 15 | `rake okuribito_rails:install:migrations` 16 | end 17 | end 18 | 19 | def run_migrations 20 | return unless options["with-migrate"] 21 | puts "Running rake db:migrate" 22 | `rake db:migrate` 23 | end 24 | 25 | def mount_engine 26 | puts "Insert routing..." 27 | route("mount OkuribitoRails::Engine, :at => '/okuribito_rails'") 28 | end 29 | 30 | def create_config_initializer 31 | puts "Create configuration..." 32 | OkuribitoRails::InstallGenerator.source_root File.expand_path("../templates", __FILE__) 33 | template "initializer.erb", "config/initializers/okuribito_rails.rb" 34 | end 35 | 36 | def finished 37 | puts "\n" + ("*" * 80) 38 | puts "Done! OkuribitoRails has been successfully installed." 39 | puts "Please create and deploy a configuration file of okuribito." 40 | puts "(The yaml that defines the method you want to monitor)" 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /app/assets/stylesheets/okuribito_rails/method_call_info.css: -------------------------------------------------------------------------------- 1 | div.search-area { 2 | padding: 4px; 3 | border: 1px solid #aaa; 4 | margin-bottom: 20px; 5 | } 6 | 7 | dl.search { 8 | position: relative; 9 | margin: 10px; 10 | } 11 | dl.search dt { 12 | margin-right: 30px; 13 | background-color: #fff; 14 | display: inline-block; 15 | } 16 | dl.search dt label { 17 | height: 24px; 18 | line-height: 24px; 19 | } 20 | dl.search dt input[type="text"], input[type="number"] { 21 | width: 100%; 22 | height: 24px; 23 | line-height: 24px; 24 | background: none; 25 | border: 1px solid #aaa; 26 | } 27 | dl.search dt input[type="checkbox"] { 28 | width: 100%; 29 | } 30 | dl.search dd { 31 | position: absolute; 32 | top: 0; 33 | right: 0; 34 | } 35 | dl.search dd button { 36 | display: block; 37 | width: 100px; 38 | height: 50px; 39 | line-height: 50px; 40 | color: #fff; 41 | text-align: center; 42 | background-color: #f66; 43 | border: 1px solid #c66; 44 | font-size: 1.1em; 45 | border-radius: 10px; 46 | } 47 | 48 | .method_call_info { 49 | width: 100%; 50 | border-collapse: collapse; 51 | } 52 | .method_call_info th { 53 | padding: 6px; 54 | text-align: left; 55 | vertical-align: top; 56 | color: #333; 57 | background-color: #eee; 58 | border: 1px solid #b9b9b9; 59 | } 60 | .method_call_info td { 61 | padding: 6px; 62 | background-color: #fff; 63 | border: 1px solid #b9b9b9; 64 | font-size: 0.9em 65 | } 66 | -------------------------------------------------------------------------------- /lib/okuribito_rails/regist_method.rb: -------------------------------------------------------------------------------- 1 | require "yaml" 2 | 3 | module OkuribitoRails 4 | class RegistMethod 5 | def update_observe_methods(path) 6 | input = yaml_to_array(path) 7 | base = db_to_array 8 | new_methods = input - base 9 | new_methods.each { |new_method| regist_method(new_method) } 10 | old_methods = base - input 11 | old_methods.each { |old_method| destroy_method(old_method) } 12 | end 13 | 14 | private 15 | 16 | def yaml_to_array(path) 17 | yaml = YAML.load_file(path) 18 | methods_array = [] 19 | yaml.each do |class_name, observe_methods| 20 | observe_methods.each do |observe_method| 21 | methods_array.push(class_name + observe_method) 22 | end 23 | end 24 | methods_array 25 | end 26 | 27 | def db_to_array 28 | methods_array = [] 29 | results = MethodCallSituation.all 30 | results.each do |result| 31 | methods_array.push(result.class_name + result.method_symbol + result.method_name) 32 | end 33 | methods_array 34 | end 35 | 36 | def regist_method(method) 37 | a = method.split(/\s*(#|\.)\s*/) 38 | MethodCallSituation.create(class_name: a[0], method_symbol: a[1], method_name: a[2]) 39 | end 40 | 41 | def destroy_method(method) 42 | a = method.split(/\s*(#|\.)\s*/) 43 | MethodCallSituation.find_by(class_name: a[0], method_symbol: a[1], method_name: a[2]).destroy 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /spec/lib/okuribito_rails/start_observer_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe OkuribitoRails::StartObserver do 4 | describe "#start" do 5 | let(:prohibit_env) { false } 6 | let(:before_migrate) { false } 7 | let(:setting_path) { "spec/support/test_config.yml" } 8 | let(:start_observer) { OkuribitoRails::StartObserver.new } 9 | 10 | before do 11 | allow(start_observer).to receive(:prohibit_env?).and_return(prohibit_env) 12 | allow(start_observer).to receive(:before_migrate?).and_return(before_migrate) 13 | allow(start_observer).to receive(:setting_path).and_return(setting_path) 14 | allow(start_observer).to receive(:regist_method) 15 | allow(start_observer).to receive(:start_observer) 16 | start_observer.start 17 | end 18 | 19 | context "allowed env / after_migrate" do 20 | it { expect(start_observer).to have_received(:regist_method) } 21 | it { expect(start_observer).to have_received(:start_observer) } 22 | end 23 | 24 | context "prohibited env" do 25 | let(:prohibit_env) { true } 26 | it { expect(start_observer).not_to have_received(:regist_method) } 27 | it { expect(start_observer).not_to have_received(:start_observer) } 28 | end 29 | 30 | context "before_migrate" do 31 | let(:before_migrate) { true } 32 | it { expect(start_observer).not_to have_received(:regist_method) } 33 | it { expect(start_observer).not_to have_received(:start_observer) } 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /app/models/okuribito_rails/method_call_situation.rb: -------------------------------------------------------------------------------- 1 | module OkuribitoRails 2 | class MethodCallSituation < ActiveRecord::Base 3 | has_many :method_call_logs 4 | 5 | validates :class_name, 6 | presence: true, 7 | length: { minimum: 1, maximum: 255 }, 8 | uniqueness: { scope: [:method_symbol, :method_name] } 9 | validates :method_symbol, presence: true, inclusion: { in: %w(. #) } 10 | validates :method_name, presence: true, length: { minimum: 1, maximum: 255 } 11 | validates :called_num, 12 | presence: true, 13 | numericality: { only_integer: true, less_than_or_equal_to: 9_999 } 14 | 15 | scope :with_class_name, ->(class_name) { where("class_name LIKE ?", "%#{class_name}%") } 16 | scope :with_method_name, ->(method_name) { where("method_name LIKE ?", "%#{method_name}%") } 17 | scope :with_days_passed, 18 | ->(num) { where("created_at <= ?", Time.zone.today.days_ago(num).end_of_day) } 19 | scope :with_uncalled_method, -> { where(called_num: 0) } 20 | scope :with_called_method, -> { where(called_num: 1..Float::INFINITY) } 21 | scope :group_by_method, -> { group("class_name", "method_symbol", "method_name") } 22 | 23 | def self.search(args) 24 | mcs = self 25 | mcs = mcs.with_class_name(args[:class_name]) if args[:class_name].present? 26 | mcs = mcs.with_method_name(args[:method_name]) if args[:method_name].present? 27 | mcs = mcs.with_days_passed(args[:x_days_passed].to_i) if args[:x_days_passed].present? 28 | mcs = mcs.with_uncalled_method if args[:uncalled_method].present? 29 | mcs = mcs.with_called_method if args[:called_method].present? 30 | mcs 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /spec/dummy/public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

We're sorry, but something went wrong.

62 |
63 |

If you are the application owner check the logs for more information.

64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /spec/dummy/public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The change you wanted was rejected.

62 |

Maybe you tried to change something you didn't have access to.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /spec/dummy/public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The page you were looking for doesn't exist.

62 |

You may have mistyped the address or the page may have moved.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /spec/lib/okuribito_rails/regist_method_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | require "support/test_target" 3 | 4 | shared_examples "Evaluate the condition of MethodCallSituation" do 5 | it { expect(OkuribitoRails::MethodCallSituation.find_by(class_name: "TestTarget", method_symbol: ".", method_name: "deprecated_self_method")).to be_present } 6 | it { expect(OkuribitoRails::MethodCallSituation.find_by(class_name: "TestTarget", method_symbol: "#", method_name: "deprecated_method")).to be_present } 7 | end 8 | 9 | describe OkuribitoRails::RegistMethod do 10 | let(:setting_path) { "spec/support/test_config.yml" } 11 | 12 | describe "create MethodCallSituation" do 13 | context "registered none" do 14 | before do 15 | OkuribitoRails::RegistMethod.new.update_observe_methods(setting_path) 16 | end 17 | 18 | it_behaves_like "Evaluate the condition of MethodCallSituation" 19 | end 20 | 21 | context "registered one (Already registered)" do 22 | before do 23 | FactoryGirl.create(:method_call_situation, class_name: "TestTarget", method_symbol: "#", method_name: "deprecated_method") 24 | OkuribitoRails::RegistMethod.new.update_observe_methods(setting_path) 25 | end 26 | 27 | it_behaves_like "Evaluate the condition of MethodCallSituation" 28 | end 29 | 30 | context "registered one (Delete target)" do 31 | before do 32 | FactoryGirl.create(:method_call_situation, class_name: "TestTarget", method_symbol: "#", method_name: "delete_target_method") 33 | OkuribitoRails::RegistMethod.new.update_observe_methods(setting_path) 34 | end 35 | 36 | it_behaves_like "Evaluate the condition of MethodCallSituation" 37 | it { expect(OkuribitoRails::MethodCallSituation.find_by(class_name: "TestTarget", method_symbol: "#", method_name: "delete_target_method")).not_to be_present } 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![CircleCI](https://circleci.com/gh/muramurasan/okuribito_rails.svg?style=svg)](https://circleci.com/gh/muramurasan/okuribito_rails) 2 | [![Code Climate](https://codeclimate.com/github/muramurasan/okuribito_rails.png)](https://codeclimate.com/github/muramurasan/okuribito_rails) 3 | [![Test Coverage](https://codeclimate.com/github/muramurasan/okuribito_rails/badges/coverage.svg)](https://codeclimate.com/github/muramurasan/okuribito_rails/coverage) 4 | 5 | # OkuribitoRails 6 | 7 | https://rubygems.org/gems/okuribito_rails 8 | 9 | ![Sample](https://raw.githubusercontent.com/muramurasan/okuribito_rails/master/doc/method_call_situations.png) 10 | 11 | OkuribitoRails is an engine for Rails that aims to manage method call status. 12 | 13 | OkuribitoRails monitors method calls with YAML. 14 | 15 | You can identify methods that have not been called from anywhere! 16 | 17 | # Features 18 | 19 | Here's a comprehensive list of the features currently in OkuribitoRails: 20 | 21 | * Monitoring method call 22 | * During application execution, monitor specified method calls 23 | * After detecting the method call, register the call history in the DB 24 | * You can enable or disable monitoring of method calls (depending on RAILS_ENV) 25 | * Web UI 26 | * Viewing monitored methods 27 | * Viewing call history of monitored methods 28 | * You can hide or show WebUI (depending on RAILS_ENV) 29 | 30 | # Getting started 31 | 32 | Please read [Getting Started](https://github.com/muramurasan/okuribito_rails/wiki/Getting-Started). 33 | 34 | # More information 35 | 36 | The following link have useful information on using OkuribitoRails. 37 | 38 | https://github.com/muramurasan/okuribito_rails/wiki 39 | 40 | # Caution! 41 | 42 | Sorry, OkuribitoRails does not support helper method monitoring. 43 | 44 | # License 45 | 46 | The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT). 47 | -------------------------------------------------------------------------------- /spec/dummy/config/environments/test.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # The test environment is used exclusively to run your application's 5 | # test suite. You never need to work with it otherwise. Remember that 6 | # your test database is "scratch space" for the test suite and is wiped 7 | # and recreated between test runs. Don't rely on the data there! 8 | config.cache_classes = true 9 | 10 | # Do not eager load code on boot. This avoids loading your whole application 11 | # just for the purpose of running a single test. If you are using a tool that 12 | # preloads Rails for running tests, you may have to set it to true. 13 | config.eager_load = false 14 | 15 | # Configure public file server for tests with Cache-Control for performance. 16 | config.public_file_server.enabled = true 17 | config.public_file_server.headers = { 18 | 'Cache-Control' => 'public, max-age=3600' 19 | } 20 | 21 | # Show full error reports and disable caching. 22 | config.consider_all_requests_local = true 23 | config.action_controller.perform_caching = false 24 | 25 | # Raise exceptions instead of rendering exception templates. 26 | config.action_dispatch.show_exceptions = false 27 | 28 | # Disable request forgery protection in test environment. 29 | config.action_controller.allow_forgery_protection = false 30 | config.action_mailer.perform_caching = false 31 | 32 | # Tell Action Mailer not to deliver emails to the real world. 33 | # The :test delivery method accumulates sent emails in the 34 | # ActionMailer::Base.deliveries array. 35 | config.action_mailer.delivery_method = :test 36 | 37 | # Print deprecation notices to the stderr. 38 | config.active_support.deprecation = :stderr 39 | 40 | # Raises error for missing translations 41 | # config.action_view.raise_on_missing_translations = true 42 | end 43 | -------------------------------------------------------------------------------- /app/views/okuribito_rails/method_call_situations/index.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= form_tag(method_call_situations_path, method: "get") do %> 3 | 28 | <% end %> 29 |
30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | <% @method_call_situations.each do |method_call_situation| %> 40 | 41 | 44 | 47 | 50 | 53 | 54 | <% end %> 55 | 56 |
Method nameTimes of calledDays monitoredMonitoring start date
42 | <%= method_call_situation.class_name %><%= method_call_situation.method_symbol %><%= method_call_situation.method_name %> 43 | 45 | <%= method_call_situation.called_num %> 46 | 48 | <%= (Time.zone.today - method_call_situation.created_at.to_date).to_i %> 49 | 51 | <%= method_call_situation.created_at %> 52 |
57 | 58 | <%= paginate @method_call_situations, views_prefix: 'okuribito_rails' %> 59 | 60 | 61 | -------------------------------------------------------------------------------- /spec/dummy/config/environments/development.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # In the development environment your application's code is reloaded on 5 | # every request. This slows down response time but is perfect for development 6 | # since you don't have to restart the web server when you make code changes. 7 | config.cache_classes = false 8 | 9 | # Do not eager load code on boot. 10 | config.eager_load = false 11 | 12 | # Show full error reports. 13 | config.consider_all_requests_local = true 14 | 15 | # Enable/disable caching. By default caching is disabled. 16 | if Rails.root.join('tmp/caching-dev.txt').exist? 17 | config.action_controller.perform_caching = true 18 | 19 | config.cache_store = :memory_store 20 | config.public_file_server.headers = { 21 | 'Cache-Control' => 'public, max-age=172800' 22 | } 23 | else 24 | config.action_controller.perform_caching = false 25 | 26 | config.cache_store = :null_store 27 | end 28 | 29 | # Don't care if the mailer can't send. 30 | config.action_mailer.raise_delivery_errors = false 31 | 32 | config.action_mailer.perform_caching = false 33 | 34 | # Print deprecation notices to the Rails logger. 35 | config.active_support.deprecation = :log 36 | 37 | # Raise an error on page load if there are pending migrations. 38 | config.active_record.migration_error = :page_load 39 | 40 | # Debug mode disables concatenation and preprocessing of assets. 41 | # This option may cause significant delays in view rendering with a large 42 | # number of complex assets. 43 | config.assets.debug = true 44 | 45 | # Suppress logger output for asset requests. 46 | config.assets.quiet = true 47 | 48 | # Raises error for missing translations 49 | # config.action_view.raise_on_missing_translations = true 50 | 51 | # Use an evented file watcher to asynchronously detect changes in source code, 52 | # routes, locales, etc. This feature depends on the listen gem. 53 | # config.file_watcher = ActiveSupport::EventedFileUpdateChecker 54 | end 55 | -------------------------------------------------------------------------------- /spec/dummy/config/puma.rb: -------------------------------------------------------------------------------- 1 | # Puma can serve each request in a thread from an internal thread pool. 2 | # The `threads` method setting takes two numbers a minimum and maximum. 3 | # Any libraries that use thread pools should be configured to match 4 | # the maximum value specified for Puma. Default is set to 5 threads for minimum 5 | # and maximum, this matches the default thread size of Active Record. 6 | # 7 | threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i 8 | threads threads_count, threads_count 9 | 10 | # Specifies the `port` that Puma will listen on to receive requests, default is 3000. 11 | # 12 | port ENV.fetch("PORT") { 3000 } 13 | 14 | # Specifies the `environment` that Puma will run in. 15 | # 16 | environment ENV.fetch("RAILS_ENV") { "development" } 17 | 18 | # Specifies the number of `workers` to boot in clustered mode. 19 | # Workers are forked webserver processes. If using threads and workers together 20 | # the concurrency of the application would be max `threads` * `workers`. 21 | # Workers do not work on JRuby or Windows (both of which do not support 22 | # processes). 23 | # 24 | # workers ENV.fetch("WEB_CONCURRENCY") { 2 } 25 | 26 | # Use the `preload_app!` method when specifying a `workers` number. 27 | # This directive tells Puma to first boot the application and load code 28 | # before forking the application. This takes advantage of Copy On Write 29 | # process behavior so workers use less memory. If you use this option 30 | # you need to make sure to reconnect any threads in the `on_worker_boot` 31 | # block. 32 | # 33 | # preload_app! 34 | 35 | # The code in the `on_worker_boot` will be called if you are using 36 | # clustered mode by specifying a number of `workers`. After each worker 37 | # process is booted this block will be run, if you are using `preload_app!` 38 | # option you will want to use this block to reconnect to any threads 39 | # or connections that may have been created at application boot, Ruby 40 | # cannot share connections between processes. 41 | # 42 | # on_worker_boot do 43 | # ActiveRecord::Base.establish_connection if defined?(ActiveRecord) 44 | # end 45 | 46 | # Allow puma to be restarted by `rails restart` command. 47 | plugin :tmp_restart 48 | -------------------------------------------------------------------------------- /spec/features/method_call_logs_page_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.feature "method_call_log pages", type: :feature do 2 | def expect_search_area 3 | within(".search-area") do 4 | expect(page).to have_content "Class name" 5 | expect(page).to have_content "Method name" 6 | end 7 | end 8 | 9 | def expect_method_call_info 10 | within(".method_call_info") do 11 | expect(page).to have_content "Method name" 12 | expect(page).to have_content "Backtrace" 13 | expect(page).to have_content "Recording date" 14 | end 15 | end 16 | 17 | given(:prohibited_env) { false } 18 | 19 | background do 20 | allow_any_instance_of(OkuribitoRails::ApplicationController).to receive(:prohibited_env?).and_return(prohibited_env) 21 | FactoryGirl.create(:method_call_situation, :user_feed, :with_method_call_log, called_num: 1) 22 | FactoryGirl.create(:method_call_situation, :user_profile, :with_method_call_log, called_num: 0) 23 | 24 | visit method_call_logs_path 25 | end 26 | 27 | context "Prohibit WebUI" do 28 | given(:prohibited_env) { true } 29 | 30 | scenario "Forbidden(403)" do 31 | expect(current_path).to eq method_call_logs_path 32 | expect(page).to have_http_status(403) 33 | end 34 | end 35 | 36 | context "Permit WebUI" do 37 | scenario "Succsess page render" do 38 | expect(current_path).to eq method_call_logs_path 39 | expect(page).to have_http_status(200) 40 | expect_search_area 41 | expect_method_call_info 42 | expect(page).to have_selector("table.method_call_info tbody tr", count: 3) 43 | end 44 | 45 | scenario "Available search function" do 46 | expect(current_path).to eq method_call_logs_path 47 | expect(page).to have_http_status(200) 48 | 49 | within(".search-area") do 50 | fill_in "class_name", with: "User" 51 | fill_in "method_name", with: "profile" 52 | click_button "Search" 53 | end 54 | 55 | expect_search_area 56 | expect_method_call_info 57 | expect(page).to have_selector("table.method_call_info tbody tr", count: 2) 58 | end 59 | 60 | scenario "Available search function(like search)" do 61 | expect(current_path).to eq method_call_logs_path 62 | expect(page).to have_http_status(200) 63 | 64 | within(".search-area") do 65 | fill_in "method_name", with: "file" 66 | click_button "Search" 67 | end 68 | 69 | expect_search_area 70 | expect_method_call_info 71 | expect(page).to have_selector("table.method_call_info tbody tr", count: 2) 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /spec/models/method_call_log_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe OkuribitoRails::MethodCallLog do 4 | let(:method_call_situation) { FactoryGirl.create(:method_call_situation) } 5 | let(:method_call_log) do 6 | FactoryGirl.build(:method_call_log, 7 | method_call_situation: method_call_situation, 8 | class_name: class_name, 9 | method_symbol: method_symbol, 10 | method_name: method_name) 11 | end 12 | let(:class_name) { "TestTarget" } 13 | let(:method_symbol) { "#" } 14 | let(:method_name) { "deprecated_method" } 15 | 16 | subject { method_call_log } 17 | 18 | describe "must have a MethodCallSituation" do 19 | let(:method_call_log) { FactoryGirl.build :method_call_log, method_call_situation: nil } 20 | it { is_expected.not_to be_valid } 21 | end 22 | 23 | describe "valid class_name" do 24 | it { is_expected.to be_valid } 25 | 26 | context "with valid long name" do 27 | let(:class_name) { "A" << "a" * 254 } 28 | it { is_expected.to be_valid } 29 | end 30 | end 31 | 32 | describe "invalid class_name" do 33 | context "must have a name" do 34 | let(:class_name) { nil } 35 | it { is_expected.not_to be_valid } 36 | end 37 | 38 | context "with no name" do 39 | let(:class_name) { "" } 40 | it { is_expected.not_to be_valid } 41 | end 42 | 43 | context "with too long name" do 44 | let(:class_name) { "A" << "a" * 255 } 45 | it { is_expected.not_to be_valid } 46 | end 47 | end 48 | 49 | describe "valid method_symbol" do 50 | context "with valid symbol '.'" do 51 | let(:method_symbol) { "." } 52 | it { is_expected.to be_valid } 53 | end 54 | 55 | context "with valid symbol '#'" do 56 | let(:method_symbol) { "#" } 57 | it { is_expected.to be_valid } 58 | end 59 | end 60 | 61 | describe "invalid method_symbol" do 62 | context "with invalid symbol '$'" do 63 | let(:method_symbol) { "$" } 64 | it { is_expected.not_to be_valid } 65 | end 66 | end 67 | 68 | describe "valid method_name" do 69 | it { is_expected.to be_valid } 70 | 71 | context "with valid long name" do 72 | let(:method_name) { "a" * 255 } 73 | it { is_expected.to be_valid } 74 | end 75 | end 76 | 77 | describe "invalid method_name" do 78 | context "must have a name" do 79 | let(:method_name) { nil } 80 | it { is_expected.not_to be_valid } 81 | end 82 | 83 | context "with no name" do 84 | let(:method_name) { "" } 85 | it { is_expected.not_to be_valid } 86 | end 87 | 88 | context "with too long name" do 89 | let(:method_name) { "a" * 256 } 90 | it { is_expected.not_to be_valid } 91 | end 92 | end 93 | end 94 | -------------------------------------------------------------------------------- /spec/features/method_call_situations_page_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.feature "method_call_situation pages", type: :feature do 2 | def expect_search_area 3 | within(".search-area") do 4 | expect(page).to have_content "Class name" 5 | expect(page).to have_content "Method name" 6 | expect(page).to have_content "x days passed" 7 | expect(page).to have_content "Uncalled" 8 | expect(page).to have_content "Called" 9 | end 10 | end 11 | 12 | def expect_method_call_info 13 | within(".method_call_info") do 14 | expect(page).to have_content "Method name" 15 | expect(page).to have_content "Times of called" 16 | expect(page).to have_content "Days monitored" 17 | expect(page).to have_content "Monitoring start date" 18 | end 19 | end 20 | 21 | given(:prohibited_env) { false } 22 | 23 | background do 24 | allow_any_instance_of(OkuribitoRails::ApplicationController).to receive(:prohibited_env?).and_return(prohibited_env) 25 | FactoryGirl.create(:method_call_situation, :user_feed, called_num: 1) 26 | FactoryGirl.create(:method_call_situation, :user_profile, called_num: 0) 27 | visit method_call_situations_path 28 | end 29 | 30 | context "Prohibit WebUI" do 31 | given(:prohibited_env) { true } 32 | 33 | scenario "Forbidden(403)" do 34 | expect(current_path).to eq method_call_situations_path 35 | expect(page).to have_http_status(403) 36 | end 37 | end 38 | 39 | context "Permit WebUI" do 40 | scenario "Succsess page render" do 41 | expect(current_path).to eq method_call_situations_path 42 | expect(page).to have_http_status(200) 43 | expect_search_area 44 | expect_method_call_info 45 | expect(page).to have_selector("table.method_call_info tbody tr", count: 3) 46 | end 47 | 48 | scenario "Available search function" do 49 | expect(current_path).to eq method_call_situations_path 50 | expect(page).to have_http_status(200) 51 | 52 | within(".search-area") do 53 | fill_in "class_name", with: "User" 54 | fill_in "method_name", with: "profile" 55 | fill_in "x_days_passed", with: 0 56 | check "uncalled_method" 57 | click_button "Search" 58 | end 59 | 60 | expect_search_area 61 | expect_method_call_info 62 | expect(page).to have_selector("table.method_call_info tbody tr", count: 2) 63 | end 64 | 65 | scenario "Available search function(like search)" do 66 | expect(current_path).to eq method_call_situations_path 67 | expect(page).to have_http_status(200) 68 | 69 | within(".search-area") do 70 | fill_in "method_name", with: "file" 71 | click_button "Search" 72 | end 73 | 74 | expect_search_area 75 | expect_method_call_info 76 | expect(page).to have_selector("table.method_call_info tbody tr", count: 2) 77 | end 78 | 79 | scenario "Available search function(called method)" do 80 | expect(current_path).to eq method_call_situations_path 81 | expect(page).to have_http_status(200) 82 | 83 | within(".search-area") do 84 | check "called_method" 85 | click_button "Search" 86 | end 87 | 88 | expect_search_area 89 | expect_method_call_info 90 | expect(page).to have_selector("table.method_call_info tbody tr", count: 2) 91 | end 92 | end 93 | end 94 | -------------------------------------------------------------------------------- /spec/models/method_call_situation_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe OkuribitoRails::MethodCallSituation do 4 | let(:method_call_situation) do 5 | FactoryGirl.build(:method_call_situation, 6 | class_name: class_name, 7 | method_symbol: method_symbol, 8 | method_name: method_name, 9 | called_num: called_num) 10 | end 11 | let(:class_name) { "TestTarget" } 12 | let(:method_symbol) { "#" } 13 | let(:method_name) { "deprecated_method" } 14 | let(:called_num) { 0 } 15 | 16 | subject { method_call_situation } 17 | 18 | describe "valid class_name" do 19 | it { is_expected.to be_valid } 20 | 21 | context "with valid long name" do 22 | let(:class_name) { "A" << "a" * 254 } 23 | it { is_expected.to be_valid } 24 | end 25 | end 26 | 27 | describe "invalid class_name" do 28 | context "must have a name" do 29 | let(:class_name) { nil } 30 | it { is_expected.not_to be_valid } 31 | end 32 | 33 | context "with no name" do 34 | let(:class_name) { "" } 35 | it { is_expected.not_to be_valid } 36 | end 37 | 38 | context "with too long name" do 39 | let(:class_name) { "A" << "a" * 255 } 40 | it { is_expected.not_to be_valid } 41 | end 42 | end 43 | 44 | describe "valid method_symbol" do 45 | context "with valid symbol '.'" do 46 | let(:method_symbol) { "." } 47 | it { is_expected.to be_valid } 48 | end 49 | 50 | context "with valid symbol '#'" do 51 | let(:method_symbol) { "#" } 52 | it { is_expected.to be_valid } 53 | end 54 | end 55 | 56 | describe "invalid method_symbol" do 57 | context "with invalid symbol '$'" do 58 | let(:method_symbol) { "$" } 59 | it { is_expected.not_to be_valid } 60 | end 61 | end 62 | 63 | describe "valid method_name" do 64 | it { is_expected.to be_valid } 65 | 66 | context "with valid long name" do 67 | let(:method_name) { "a" * 255 } 68 | it { is_expected.to be_valid } 69 | end 70 | end 71 | 72 | describe "invalid method_name" do 73 | context "must have a name" do 74 | let(:method_name) { nil } 75 | it { is_expected.not_to be_valid } 76 | end 77 | 78 | context "with no name" do 79 | let(:method_name) { "" } 80 | it { is_expected.not_to be_valid } 81 | end 82 | 83 | context "with too long name" do 84 | let(:method_name) { "a" * 256 } 85 | it { is_expected.not_to be_valid } 86 | end 87 | end 88 | 89 | describe "valid called_num" do 90 | it { is_expected.to be_valid } 91 | 92 | context "with valid large number" do 93 | let(:called_num) { 9999 } 94 | it { is_expected.to be_valid } 95 | end 96 | end 97 | 98 | describe "invalid called_num" do 99 | context "must have a value" do 100 | let(:called_num) { nil } 101 | it { is_expected.not_to be_valid } 102 | end 103 | 104 | context "with string" do 105 | let(:called_num) { "a" } 106 | it { is_expected.not_to be_valid } 107 | end 108 | 109 | context "with too large number" do 110 | let(:called_num) { 10_000 } 111 | it { is_expected.not_to be_valid } 112 | end 113 | end 114 | 115 | describe "duplicate registration" do 116 | before do 117 | FactoryGirl.create(:method_call_situation, 118 | class_name: class_name, 119 | method_symbol: method_symbol, 120 | method_name: method_name, 121 | called_num: called_num) 122 | end 123 | 124 | it { is_expected.not_to be_valid } 125 | end 126 | end 127 | -------------------------------------------------------------------------------- /spec/dummy/config/environments/production.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # Code is not reloaded between requests. 5 | config.cache_classes = true 6 | 7 | # Eager load code on boot. This eager loads most of Rails and 8 | # your application in memory, allowing both threaded web servers 9 | # and those relying on copy on write to perform better. 10 | # Rake tasks automatically ignore this option for performance. 11 | config.eager_load = true 12 | 13 | # Full error reports are disabled and caching is turned on. 14 | config.consider_all_requests_local = false 15 | config.action_controller.perform_caching = true 16 | 17 | # Disable serving static files from the `/public` folder by default since 18 | # Apache or NGINX already handles this. 19 | config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? 20 | 21 | # Compress JavaScripts and CSS. 22 | config.assets.js_compressor = :uglifier 23 | # config.assets.css_compressor = :sass 24 | 25 | # Do not fallback to assets pipeline if a precompiled asset is missed. 26 | config.assets.compile = false 27 | 28 | # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb 29 | 30 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 31 | # config.action_controller.asset_host = 'http://assets.example.com' 32 | 33 | # Specifies the header that your server uses for sending files. 34 | # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache 35 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX 36 | 37 | # Mount Action Cable outside main process or domain 38 | # config.action_cable.mount_path = nil 39 | # config.action_cable.url = 'wss://example.com/cable' 40 | # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] 41 | 42 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 43 | # config.force_ssl = true 44 | 45 | # Use the lowest log level to ensure availability of diagnostic information 46 | # when problems arise. 47 | config.log_level = :debug 48 | 49 | # Prepend all log lines with the following tags. 50 | config.log_tags = [ :request_id ] 51 | 52 | # Use a different cache store in production. 53 | # config.cache_store = :mem_cache_store 54 | 55 | # Use a real queuing backend for Active Job (and separate queues per environment) 56 | # config.active_job.queue_adapter = :resque 57 | # config.active_job.queue_name_prefix = "dummy_#{Rails.env}" 58 | config.action_mailer.perform_caching = false 59 | 60 | # Ignore bad email addresses and do not raise email delivery errors. 61 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 62 | # config.action_mailer.raise_delivery_errors = false 63 | 64 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 65 | # the I18n.default_locale when a translation cannot be found). 66 | config.i18n.fallbacks = true 67 | 68 | # Send deprecation notices to registered listeners. 69 | config.active_support.deprecation = :notify 70 | 71 | # Use default logging formatter so that PID and timestamp are not suppressed. 72 | config.log_formatter = ::Logger::Formatter.new 73 | 74 | # Use a different logger for distributed setups. 75 | # require 'syslog/logger' 76 | # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') 77 | 78 | if ENV["RAILS_LOG_TO_STDOUT"].present? 79 | logger = ActiveSupport::Logger.new(STDOUT) 80 | logger.formatter = config.log_formatter 81 | config.logger = ActiveSupport::TaggedLogging.new(logger) 82 | end 83 | 84 | # Do not dump schema after migrations. 85 | config.active_record.dump_schema_after_migration = false 86 | end 87 | --------------------------------------------------------------------------------