Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
JackDanger authored Oct 16, 2019
2 parents 129b4c4 + 7fefd72 commit 39583fe
Show file tree
Hide file tree
Showing 20 changed files with 196 additions and 100 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/gempush.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Ruby Gem

on:
push:
branches:
- master

jobs:
build:
name: gem publishing
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@master
- name: Set up Ruby 2.6
uses: actions/setup-ruby@v1
with:
ruby-version: 2.6.x

- name: Publish to RubyGems
run: |
mkdir -p $HOME/.gem
touch $HOME/.gem/credentials
chmod 0600 $HOME/.gem/credentials
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
bin/gempush-if-changed
env:
GEM_HOST_API_KEY: ${{secrets.RUBYGEMS_AUTH_TOKEN}}
32 changes: 32 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Tests

on: push

jobs:
ci:
name: CI
runs-on: ubuntu-latest
strategy:
matrix:
ruby:
- '2.3.x'
- '2.4.x'
- '2.5.x'
- '2.6.x'
rails:
- '5.0.7.2'
- '5.1.7'
- '5.2.3'
steps:
- name: Install system dependencies
run: sudo apt-get install -y libsqlite3-dev
- uses: actions/checkout@master
- name: Setup ruby
uses: actions/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
architecture: 'x64'
- run: gem install bundler && bundle && bundle exec rake
env:
AR_TEST_VERSION: ${{ matrix.rails }}

8 changes: 8 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
require: rubocop-performance

inherit_from: .rubocop_todo.yml

