Upgrade to Rails 6.0 (#7658)

* Add dual booting logic to Gemfile

This might be helpful for the Rails 6.0 upgrade project.

* Add more than one gemfile to Travis' configuration

We want to see how the application behaves with more than one Rails versions:

- Gemfile -> Rails 5.2
- Gemfile.next -> Rails 6.0

This will help us figure out what needs to be addressed before migrating to Rails 6.0.

If you want to read more about this technique (dual booting) you can check out this page: https://www.fastruby.io/blog/upgrade-rails/dual-boot/dual-boot-with-rails-6-0-beta.html

* Fix joins

* Upgrade Gemfile.next.lock

* Make sure we're installing the correct versions of gems

* Add Rails 6 notes

* Update rubocop in Gemfile.next.lock

* Fix organization spec

* Fix page_views_spec

* Add Rails 6 and run rails app:update

* Remove some tricks

* Remove Gemfile.next for now

* Fix .content_type deprecation

* Fix deprecation of .where.not NAND/NOR behavior

* Fix deprecation of parameterized emails

* Fix specs

* Remove next flag for now

* Fix spec (hopefully)

* Add wait_for_javascript

* Fix spec, thanks @maestromac!

* Try without wait for javascript hack

* Remove unnecessary bin/update

* Remove file that snuck in the rebase

* Update the vendored gems

* Replace migrate+db:setup with db:prepare

* Update vendored gems

* Fix Gemfile.lock and update vendored stuff

* Fix Gemfile.lock to be the same as master's minus the changes

Co-authored-by: rhymes <rhymesete@gmail.com>
This commit is contained in:
Ernesto Tagwerker 2020-06-04 05:54:25 -04:00 committed by GitHub
parent d2d46c5f47
commit 9ea3a8c67d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
150 changed files with 2417 additions and 157 deletions

View file

@ -15,6 +15,8 @@ addons:
- $(ls tmp/screenshots/*.png | tr "\n" ":")
- $(ls tmp/csvs/*.csv | tr "\n" ":")
debug: true
gemfile:
- Gemfile
services:
- redis-server
env:

View file

@ -78,7 +78,7 @@ gem "pusher-push-notifications", "~> 1.1" # Pusher Push Notifications Ruby serve
gem "rack-attack", "~> 6.3.1" # Used to throttle requests to prevent brute force attacks
gem "rack-cors", "~> 1.1" # Middleware that will make Rack-based apps CORS compatible
gem "rack-timeout", "~> 0.6" # Rack middleware which aborts requests that have been running for longer than a specified timeout
gem "rails", "~> 5.2" # Ruby on Rails
gem "rails", "~> 6.0.1" # Ruby on Rails
gem "rails-settings-cached", ">= 2.1.1" # Settings plugin for Rails that makes managing a table of global key, value pairs easy.
gem "ransack", "~> 2.3" # Searching and sorting
gem "recaptcha", "~> 5.5", require: "recaptcha/rails" # Helpers for the reCAPTCHA API
@ -101,7 +101,7 @@ gem "storext", "~> 3.1" # Add type-casting and other features on top of ActiveRe
gem "stripe", "~> 5.22" # Ruby library for the Stripe API
gem "strong_migrations", "~> 0.6" # Catch unsafe migrations
gem "timber", "~> 3.0" # Great Ruby logging made easy
gem "timber-rails", "~> 1.0" # Timber integration for Rails
gem "timber-rails", github: "timberio/timber-ruby-rails", branch: "master" # Timber integration for Rails
gem "twilio-ruby", "~> 5.36" # The official library for communicating with the Twilio REST API
gem "twitter", "~> 7.0" # A Ruby interface to the Twitter API
gem "uglifier", "~> 4.2" # Uglifier minifies JavaScript files

View file

@ -6,54 +6,78 @@ GIT
acts_as_follower (0.2.1)
activerecord (>= 4.0)
GIT
remote: https://github.com/timberio/timber-ruby-rails.git
revision: 250326b0926d33207f0e1147a594dd8fe4487466
branch: master
specs:
timber-rails (1.0.2)
rails (>= 3.0.0)
timber (~> 3.0)
timber-rack (~> 1.0)
GEM
remote: https://rubygems.org/
specs:
actioncable (5.2.4.3)
actionpack (= 5.2.4.3)
actioncable (6.0.3.1)
actionpack (= 6.0.3.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailer (5.2.4.3)
actionpack (= 5.2.4.3)
actionview (= 5.2.4.3)
activejob (= 5.2.4.3)
actionmailbox (6.0.3.1)
actionpack (= 6.0.3.1)
activejob (= 6.0.3.1)
activerecord (= 6.0.3.1)
activestorage (= 6.0.3.1)
activesupport (= 6.0.3.1)
mail (>= 2.7.1)
actionmailer (6.0.3.1)
actionpack (= 6.0.3.1)
actionview (= 6.0.3.1)
activejob (= 6.0.3.1)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (5.2.4.3)
actionview (= 5.2.4.3)
activesupport (= 5.2.4.3)
actionpack (6.0.3.1)
actionview (= 6.0.3.1)
activesupport (= 6.0.3.1)
rack (~> 2.0, >= 2.0.8)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (5.2.4.3)
activesupport (= 5.2.4.3)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (6.0.3.1)
actionpack (= 6.0.3.1)
activerecord (= 6.0.3.1)
activestorage (= 6.0.3.1)
activesupport (= 6.0.3.1)
nokogiri (>= 1.8.5)
actionview (6.0.3.1)
activesupport (= 6.0.3.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
active_record_union (1.3.0)
activerecord (>= 4.0)
activejob (5.2.4.3)
activesupport (= 5.2.4.3)
activejob (6.0.3.1)
activesupport (= 6.0.3.1)
globalid (>= 0.3.6)
activemodel (5.2.4.3)
activesupport (= 5.2.4.3)
activerecord (5.2.4.3)
activemodel (= 5.2.4.3)
activesupport (= 5.2.4.3)
arel (>= 9.0)
activemodel (6.0.3.1)
activesupport (= 6.0.3.1)
activerecord (6.0.3.1)
activemodel (= 6.0.3.1)
activesupport (= 6.0.3.1)
activerecord-import (1.0.5)
activerecord (>= 3.2)
activestorage (5.2.4.3)
actionpack (= 5.2.4.3)
activerecord (= 5.2.4.3)
activestorage (6.0.3.1)
actionpack (= 6.0.3.1)
activejob (= 6.0.3.1)
activerecord (= 6.0.3.1)
marcel (~> 0.3.1)
activesupport (5.2.4.3)
activesupport (6.0.3.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
acts-as-taggable-on (6.5.0)
activerecord (>= 5.0, < 6.1)
addressable (2.7.0)
@ -86,7 +110,6 @@ GEM
approvals (0.0.24)
nokogiri (~> 1.6)
thor (~> 0.18)
arel (9.0.0)
ast (2.4.0)
autoprefixer-rails (9.7.6)
execjs
@ -566,18 +589,20 @@ GEM
rack-test (1.1.0)
rack (>= 1.0, < 3)
rack-timeout (0.6.0)
rails (5.2.4.3)
actioncable (= 5.2.4.3)
actionmailer (= 5.2.4.3)
actionpack (= 5.2.4.3)
actionview (= 5.2.4.3)
activejob (= 5.2.4.3)
activemodel (= 5.2.4.3)
activerecord (= 5.2.4.3)
activestorage (= 5.2.4.3)
activesupport (= 5.2.4.3)
rails (6.0.3.1)
actioncable (= 6.0.3.1)
actionmailbox (= 6.0.3.1)
actionmailer (= 6.0.3.1)
actionpack (= 6.0.3.1)
actiontext (= 6.0.3.1)
actionview (= 6.0.3.1)
activejob (= 6.0.3.1)
activemodel (= 6.0.3.1)
activerecord (= 6.0.3.1)
activestorage (= 6.0.3.1)
activesupport (= 6.0.3.1)
bundler (>= 1.3.0)
railties (= 5.2.4.3)
railties (= 6.0.3.1)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
@ -587,12 +612,12 @@ GEM
rails-settings-cached (2.1.1)
rails (>= 4.2.0)
request_store
railties (5.2.4.3)
actionpack (= 5.2.4.3)
activesupport (= 5.2.4.3)
railties (6.0.3.1)
actionpack (= 6.0.3.1)
activesupport (= 6.0.3.1)
method_source
rake (>= 0.8.7)
thor (>= 0.19.0, < 2.0)
thor (>= 0.20.3, < 2.0)
rainbow (3.0.0)
rake (13.0.1)
ransack (2.3.2)
@ -774,10 +799,6 @@ GEM
timber-rack (1.0.1)
rack (>= 1.2, < 3.0)
timber (~> 3.0)
timber-rails (1.0.1)
rails (>= 3.0.0, < 6.0.0)
timber (~> 3.0)
timber-rack (~> 1.0)
timecop (0.9.1)
twilio-ruby (5.36.0)
faraday (>= 0.9, < 2.0)
@ -835,7 +856,7 @@ GEM
rack-proxy (>= 0.6.1)
railties (>= 5.2)
semantic_range (>= 2.3.0)
websocket-driver (0.7.1)
websocket-driver (0.7.2)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.4)
xpath (3.2.0)
@ -846,6 +867,7 @@ GEM
yard (>= 0.8.3)
yard-activesupport-concern (0.0.1)
yard (>= 0.8)
zeitwerk (2.3.0)
zonebie (0.6.1)
PLATFORMS
@ -949,7 +971,7 @@ DEPENDENCIES
rack-cors (~> 1.1)
rack-host-redirect (~> 1.3)
rack-timeout (~> 0.6)
rails (~> 5.2)
rails (~> 6.0.1)
rails-settings-cached (>= 2.1.1)
ransack (~> 2.3)
recaptcha (~> 5.5)
@ -987,7 +1009,7 @@ DEPENDENCIES
strong_migrations (~> 0.6)
test-prof (~> 0.11)
timber (~> 3.0)
timber-rails (~> 1.0)
timber-rails!
timecop (~> 0.9)
twilio-ruby (~> 5.36)
twitter (~> 7.0)

View file

@ -121,7 +121,9 @@ class ChatChannelMembershipsController < ApplicationController
flash[:settings_notice] = "Invitation to #{channel_name} accepted. It may take a moment to show up in your list."
else
send_chat_action_message("@#{current_user.username} added @#{@chat_channel_membership.user.username}", current_user, @chat_channel_membership.chat_channel_id, "joined")
NotifyMailer.channel_invite_email(@chat_channel_membership, @chat_channel_membership.user).deliver_later
NotifyMailer.with(membership: @chat_channel_membership, inviter: @chat_channel_membership.user).channel_invite_email.deliver_later
flash[:settings_notice] = "Accepted request of #{@chat_channel_membership.user.username} to join #{channel_name}."
membership = ChatChannelMembership.find_by!(chat_channel_id: @chat_channel_membership.chat_channel.id, user: current_user)
respond_to do |format|

View file

@ -24,7 +24,7 @@ class StickyArticleCollection
@tag_articles ||= Article.published.tagged_with(article_tags, any: true).
includes(:user).
where("public_reactions_count > ? OR comments_count > ?", reaction_count_num, comment_count_num).
where.not(id: article.id, user_id: article.user_id).
where.not(id: article.id).where.not(user_id: article.user_id).
where("featured_number > ?", 5.days.ago.to_i).
order(Arel.sql("RANDOM()")).
limit(8)
@ -36,7 +36,7 @@ class StickyArticleCollection
Article.published.tagged_with(%w[career productivity discuss explainlikeimfive], any: true).
includes(:user).
where("comments_count > ?", comment_count_num).
where.not(id: article.id, user_id: article.user_id).
where.not(id: article.id).where.not(user_id: article.user_id).
where("featured_number > ?", 5.days.ago.to_i).
order(Arel.sql("RANDOM()")).
limit(10 - tag_articles.size)

View file

@ -81,14 +81,16 @@ class NotifyMailer < ApplicationMailer
mail(to: @user.email, subject: subject)
end
def channel_invite_email(membership, inviter)
@membership = membership
@inviter = inviter
def channel_invite_email
@membership = params[:membership]
@inviter = params[:inviter]
subject = if @membership.role == "mod"
"You are invited to the #{@membership.chat_channel.channel_name} channel as moderator."
else
"You are invited to the #{@membership.chat_channel.channel_name} channel."
end
mail(to: @membership.user.email, subject: subject)
end

View file

@ -169,7 +169,7 @@ class Article < ApplicationRecord
scope :feed, -> { published.includes(:taggings).select(:id, :published_at, :processed_html, :user_id, :organization_id, :title, :path, :cached_tag_list) }
scope :with_video, -> { published.where.not(video: [nil, ""], video_thumbnail_url: [nil, ""]).where("score > ?", -4) }
scope :with_video, -> { published.where.not(video: [nil, ""]).where.not(video_thumbnail_url: [nil, ""]).where("score > ?", -4) }
scope :eager_load_serialized_data, -> { includes(:user, :organization, :tags) }

View file

@ -112,13 +112,13 @@ class ChatChannel < ApplicationRecord
existing_membership = ChatChannelMembership.find_by(user_id: user.id, chat_channel_id: id)
if existing_membership.present? && %w[active pending].exclude?(existing_membership.status)
if existing_membership.update(status: "pending", role: membership_role)
NotifyMailer.channel_invite_email(existing_membership, inviter).deliver_later
NotifyMailer.with(membership: existing_membership, inviter: inviter).channel_invite_email.deliver_later
invitation_sent += 1
end
else
membership = ChatChannelMembership.create(user_id: user.id, chat_channel_id: id, role: membership_role, status: "pending")
if membership.persisted?
NotifyMailer.channel_invite_email(membership, inviter).deliver_later
NotifyMailer.with(membership: membership, inviter: inviter).channel_invite_email.deliver_later
invitation_sent += 1
end
end

View file

@ -14,7 +14,7 @@ module Internal
role_id_for(:trusted),
).order("users.comments_count DESC")
else
relation.joins(:users_roles).
relation.joins(:roles).
where(users_roles: { role_id: role_id_for(state) })
end

View file

@ -1,3 +1,4 @@
# NOTE: [Rails 6] Util class is obsolete in Rails 6
module Audit
module Event
class Util

View file

@ -10,9 +10,10 @@ module Suggester
end
def suggest
base_articles = Article.includes(:user).
includes(:organization).
where.not(id: not_ids, organization_id: nil).
base_articles = Article.
includes(:user, :organization).
where.not(id: not_ids).
where.not(organization_id: nil).
cached_tagged_with(tag)
if area == "additional_articles"

View file

@ -1,5 +1,6 @@
#!/usr/bin/env ruby
require "fileutils"
include FileUtils
# path to your application root.
APP_ROOT = File.expand_path("..", __dir__)
@ -8,7 +9,7 @@ def system!(*args)
system(*args) || abort("\n== Command #{args} failed ==")
end
FileUtils.chdir APP_ROOT do
chdir APP_ROOT do
# This script is a way to set up or update your development environment automatically.
# This script is idempotent, so that you can run it at anytime and get an expectable outcome.
# Add necessary setup steps to this file.
@ -26,7 +27,7 @@ FileUtils.chdir APP_ROOT do
puts "\n== Copying sample files =="
unless File.exist?("config/database.yml")
FileUtils.cp "config/database.yml.sample", "config/database.yml"
cp "config/database.yml.sample", "config/database.yml"
end
puts "\n== Preparing Test Elasticsearch =="

View file

@ -20,7 +20,7 @@ Bundler.require(*Rails.groups)
module PracticalDeveloper
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 5.1
config.load_defaults 5.1 # NOTE: [Rails 6] we should at least work towards updating this to 5.2
# Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers
@ -50,24 +50,9 @@ module PracticalDeveloper
# Therefore we disable "per_form_csrf_tokens" for the time being.
config.action_controller.per_form_csrf_tokens = false
# Enable CORS for API v0
# (logging is only activated when debug is enabled)
debug_cors = ENV["DEBUG_CORS"].present? ? true : false
config.middleware.insert_before 0, Rack::Cors, debug: debug_cors, logger: (-> { Rails.logger }) do
allow do
origins do |source, _env|
source # echo back the client's `Origin` header instead of using `*`
end
# allowed public APIs
%w[articles comments listings podcast_episodes tags users videos].each do |resource_name|
# allow read operations, disallow custom headers (eg. api-key) and enable preflight caching
# NOTE: Chrome caps preflight caching at 2 hours, Firefox at 24 hours
# see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age#Directives
resource "/api/#{resource_name}/*", methods: %i[head get options], headers: [], max_age: 2.hours.to_i
end
end
end
# NOTE: [Rails 6]
# To improve security, Rails embeds the purpose and expiry metadata inside encrypted or signed cookies value.
config.action_dispatch.use_cookies_with_metadata = false
# After-initialize checker to add routes to reserved words
config.after_initialize do

View file

@ -1,5 +1,4 @@
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
ENV["COMMAND"] = ARGV[0]
require "bundler/setup" # Set up gems listed in the Gemfile.
require "bootsnap/setup" # Speed up boot time by caching expensive operations.

View file

@ -1,7 +1,4 @@
Rails.application.configure do
# Verifies that versions and hashed value of the package contents in the project's package.json
config.webpacker.check_yarn_integrity = false
# Settings specified here will take precedence over those in config/application.rb.
# Code is not reloaded between requests.
@ -20,6 +17,10 @@ Rails.application.configure do
# Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
# or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
# config.require_master_key = true
# Attempt to read encrypted secrets from `config/secrets.yml.enc`.
# Requires an encryption key in `ENV["RAILS_MASTER_KEY"]` or
# `config/secrets.yml.key`.
config.read_encrypted_secrets = true
# Disable serving static files from the `/public` folder by default since
@ -40,7 +41,7 @@ Rails.application.configure do
config.assets.digest = true
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = 'http://assets.example.com'
config.action_controller.asset_host = ENV["FASTLY_CDN_URL"]
# Specifies the header that your server uses for sending files.
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
@ -59,14 +60,12 @@ Rails.application.configure do
# Prepend all log lines with the following tags.
config.log_tags = [:request_id]
# Use a different logger for distributed setups.
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
# Use a different cache store in production.
# config.cache_store = :mem_cache_store
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
config.action_controller.asset_host = ENV["FASTLY_CDN_URL"]
# DEV uses the RedisCloud Heroku Add-On which comes with the predefined env variable REDISCLOUD_URL
redis_url = ENV["REDISCLOUD_URL"]
redis_url ||= ENV["REDIS_URL"]
DEFAULT_EXPIRATION = 24.hours.to_i.freeze
config.cache_store = :redis_cache_store, { url: redis_url, expires_in: DEFAULT_EXPIRATION }
# Use a real queuing backend for Active Job (and separate queues per environment)
# config.active_job.queue_adapter = :resque
@ -109,12 +108,6 @@ Rails.application.configure do
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
# DEV uses the RedisCloud Heroku Add-On which comes with the predefined env variable REDISCLOUD_URL
redis_url = ENV["REDISCLOUD_URL"]
redis_url ||= ENV["REDIS_URL"]
DEFAULT_EXPIRATION = 24.hours.to_i.freeze
config.cache_store = :redis_cache_store, { url: redis_url, expires_in: DEFAULT_EXPIRATION }
config.app_domain = ENV["APP_DOMAIN"]
config.action_mailer.delivery_method = :smtp

View file

@ -10,6 +10,9 @@ Rails.application.configure do
# and recreated between test runs. Don't rely on the data there!
config.cache_classes = true
# NOTE: [Rails 6] this is the default store in testing,
# as we haven't enabled Rails 6.0 defaults in config/application.rb,
# we need to keep this explicit, for now
config.cache_store = :null_store
# Do not eager load code on boot. This avoids loading your whole application

View file

@ -6,7 +6,7 @@ Rails.application.config.assets.version = "1.1"
# Add additional assets to the asset load path.
# Rails.application.config.assets.paths << Emoji.images_path
# Add Yarn node_modules folder to the asset load path
# Add Yarn node_modules folder to the asset load path.
Rails.application.config.assets.paths << Rails.root.join("node_modules")
Rails.application.config.assets.paths << Rails.root.join("app/assets/xml")

View file

@ -1,9 +1,7 @@
# Be sure to restart your server when you modify this file.
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
# but don't wish to see in your backtraces.
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
# You can also remove all the silencers if you're trying to debug a problem
# that might stem from framework code.
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
# Rails.backtrace_cleaner.remove_silencers!

View file

@ -0,0 +1,19 @@
# Be sure to restart your server when you modify this file.
# Enable CORS for API v0 (logging is only activated when debug is enabled)
debug_cors = ENV["DEBUG_CORS"].present? ? true : false
Rails.application.config.middleware.insert_before 0, Rack::Cors, debug: debug_cors, logger: (-> { Rails.logger }) do
allow do
origins do |source, _env|
source # echo back the client's `Origin` header instead of using `*`
end
# allowed public APIs
%w[articles comments listings podcast_episodes tags users videos].each do |resource_name|
# allow read operations, disallow custom headers (eg. api-key) and enable preflight caching
# NOTE: Chrome caps preflight caching at 2 hours, Firefox at 24 hours
# see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age#Directives
resource "/api/#{resource_name}/*", methods: %i[head get options], headers: [], max_age: 2.hours.to_i
end
end
end

View file

@ -0,0 +1,45 @@
# Be sure to restart your server when you modify this file.
#
# This file contains migration options to ease your Rails 6.0 upgrade.
#
# Once upgraded flip defaults one by one to migrate to the new default.
#
# Read the Guide for Upgrading Ruby on Rails for more info on each option.
# Don't force requests from old versions of IE to be UTF-8 encoded.
# Rails.application.config.action_view.default_enforce_utf8 = false
# Embed purpose and expiry metadata inside signed and encrypted
# cookies for increased security.
#
# This option is not backwards compatible with earlier Rails versions.
# It's best enabled when your entire app is migrated and stable on 6.0.
# Rails.application.config.action_dispatch.use_cookies_with_metadata = true
# Change the return value of `ActionDispatch::Response#content_type` to Content-Type header without modification.
# Rails.application.config.action_dispatch.return_only_media_type_on_content_type = false
# Return false instead of self when enqueuing is aborted from a callback.
# Rails.application.config.active_job.return_false_on_aborted_enqueue = true
# Send Active Storage analysis and purge jobs to dedicated queues.
# Rails.application.config.active_storage.queues.analysis = :active_storage_analysis
# Rails.application.config.active_storage.queues.purge = :active_storage_purge
# When assigning to a collection of attachments declared via `has_many_attached`, replace existing
# attachments instead of appending. Use #attach to add new attachments without replacing existing ones.
# Rails.application.config.active_storage.replace_on_assign_to_many = true
# Use ActionMailer::MailDeliveryJob for sending parameterized and normal mail.
#
# The default delivery jobs (ActionMailer::Parameterized::DeliveryJob, ActionMailer::DeliveryJob),
# will be removed in Rails 6.1. This setting is not backwards compatible with earlier Rails versions.
# If you send mail in the background, job workers need to have a copy of
# MailDeliveryJob to ensure all delivery jobs are processed properly.
# Make sure your entire app is migrated and stable on 6.0 before using this setting.
# Rails.application.config.action_mailer.delivery_job = "ActionMailer::MailDeliveryJob"
# Enable the same cache key to be reused when the object being cached of type
# `ActiveRecord::Relation` changes by moving the volatile information (max updated at and count)
# of the relation's cache key into the cache version to support recycling cache key.
# Rails.application.config.active_record.collection_cache_versioning = true

View file

@ -15,6 +15,9 @@ port ENV.fetch("PORT") { 3000 }
#
environment ENV.fetch("RAILS_ENV") { "development" }
# Specifies the `pidfile` that Puma will use.
pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
# Specifies the number of `workers` to boot in clustered mode.
# Workers are forked webserver processes. If using threads and workers together
# the concurrency of the application would be max `threads` * `workers`.

View file

@ -5,12 +5,7 @@ namespace :app_initializer do
Rake::Task["search:setup"].execute
puts "\n== Preparing database =="
begin
Rake::Task["db:migrate"].execute
rescue ActiveRecord::NoDatabaseError
puts "\n== Creating and Seeding database =="
system("bin/rails db:setup")
end
system!('bin/rails db:prepare')
puts "\n== Updating Data =="
Rake::Task["data_updates:enqueue_data_update_worker"].execute

View file

@ -485,8 +485,8 @@ RSpec.describe NotifyMailer, type: :mailer do
describe "#channel_invite_email" do
let(:moderator_membership) { create(:chat_channel_membership, user_id: user2.id, role: "mod") }
let(:regular_membership) { create(:chat_channel_membership, user_id: user2.id, role: "member") }
let(:moderator_email) { described_class.channel_invite_email(moderator_membership, nil) }
let(:member_email) { described_class.channel_invite_email(regular_membership, user) }
let(:moderator_email) { described_class.with(membership: moderator_membership, inviter: nil).channel_invite_email }
let(:member_email) { described_class.with(membership: regular_membership, inviter: user).channel_invite_email }
it "renders proper subject" do
expect(moderator_email.subject).to eq("You are invited to the #{moderator_membership.chat_channel.channel_name} channel as moderator.")

View file

@ -35,7 +35,7 @@ class NotifyMailerPreview < ActionMailer::Preview
def channel_invite_email
user = User.first
membership = ChatChannelMembership.last
NotifyMailer.channel_invite_email(membership, user)
NotifyMailer.with(membership: membership, inviter: user).channel_invite_email
end
def tag_moderator_confirmation_email

View file

@ -255,14 +255,22 @@ RSpec.describe Organization, type: :model do
it "updates the paths of the organization's articles" do
new_slug = "slug_#{rand(10_000)}"
organization.update(slug: new_slug)
sidekiq_perform_enqueued_jobs(only: Organizations::UpdateOrganizationArticlesPathsWorker) do
organization.update(slug: new_slug)
end
article = Article.find_by(organization_id: organization.id)
expect(article.path).to include(new_slug)
end
it "updates article cached_organizations" do
new_slug = "slug_#{rand(10_000)}"
organization.update(slug: new_slug)
sidekiq_perform_enqueued_jobs(only: Organizations::UpdateOrganizationArticlesPathsWorker) do
organization.update(slug: new_slug)
end
article = Article.find_by(organization_id: organization.id)
expect(article.cached_organization.slug).to eq(new_slug)
end

View file

@ -143,6 +143,9 @@ RSpec.configure do |config|
stub_request(:any, /dummyimage.com/).
to_return(status: 200, body: "", headers: {})
stub_request(:post, "http://www.google-analytics.com/collect").
to_return(status: 200, body: "", headers: {})
end
OmniAuth.config.test_mode = true

View file

@ -45,7 +45,7 @@ RSpec.describe "Api::V0::Articles", type: :request do
context "without params" do
it "returns json response" do
get api_articles_path
expect(response.content_type).to eq("application/json")
expect(response.media_type).to eq("application/json")
end
it "returns nothing if params state=all is not found" do
@ -371,20 +371,20 @@ RSpec.describe "Api::V0::Articles", type: :request do
headers = { "authorization" => "Bearer #{access_token.token}", "content-type" => "application/json" }
get me_api_articles_path, headers: headers
expect(response.content_type).to eq("application/json")
expect(response.media_type).to eq("application/json")
expect(response).to have_http_status(:ok)
end
it "returns proper response specification" do
get me_api_articles_path, params: { access_token: access_token.token }
expect(response.content_type).to eq("application/json")
expect(response.media_type).to eq("application/json")
expect(response).to have_http_status(:ok)
end
it "returns success when requesting publiched articles with public token" do
public_token = create(:doorkeeper_access_token, resource_owner: user, scopes: "public")
get me_api_articles_path(status: :published), params: { access_token: public_token.token }
expect(response.content_type).to eq("application/json")
expect(response.media_type).to eq("application/json")
expect(response).to have_http_status(:ok)
end

View file

@ -59,7 +59,8 @@ RSpec.describe "Api::V0::Listings", type: :request do
it "returns json response and ok status" do
get api_listings_path
expect(response.content_type).to eq("application/json")
expect(response.media_type).to eq("application/json")
expect(response).to have_http_status(:ok)
end

View file

@ -7,7 +7,7 @@ RSpec.describe "Api::V0::PodcastEpisodes", type: :request do
it "returns json response" do
get api_podcast_episodes_path
expect(response.content_type).to eq("application/json")
expect(response.media_type).to eq("application/json")
end
it "does not return unreachable podcasts" do

View file

@ -162,7 +162,7 @@ RSpec.describe "Api::V0::Webhooks", type: :request do
it "returns :created and json response on success" do
post api_webhooks_path, params: { webhook_endpoint: webhook_params }
expect(response).to have_http_status(:created)
expect(response.content_type).to eq("application/json")
expect(response.media_type).to eq("application/json")
json = JSON.parse(response.body)
expect(json["target_url"]).to eq(webhook_params[:target_url])
end
@ -205,7 +205,7 @@ RSpec.describe "Api::V0::Webhooks", type: :request do
it "renders index successfully" do
get api_webhooks_path, params: { access_token: access_token.token }
expect(response.content_type).to eq("application/json")
expect(response.media_type).to eq("application/json")
expect(response).to have_http_status(:ok)
end

View file

@ -9,7 +9,7 @@ RSpec.describe "Articles", type: :request do
create(:article, featured: true)
get "/feed"
expect(response.status).to eq(200)
expect(response.content_type).to eq("application/rss+xml")
expect(response.media_type).to eq("application/rss+xml")
end
it "contains the full app URL" do

View file

@ -11,7 +11,7 @@ RSpec.describe "BufferedArticles", type: :request do
it "responds with json" do
get buffered_articles_path
expect(response.content_type).to eq("application/json")
expect(response.media_type).to eq("application/json")
end
it "responds with at least one url" do

View file

@ -380,7 +380,7 @@ RSpec.describe "ChatChannelMemberships", type: :request do
end
it "returns in json" do
expect(response.content_type).to eq("application/json")
expect(response.media_type).to eq("application/json")
end
end
@ -392,7 +392,7 @@ RSpec.describe "ChatChannelMemberships", type: :request do
end
it "returns in json" do
expect(response.content_type).to eq("application/json")
expect(response.media_type).to eq("application/json")
end
end
end

View file

@ -286,7 +286,7 @@ RSpec.describe "Comments", type: :request do
end
it "returns json" do
expect(response.content_type).to eq("application/json")
expect(response.media_type).to eq("application/json")
end
end
end

View file

@ -48,7 +48,7 @@ RSpec.describe "Editor", type: :request do
it "returns json" do
sign_in user
post "/articles/preview", headers: headers
expect(response.content_type).to eq("application/json")
expect(response.media_type).to eq("application/json")
end
end
end

View file

@ -94,7 +94,7 @@ RSpec.describe "GithubRepos", type: :request do
post update_or_create_github_repos_path(params), headers: headers
expect(response).to have_http_status(:ok)
expect(response.content_type).to eq("application/json")
expect(response.media_type).to eq("application/json")
end
it "returns 404 if no repository is found" do

View file

@ -31,7 +31,7 @@ RSpec.describe "ImageUploads", type: :request do
it "returns json" do
post "/image_uploads", headers: headers
expect(response.content_type).to eq("application/json")
expect(response.media_type).to eq("application/json")
end
it "provides a link" do

View file

@ -32,7 +32,7 @@ RSpec.describe "Messages", type: :request do
end
it "returns in json" do
expect(response.content_type).to eq("application/json")
expect(response.media_type).to eq("application/json")
end
end
@ -68,7 +68,7 @@ RSpec.describe "Messages", type: :request do
end
it "returns in json" do
expect(response.content_type).to eq("application/json")
expect(response.media_type).to eq("application/json")
end
end
end
@ -100,7 +100,7 @@ RSpec.describe "Messages", type: :request do
end
it "returns in json" do
expect(response.content_type).to eq("application/json")
expect(response.media_type).to eq("application/json")
end
end
end

View file

@ -23,7 +23,7 @@ RSpec.describe "NotificationSubscriptions", type: :request do
it "returns a JSON response" do
get "/notification_subscriptions/Article/#{article.id}",
headers: headers
expect(response.content_type).to eq "application/json"
expect(response.media_type).to eq "application/json"
end
it "returns the correct subscription boolean as JSON" do
@ -43,7 +43,7 @@ RSpec.describe "NotificationSubscriptions", type: :request do
it "returns a JSON response 'null' if there is no logged in user" do
get "/notification_subscriptions/Article/#{article.id}", headers: headers
expect(response.body).to eq "null"
expect(response.content_type).to eq "application/json"
expect(response.media_type).to eq "application/json"
end
end

View file

@ -107,7 +107,9 @@ RSpec.describe "PageViews", type: :request do
it "updates a new page view time on page by 15" do
post "/page_views", params: { article_id: article.id }
put "/page_views/#{article.id}"
expect(PageView.last.time_tracked_in_seconds).to eq(30)
end

View file

@ -17,7 +17,7 @@ RSpec.describe "ResponseTemplate", type: :request do
it "responds with JSON" do
create(:response_template, user: user, type_of: "personal_comment")
get response_templates_path, headers: { HTTP_ACCEPT: "application/json" }
expect(response.content_type).to eq "application/json"
expect(response.media_type).to eq "application/json"
end
it "raises RoutingError if the format is not JSON" do
@ -61,7 +61,7 @@ RSpec.describe "ResponseTemplate", type: :request do
it "responds with JSON" do
create(:response_template, user: moderator, type_of: "personal_comment")
get response_templates_path, params: { type_of: "mod_comment" }, headers: { HTTP_ACCEPT: "application/json" }
expect(response.content_type).to eq "application/json"
expect(response.media_type).to eq "application/json"
end
it "returns the correct amount of moderator response templates" do

View file

@ -4,7 +4,7 @@ RSpec.describe "Sitemaps", type: :request do
describe "GET /sitemap-*" do
it "renders xml file" do
get "/sitemap-Mar-2011.xml"
expect(response.content_type).to eq("application/xml")
expect(response.media_type).to eq("application/xml")
end
it "renders not found if incorrect input" do
@ -33,7 +33,7 @@ RSpec.describe "Sitemaps", type: :request do
expect(response.body).to include("<loc>#{ApplicationConfig['APP_PROTOCOL']}#{ApplicationConfig['APP_DOMAIN']}#{article.path}</loc>")
expect(response.body).to include("<lastmod>#{article.last_comment_at.strftime('%F')}</lastmod>")
expect(response.body).not_to include(Article.last.path)
expect(response.content_type).to eq("application/xml")
expect(response.media_type).to eq("application/xml")
end
end
end

View file

@ -18,7 +18,7 @@ RSpec.describe "Stories::Feeds", type: :request do
it "renders article list as json" do
get "/stories/feed", headers: headers
expect(response.content_type).to eq("application/json")
expect(response.media_type).to eq("application/json")
expect(response_article).to include(
"id" => article.id,
"title" => title,

View file

@ -10,21 +10,21 @@ RSpec.describe "UserBlock", type: :request do
it "rejects when not-logged-in" do
sign_out(blocker)
get "/user_blocks/#{blocked.id}"
expect(response.content_type).to eq "application/json"
expect(response.media_type).to eq "application/json"
expect(response.status).to eq 401
expect(response.parsed_body["result"]).to eq "not-logged-in"
end
it "returns 'not-blocking' when the user is not blocked" do
get "/user_blocks/#{blocked.id}"
expect(response.content_type).to eq "application/json"
expect(response.media_type).to eq "application/json"
expect(response.parsed_body["result"]).to eq "not-blocking"
end
it "returns 'blocking' when blocking" do
create(:user_block, blocker: blocker, blocked: blocked)
get "/user_blocks/#{blocked.id}"
expect(response.content_type).to eq "application/json"
expect(response.media_type).to eq "application/json"
expect(response.parsed_body["result"]).to eq "blocking"
end
end
@ -33,7 +33,7 @@ RSpec.describe "UserBlock", type: :request do
it "renders 'not-logged-in' when not logged in" do
sign_out blocker
post "/user_blocks", params: { user_block: { blocked_id: blocked.id } }
expect(response.content_type).to eq "application/json"
expect(response.media_type).to eq "application/json"
expect(response.status).to eq 401
expect(response.parsed_body["result"]).to eq "not-logged-in"
end
@ -47,7 +47,7 @@ RSpec.describe "UserBlock", type: :request do
it "returns a JSON response with blocked" do
post "/user_blocks", params: { user_block: { blocked_id: blocked.id } }
expect(response.content_type).to eq "application/json"
expect(response.media_type).to eq "application/json"
expect(response.parsed_body["result"]).to eq "blocked"
end
@ -69,7 +69,7 @@ RSpec.describe "UserBlock", type: :request do
it "renders 'not-logged-in' when not logged in" do
sign_out blocker
delete "/user_blocks/#{blocked.id}", params: { user_block: { blocked_id: blocked.id } }
expect(response.content_type).to eq "application/json"
expect(response.media_type).to eq "application/json"
expect(response.status).to eq 401
expect(response.parsed_body["result"]).to eq "not-logged-in"
end
@ -78,7 +78,7 @@ RSpec.describe "UserBlock", type: :request do
UserBlock.delete_all
blocker.update(blocking_others_count: 0)
delete "/user_blocks/#{blocked.id}", params: { user_block: { blocked_id: blocked.id } }
expect(response.content_type).to eq "application/json"
expect(response.media_type).to eq "application/json"
expect(response.parsed_body["result"]).to eq "not-blocking-anyone"
end

View file

@ -38,7 +38,7 @@ RSpec.shared_examples "GET /api/analytics/:endpoint authorization examples" do |
before { get "/api/analytics/#{endpoint}?#{params}", headers: { "api-key" => pro_api_token.secret } }
it "renders JSON as the content type" do
expect(response.content_type).to eq "application/json"
expect(response.media_type).to eq "application/json"
end
end
@ -63,7 +63,7 @@ RSpec.shared_examples "GET /api/analytics/:endpoint authorization examples" do |
end
it "renders JSON as the content type" do
expect(response.content_type).to eq "application/json"
expect(response.media_type).to eq "application/json"
end
end

View file

@ -10,8 +10,9 @@ RSpec.describe "Notifications page", type: :system, js: true do
fill_in "comment-textarea-for-#{id}", with: "thanks i guess"
click_button("SUBMIT")
expect(page).to have_css("div.reply-sent-notice")
click_link("Check it out")
expect(page).to have_text(/thanks i guess/)
expect(page).to have_text("thanks i guess")
end
it "shows 1 notification and disappear after clicking it" do
@ -33,10 +34,14 @@ RSpec.describe "Notifications page", type: :system, js: true do
end
visit "/notifications"
expect(page).to have_css("div.single-notification")
click_button("heart")
expect(page).to have_css("img.reacted-emoji")
click_link("Reply")
validate_reply(leslie.comments.first.id)
end
@ -53,7 +58,7 @@ RSpec.describe "Notifications page", type: :system, js: true do
before do
dev_user = create(:user)
allow(User).to receive(:dev_account).and_return(dev_user)
alex.add_role :trusted
alex.add_role(:trusted)
end
def interact_with_each_emojis
@ -67,12 +72,16 @@ RSpec.describe "Notifications page", type: :system, js: true do
it "allows trusted user to moderate content" do
article = create(:article, user: alex)
comment = nil
sidekiq_perform_enqueued_jobs { comment = create(:comment, commentable: article, user: leslie) }
comment = create(:comment, commentable: article, user: leslie)
sidekiq_perform_enqueued_jobs
visit "/notifications"
expect(page).to have_css("div.single-notification")
interact_with_each_emojis
click_link("Reply")
validate_reply(comment.id)
end
end

Binary file not shown.

BIN
vendor/cache/actioncable-6.0.3.1.gem vendored Normal file

Binary file not shown.

BIN
vendor/cache/actionmailbox-6.0.3.1.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/actionmailer-6.0.3.1.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/actionpack-6.0.3.1.gem vendored Normal file

Binary file not shown.

BIN
vendor/cache/actiontext-6.0.3.1.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/actionview-6.0.3.1.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/activejob-6.0.3.1.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/activemodel-6.0.3.1.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/activerecord-6.0.3.1.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/activestorage-6.0.3.1.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/activesupport-6.0.3.1.gem vendored Normal file

Binary file not shown.

View file

@ -8,7 +8,7 @@ Gem::Specification.new do |s|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
s.require_paths = ["lib".freeze]
s.authors = ["Tom Cocca".freeze]
s.date = "2020-05-26"
s.date = "2020-06-01"
s.description = "acts_as_follower is a Rubygem to allow any model to follow any other model. This is accomplished through a double polymorphic relationship on the Follow model. There is also built in support for blocking/un-blocking follow records. Main uses would be for Users to follow other Users or for Users to follow Books, etc\u2026 (Basically, to develop the type of follow system that GitHub has)".freeze
s.email = ["tom dot cocca at gmail dot com".freeze]
s.files = [".gitignore".freeze, ".travis.yml".freeze, "Gemfile".freeze, "MIT-LICENSE".freeze, "README.rdoc".freeze, "Rakefile".freeze, "acts_as_follower.gemspec".freeze, "init.rb".freeze, "lib/acts_as_follower.rb".freeze, "lib/acts_as_follower/follow_scopes.rb".freeze, "lib/acts_as_follower/followable.rb".freeze, "lib/acts_as_follower/follower.rb".freeze, "lib/acts_as_follower/follower_lib.rb".freeze, "lib/acts_as_follower/railtie.rb".freeze, "lib/acts_as_follower/version.rb".freeze, "lib/generators/USAGE".freeze, "lib/generators/acts_as_follower_generator.rb".freeze, "lib/generators/templates/migration.rb".freeze, "lib/generators/templates/model.rb".freeze, "test/README".freeze, "test/acts_as_followable_test.rb".freeze, "test/acts_as_follower_test.rb".freeze, "test/dummy30/Gemfile".freeze, "test/dummy30/Rakefile".freeze, "test/dummy30/app/models/application_record.rb".freeze, "test/dummy30/app/models/band.rb".freeze, "test/dummy30/app/models/band/punk.rb".freeze, "test/dummy30/app/models/band/punk/pop_punk.rb".freeze, "test/dummy30/app/models/custom_record.rb".freeze, "test/dummy30/app/models/some.rb".freeze, "test/dummy30/app/models/user.rb".freeze, "test/dummy30/config.ru".freeze, "test/dummy30/config/application.rb".freeze, "test/dummy30/config/boot.rb".freeze, "test/dummy30/config/database.yml".freeze, "test/dummy30/config/environment.rb".freeze, "test/dummy30/config/environments/development.rb".freeze, "test/dummy30/config/environments/test.rb".freeze, "test/dummy30/config/initializers/backtrace_silencers.rb".freeze, "test/dummy30/config/initializers/inflections.rb".freeze, "test/dummy30/config/initializers/secret_token.rb".freeze, "test/dummy30/config/initializers/session_store.rb".freeze, "test/dummy30/config/locales/en.yml".freeze, "test/dummy30/config/routes.rb".freeze, "test/factories/bands.rb".freeze, "test/factories/somes.rb".freeze, "test/factories/users.rb".freeze, "test/follow_test.rb".freeze, "test/schema.rb".freeze, "test/test_helper.rb".freeze]

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/rails-6.0.3.1.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/railties-6.0.3.1.gem vendored Normal file

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,14 @@
/.bundle/
/.yardoc
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/
# rspec failure tracking
.rspec_status
# Ignore gemset
/.gem

View file

@ -0,0 +1,3 @@
--format documentation
--color
--require spec_helper

View file

@ -0,0 +1,68 @@
sudo: false
language: ruby
cache: bundler
rvm:
- 1.9.3
- 2.2.10
- 2.3.8
- 2.4.7
- 2.5.6
- 2.6.4
- jruby-9.2.8.0
before_install: gem install bundler -v 1.17.3
gemfile:
- gemfiles/rails-3.2.gemfile
- gemfiles/rails-4.0.gemfile
- gemfiles/rails-4.1.gemfile
- gemfiles/rails-4.2.gemfile
- gemfiles/rails-5.0.gemfile
- gemfiles/rails-5.1.gemfile
- gemfiles/rails-5.2.gemfile
- gemfiles/rails-6.0.gemfile
- gemfiles/rails-edge.gemfile
env:
global: RAILS_ENV=test
before_script:
- echo $BUNDLE_GEMFILE
- bundle install
script:
- bundle exec rspec --format documentation
matrix:
fast_finish: true
exclude:
- rvm: 1.9.3
- gemfile: gemfiles/rails-edge.gemfile
- rvm: 2.2.10
gemfile: gemfiles/rails-6.0.gemfile
- rvm: 2.3.8
gemfile: gemfiles/rails-6.0.gemfile
- rvm: 2.4.7
gemfile: gemfiles/rails-4.0.gemfile
- rvm: 2.4.7
gemfile: gemfiles/rails-4.1.gemfile
- rvm: 2.4.7
gemfile: gemfiles/rails-6.0.gemfile
- rvm: 2.5.6
gemfile: gemfiles/rails-3.2.gemfile
- rvm: 2.5.6
gemfile: gemfiles/rails-4.0.gemfile
- rvm: 2.5.6
gemfile: gemfiles/rails-4.1.gemfile
- rvm: 2.6.4
gemfile: gemfiles/rails-4.0.gemfile
- rvm: 2.6.4
gemfile: gemfiles/rails-4.1.gemfile
include:
- rvm: 2.5.6
gemfile: gemfiles/rails-edge.gemfile
- rvm: 1.9.3
gemfile: gemfiles/rails-3.2.gemfile
allow_failures:
- rvm: 1.9.3 # bundler wont install the gems
- gemfile: gemfiles/rails-edge.gemfile
- rvm: jruby-9.2.8.0
notifications:
email: false
slack:
rooms:
secure: F4BGVLUnaDqJ3YXfuIwx+m6047E8YstCUXs33Tfcs7SUlSuOSChuXqvCfVtnfNy2muF7xgB6VRL3xpFIRm7qNStqGUWCQJXmKq2OEgq1DYGkhAVle4d/LBtVcfBgeLelsoi+1TI9MrUtpZDHPl0li3PLoC+dq7rzSuhrxQ9EOhZlZGVn6LTeVcgNw6cLNzHSWJJ8zpYWLjBWUXgJ75MQvo5qaNbQxyfzm7GzEgRNfSzabFBwpKwB1Tog9X9TKTtPrn30O9Ur9+wmTu6EnwaDWZjaTK6I+AbxE8huIfUGvSrq1aV2JaDIra6zHEQ+d4j0oRYutgFM4YfyN9124MbPE2yH/5lXNQHMpUOsP0bl2U+KGDzq/V5APyrZ6irsvwGYpo3fSXrW8nDIAK4Mh8KB+Ta0zN5H8PmIRK76wJ+wG2zAtrfl+ailxMrdpK6J04fl3pCBuO6eW+AKEJ7Wfi5GiE7a9lk/YewAeDHyyLSnUNFIP0/iFAbTtRh5denCk0ZUS1XyfZNQuFoku7jk5lpe41SNItqOO0jv/jXPF+wensNa2UgMBIP0XkRw55LKn9eY0MKm9P+zp9ePaXs0T0Ttv4e0T4Jxrgf5QBynefgHwAsOI1nHr7GhlPaFQ6u8iNmjNYLB9v1JZMlO08LkytzZFpUuJoHbYYoBaRtUtEosBHg=

View file

@ -0,0 +1,3 @@
source "https://rubygems.org"
gemspec

View file

@ -0,0 +1,15 @@
# License
Copyright (c) 2019, Timber Technologies, Inc.
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.

View file

@ -0,0 +1,14 @@
# 🌲 Timber Integration For Rails
[![ISC License](https://img.shields.io/badge/license-ISC-ff69b4.svg)](LICENSE.md)
[![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](http://www.rubydoc.info/github/timberio/timber-ruby-rails)
[![Build Status](https://travis-ci.org/timberio/timber-ruby-rails.svg?branch=master)](https://travis-ci.org/timberio/timber-ruby-rails)
This library integrates the
[`timber` Ruby library](https://github.com/timberio/timber-ruby) with the
[rails](https://github.com/rails/rails) framework, turning your rails logs into
rich structured events.
- **Sign-up: [https://app.timber.io](https://app.timber.io)**
- **Documentation:
[https://docs.timber.io/setup/languages/ruby/integrations/rails](https://docs.timber.io/setup/languages/ruby/integrations/rails)**

View file

@ -0,0 +1,6 @@
require "bundler/gem_tasks"
require "rspec/core/rake_task"
RSpec::Core::RakeTask.new(:spec)
task :default => :spec

View file

@ -0,0 +1,14 @@
#!/usr/bin/env ruby
require "bundler/setup"
require "timber-rails"
# You can add fixtures and/or initialization code here to make experimenting
# with your gem easier. You can also use a different console, if you like.
# (If you use this, don't forget to add pry to your Gemfile!)
# require "pry"
# Pry.start
require "irb"
IRB.start(__FILE__)

View file

@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
set -vx
bundle install
# Do any other automated setup that you need to do here

View file

@ -0,0 +1,8 @@
source 'https://rubygems.org'
gem 'rails', '~> 3.0.0'
gem 'timber',
gem 'timber-rack'
gemspec :path => '../'

View file

@ -0,0 +1,8 @@
source 'https://rubygems.org'
gem 'rails', '~> 3.1.0'
gem 'timber'
gem 'timber-rack'
gemspec :path => '../'

View file

@ -0,0 +1,8 @@
source 'https://rubygems.org'
gem 'rails', '~> 3.2.0'
gem 'timber'
gem 'timber-rack'
gemspec :path => '../'

View file

@ -0,0 +1,12 @@
source 'https://rubygems.org'
gem 'rails', '~> 4.0.0'
gem 'timber'
gem 'timber-rack'
if RUBY_PLATFORM == "java"
gem 'mime-types', '2.6.2'
end
gemspec :path => '../'

View file

@ -0,0 +1,12 @@
source 'https://rubygems.org'
gem 'rails', '~> 4.1.0'
gem 'timber'
gem 'timber-rack'
if RUBY_PLATFORM == "java"
gem 'mime-types', '2.6.2'
end
gemspec :path => '../'

View file

@ -0,0 +1,12 @@
source 'https://rubygems.org'
gem 'rails', '~> 4.2.0'
gem 'timber'
gem 'timber-rack'
if RUBY_PLATFORM == "java"
gem 'mime-types', '2.6.2'
end
gemspec :path => '../'

View file

@ -0,0 +1,12 @@
source 'https://rubygems.org'
gem 'rails', '~> 5.0.0'
gem 'timber'
gem 'timber-rack'
if RUBY_PLATFORM == "java"
gem 'mime-types', '2.6.2'
end
gemspec :path => '../'

View file

@ -0,0 +1,12 @@
source 'https://rubygems.org'
gem 'rails', '~> 5.1.0'
gem 'timber'
gem 'timber-rack'
if RUBY_PLATFORM == "java"
gem 'mime-types', '2.6.2'
end
gemspec :path => '../'

View file

@ -0,0 +1,12 @@
source 'https://rubygems.org'
gem 'rails', '~> 5.2.0'
gem 'timber'
gem 'timber-rack'
if RUBY_PLATFORM == "java"
gem 'mime-types', '2.6.2'
end
gemspec :path => '../'

View file

@ -0,0 +1,12 @@
source 'https://rubygems.org'
gem 'rails', '~> 6.0.0'
gem 'timber'
gem 'timber-rack'
if RUBY_PLATFORM == "java"
gem 'mime-types', '2.6.2'
end
gemspec :path => '../'

View file

@ -0,0 +1,10 @@
source 'https://rubygems.org'
gem 'rack', git: 'https://github.com/rack/rack', branch: 'master'
gem 'arel', git: 'https://github.com/rails/arel', branch: 'master'
gem 'rails', git: 'https://github.com/rails/rails', branch: 'master'
gem 'timber'
gem 'timber-rack'
gemspec :path => '../'

View file

@ -0,0 +1,65 @@
require "timber-rails/overrides"
require "timber"
require "rails"
require "timber-rails/active_support_log_subscriber"
require "timber-rails/config"
require "timber-rails/railtie"
require "timber-rack/http_context"
require "timber-rack/http_events"
require "timber-rack/user_context"
require "timber-rails/session_context"
require "timber-rails/rack_logger"
require "timber-rails/error_event"
require "timber-rails/action_controller"
require "timber-rails/action_dispatch"
require "timber-rails/action_view"
require "timber-rails/active_record"
require "timber-rails/logger"
module Timber
module Integrations
# Module for holding *all* Rails integrations. This module does *not*
# extend {Integration} because it's dependent on {Rack::HTTPEvents}. This
# module simply disables the default HTTP request logging.
module Rails
def self.enabled?
Timber::Integrations::Rack::HTTPEvents.enabled?
end
def self.integrate!
return false if !enabled?
ActionController.integrate!
ActionDispatch.integrate!
ActionView.integrate!
ActiveRecord.integrate!
RackLogger.integrate!
end
def self.enabled=(value)
Timber::Integrations::Rails::ErrorEvent.enabled = value
Timber::Integrations::Rack::HTTPContext.enabled = value
Timber::Integrations::Rack::HTTPEvents.enabled = value
Timber::Integrations::Rack::UserContext.enabled = value
SessionContext.enabled = value
ActionController.enabled = value
ActionView.enabled = value
ActiveRecord.enabled = value
end
# All enabled middlewares. The order is relevant. Middlewares that set
# context are added first so that context is included in subsequent log lines.
def self.middlewares
@middlewares ||= [Timber::Integrations::Rack::HTTPContext, SessionContext, Timber::Integrations::Rack::UserContext,
Timber::Integrations::Rack::HTTPEvents, Timber::Integrations::Rails::ErrorEvent].select(&:enabled?)
end
end
end
end

View file

@ -0,0 +1,17 @@
require "timber-rails/action_controller/log_subscriber"
module Timber
module Integrations
# Module for holding *all* ActionController integrations. See {Integration} for
# configuration details for all integrations.
module ActionController
extend Integration
def self.integrate!
return false if !enabled?
LogSubscriber.integrate!
end
end
end
end

View file

@ -0,0 +1,25 @@
module Timber
module Integrations
module ActionController
# Responsible for removing the default ActionController::LogSubscriber and installing
# the TimberLogSubscriber
#
# @private
class LogSubscriber < Integrator
def initialize
require "action_controller/log_subscriber"
require "timber-rails/action_controller/log_subscriber/timber_log_subscriber"
rescue LoadError => e
raise RequirementNotMetError.new(e.message)
end
def integrate!
return true if Timber::Integrations::Rails::ActiveSupportLogSubscriber.subscribed?(:action_controller, TimberLogSubscriber)
Timber::Integrations::Rails::ActiveSupportLogSubscriber.unsubscribe!(:action_controller, ::ActionController::LogSubscriber)
TimberLogSubscriber.attach_to(:action_controller)
end
end
end
end
end

View file

@ -0,0 +1,46 @@
module Timber
module Integrations
module ActionController
class LogSubscriber < Integrator
# The log subscriber that replaces the default `ActionController::LogSubscriber`.
# The intent of this subscriber is to, as transparently as possible, properly
# track events that are being logged here. This LogSubscriber will never change
# default behavior / log messages.
#
# @private
class TimberLogSubscriber < ::ActionController::LogSubscriber
def start_processing(event)
return true if silence?
info do
payload = event.payload
params = payload[:params].except(*INTERNAL_PARAMS)
format = extract_format(payload)
format = format.to_s.upcase if format.is_a?(Symbol)
Events::ControllerCall.new(
controller: payload[:controller],
action: payload[:action],
format: format,
params: params
)
end
end
private
def extract_format(payload)
if payload.key?(:format)
payload[:format] # rails > 4.X
elsif payload.key?(:formats)
payload[:formats].first # rails 3.X
end
end
def silence?
ActionController.silence?
end
end
end
end
end
end

View file

@ -0,0 +1,20 @@
require "timber-rails/action_dispatch/debug_exceptions"
module Timber
module Integrations
# Module for holding *all* ActionDispatch integrations. This
# module simply disables the exception tracking middleware so that our middleware
# works as expected.
module ActionDispatch
def self.enabled?
Rails::ErrorEvent.enabled?
end
def self.integrate!
return false if !enabled?
DebugExceptions.integrate!
end
end
end
end

View file

@ -0,0 +1,51 @@
module Timber
module Integrations
module ActionDispatch
# Reponsible for disabled logging in the ActionDispatch::DebugExceptions
# Rack middleware. We cannot simply remove the middleware because it is
# coupled with displaying an exception debug screen if debug exceptions is enabled.
#
# @private
class DebugExceptions < Integrator
# Patch for disabling logging
#
# @private
module InstanceMethods
def self.included(klass)
klass.class_eval do
private
def logger(*args)
nil
end
end
end
end
def initialize
begin
# Rails >= 3.1
require "action_dispatch/middleware/debug_exceptions"
rescue LoadError
# Rails < 3.1
require "action_dispatch/middleware/show_exceptions"
end
rescue LoadError => e
raise RequirementNotMetError.new(e.message)
end
def integrate!
if defined?(::ActionDispatch::DebugExceptions) && !::ActionDispatch::DebugExceptions.include?(InstanceMethods)
::ActionDispatch::DebugExceptions.send(:include, InstanceMethods)
end
if defined?(::ActionDispatch::ShowExceptions) && !::ActionDispatch::ShowExceptions.include?(InstanceMethods)
::ActionDispatch::ShowExceptions.send(:include, InstanceMethods)
end
true
end
end
end
end
end

Some files were not shown because too many files have changed in this diff Show more