AllCops:
Exclude:
- bin/*
TargetRubyVersion: 2.2

Metrics/BlockLength:
Enabled: false

Metrics/LineLength:
Max: 120
Expand Down
7 changes: 7 additions & 0 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2019-10-15 13:32:11 +0200 using RuboCop version 0.68.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
13 changes: 8 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
language: ruby
rvm:
- 2.0.0
- 2.2.2
- 2.3.0
- 2.2.10
- 2.3.8
- 2.4.9
- 2.5.7
- 2.6.5
env:
- AR_TEST_VERSION: 4.2.0
- AR_TEST_VERSION: 4.2.5
- AR_TEST_VERSION: 5.0.7.2
- AR_TEST_VERSION: 5.1.7
- AR_TEST_VERSION: 5.2.3
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# PermanentRecords (Rails 3.1+)
# PermanentRecords (Rails 5)

[http://github.com/JackDanger/permanent_records/](http://github.com/JackDanger/permanent_records/)

Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
PermanentRecords (Rails 3.1+)
PermanentRecords (Rails 5)
=============================

http://github.com/JackDanger/permanent_records/
Expand Down
4 changes: 2 additions & 2 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ task :pandoc do
system('pandoc -s -r markdown -w rst README.md -o README.rst')
end

task publish: [:pandoc, :rubocop, :rspec] do
task publish: %i[pandoc rubocop rspec] do
# Ensure the gem builds
system('gem build permanent_records.gemspec') &&
# And we didn't leave anything (aside from the gem) uncommitted
Expand All @@ -46,4 +46,4 @@ task publish: [:pandoc, :rubocop, :rspec] do
system("gem push permanent_records-#{version}.gem")
end

task default: [:rspec, :rubocop]
task default: %i[rspec rubocop]
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4.2.7
4.2.8
8 changes: 8 additions & 0 deletions bin/gempush-if-changed
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash

set -x
if git diff --name-only HEAD..HEAD^ | egrep -q '^VERSION$'; then
# The VERSION file changed in the last commit, build the gem and push
gem build *.gemspec
gem push *.gem
fi
1 change: 1 addition & 0 deletions github-actions-test.yml
55 changes: 29 additions & 26 deletions lib/permanent_records.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def self.included(base)
end
end

def is_permanent? # rubocop:disable Style/PredicateName
def is_permanent? # rubocop:disable Naming/PredicateName
respond_to?(:deleted_at)
end

Expand Down Expand Up @@ -51,7 +51,7 @@ def destroy(force = nil)
if !is_permanent? || PermanentRecords.should_force_destroy?(force)
permanently_delete_records_after { super() }
else
destroy_with_permanent_records force
destroy_with_permanent_records(force)
end
end
end
Expand All @@ -68,21 +68,22 @@ def revival # rubocop:disable Metrics/MethodLength
set_deleted_at(nil, validate)
# increment all associated counters for counter cache
each_counter_cache do |assoc_class, counter_cache_column, assoc_id|
assoc_class.increment_counter counter_cache_column, assoc_id
assoc_class.increment_counter(counter_cache_column, assoc_id)
end
true
end
end
]
end

def get_deleted_record # rubocop:disable Style/AccessorMethodName
def get_deleted_record # rubocop:disable Naming/AccessorMethodName
self.class.unscoped.find(id)
end

# rubocop:disable Metrics/MethodLength
def set_deleted_at(value, force = nil)
return self unless is_permanent?

record = get_deleted_record
record.deleted_at = value
begin
Expand All @@ -97,14 +98,16 @@ def set_deleted_at(value, force = nil)
end

@attributes = record.instance_variable_get('@attributes')
rescue => e
rescue StandardError => e
# trigger dependent record destruction (they were revived before this
# record, which cannot be revived due to validations)
record.destroy
raise e
end
end

# rubocop:enable Metrics/MethodLength

def each_counter_cache
_reflections.each do |name, reflection|
association = respond_to?(name.to_sym) ? send(name.to_sym) : nil
Expand All @@ -113,12 +116,11 @@ def each_counter_cache

associated_class = association.class

yield(associated_class,
reflection.counter_cache_column,
send(reflection.foreign_key))
yield(associated_class, reflection.counter_cache_column, send(reflection.foreign_key))
end
end

# rubocop:disable Metrics/MethodLength
def destroy_with_permanent_records(force = nil)
run_callbacks(:destroy) do
if deleted? || new_record?
Expand All @@ -127,13 +129,14 @@ def destroy_with_permanent_records(force = nil)
set_deleted_at(Time.now, force)
# decrement all associated counters for counter cache
each_counter_cache do |assoc_class, counter_cache_column, assoc_id|
assoc_class.decrement_counter counter_cache_column, assoc_id
assoc_class.decrement_counter(counter_cache_column, assoc_id)
end
end
true
end
deleted? ? self : false
end
# rubocop:enable Metrics/MethodLength

def add_record_window(_request, name, reflection)
send(name).unscope(where: :deleted_at).where(
Expand All @@ -147,31 +150,30 @@ def add_record_window(_request, name, reflection)
)
end

# TODO: Feel free to refactor this without polluting the ActiveRecord
# namespace.
# rubocop:disable Metrics/AbcSize
# TODO: Feel free to refactor this without polluting the ActiveRecord namespace.
def revive_destroyed_dependent_records(force = nil)
destroyed_dependent_relations.each do |relation|
relation.to_a.each { |destroyed_dependent_record| destroyed_dependent_record.try(:revive, force) }
end
reload
end

# rubocop:disable Metrics/MethodLength
def destroyed_dependent_relations
PermanentRecords.dependent_permanent_reflections(self.class).map do |name, relation|
cardinality = relation.macro.to_s.gsub('has_', '').to_sym
case cardinality
when :many
case relation.macro.to_sym
when :has_many
if deleted_at
add_record_window(send(name), name, relation)
else
send(name).unscope(where: :deleted_at)
end
when :one, :belongs_to
when :has_one, :belongs_to
self.class.unscoped { Array(send(name)) }
end
end
end
# rubocop:enable Metrics/MethodLength

def attempt_notifying_observers(callback)
notify_observers(callback)
Expand All @@ -187,6 +189,7 @@ def dependent_record_ids
.reduce({}) do |records, (key, _)|
found = Array(send(key)).compact
next records if found.empty?

records.update found.first.class => found.map(&:id)
end
end
Expand All @@ -211,6 +214,7 @@ def permanently_delete_records(dependent_records)
ids.each do |id|
record = klass.unscoped.where(klass.primary_key => id).first
next unless record

record.deleted_at = nil
record.destroy(:force)
end
Expand All @@ -231,25 +235,25 @@ def not_deleted

# Included into ActiveRecord for all models
module IsPermanent
def is_permanent? # rubocop:disable Style/PredicateName
columns.detect { |c| 'deleted_at' == c.name }
def is_permanent? # rubocop:disable Naming/PredicateName
columns.detect { |c| c.name == 'deleted_at' }
end
end

def self.should_force_destroy?(force)
if force.is_a?(Hash)
force[:force]
else
:force == force
force == :force
end
end

def self.should_revive_parent_first?(order)
order.is_a?(Hash) && true == order[:reverse]
order.is_a?(Hash) && order[:reverse] == true
end

def self.should_ignore_validations?(force)
force.is_a?(Hash) && false == force[:validate]
force.is_a?(Hash) && force[:validate] == false
end

def self.dependent_record_window
Expand All @@ -275,10 +279,9 @@ def self.dependent_permanent_reflections(klass)
end

ActiveSupport.on_load(:active_record) do
ActiveRecord::Base.send :include, PermanentRecords::ActiveRecord
ActiveRecord::Base.send(:include, PermanentRecords::ActiveRecord)

if [ActiveRecord::VERSION::MAJOR, ActiveRecord::VERSION::MINOR] == [5, 2] ||
ActiveRecord::VERSION::MAJOR > 5
require 'permanent_records/active_record_5_2'
end
if [ActiveRecord::VERSION::MAJOR, ActiveRecord::VERSION::MINOR] == [5, 2] || ActiveRecord::VERSION::MAJOR > 5
require 'permanent_records/active_record_5_2'
end
end
35 changes: 21 additions & 14 deletions lib/permanent_records/active_record_5_2.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# rubocop:disable Metrics/AbcSize
# Support destroy for rails belongs_to assocations.
module HandlePermanentRecordsDestroyedInBelongsToAssociation
def handle_dependency
return unless load_target
Expand All @@ -12,22 +14,27 @@ def handle_dependency
end
end

# rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/CyclomaticComplexity
# Support destroy for rails 5.2. has_on associations.
module HandlePermanentRecordsDestroyedInHasOneAssociation
def delete(method = options[:dependent])
if load_target
case method
when :delete
target.delete
when :destroy
target.destroyed_by_association = reflection
target.destroy
throw(:abort) if target.respond_to?(:deleted?) && !target.deleted?
when :nullify
target.update_columns(reflection.foreign_key => nil) if target.persisted?
end
return unless load_target

case method
when :delete
target.delete
when :destroy
target.destroyed_by_association = reflection
target.destroy
throw(:abort) if target.respond_to?(:deleted?) && !target.deleted?
when :nullify
target.update_columns(reflection.foreign_key => nil) if target.persisted?
end
end
end

ActiveRecord::Associations::BelongsToAssociation.prepend HandlePermanentRecordsDestroyedInBelongsToAssociation
ActiveRecord::Associations::HasOneAssociation.prepend HandlePermanentRecordsDestroyedInHasOneAssociation
# rubocop:enable Metrics/CyclomaticComplexity
# rubocop:enable Metrics/MethodLength
# rubocop:enable Metrics/AbcSize
ActiveRecord::Associations::BelongsToAssociation.prepend(HandlePermanentRecordsDestroyedInBelongsToAssociation)
ActiveRecord::Associations::HasOneAssociation.prepend(HandlePermanentRecordsDestroyedInHasOneAssociation)
Loading

0 comments on commit 39583fe

Please sign in to comment.