Skip to content

Commit

Permalink
Modern Ruby + ActiveRecord, Update Travis Config (attr-encrypted#416)
Browse files Browse the repository at this point in the history
* Update Travis configuration

* Drop os, use default

* Use focal for OS

* Restore patch versions of ruby, rvm not pulling latest patch

* Update local test/run.sh script for easier local testing

* Add some old AR back, remove 3+ rubies, drop deprecated codeclimate gem

* Lock sqlite3 for Ruby 2.5

* ActiveRecord 6.0 and 6.1 tests failing, add later

* Drop 2.5

* Update gemspec, pry for dev support

* 5.1.1 AR works, update test/run.sh

* Fix support for ActiveRecord 5.2
  • Loading branch information
joshbranham authored and WillRogers727 committed Feb 27, 2023
1 parent 028ec5e commit 82f6d70
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 132 deletions.
57 changes: 6 additions & 51 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,59 +1,14 @@
sudo: false
language: ruby
dist: focal
os: linux
cache: bundler
rvm:
- 2.0
- 2.1
- 2.2.2
- 2.3.0
- 2.4.0
- 2.5.0
- rbx
- 2.6.10
- 2.7.6
env:
- ACTIVERECORD=3.0.0
- ACTIVERECORD=3.1.0
- ACTIVERECORD=3.2.0
- ACTIVERECORD=4.0.0
- ACTIVERECORD=4.1.0
- ACTIVERECORD=4.2.0
- ACTIVERECORD=5.0.0
- ACTIVERECORD=5.1.1
matrix:
exclude:
- rvm: 2.0
env: ACTIVERECORD=5.0.0
- rvm: 2.0
env: ACTIVERECORD=5.1.1
- rvm: 2.1
env: ACTIVERECORD=5.0.0
- rvm: 2.1
env: ACTIVERECORD=5.1.1
- rvm: 2.4.0
env: ACTIVERECORD=3.0.0
- rvm: 2.4.0
env: ACTIVERECORD=3.1.0
- rvm: 2.4.0
env: ACTIVERECORD=3.2.0
- rvm: 2.4.0
env: ACTIVERECORD=4.0.0
- rvm: 2.4.0
env: ACTIVERECORD=4.1.0
- rvm: 2.5.0
env: ACTIVERECORD=3.0.0
- rvm: 2.5.0
env: ACTIVERECORD=3.1.0
- rvm: 2.5.0
env: ACTIVERECORD=3.2.0
- rvm: 2.5.0
env: ACTIVERECORD=4.0.0
- rvm: 2.5.0
env: ACTIVERECORD=4.1.0
- rvm: rbx
env: ACTIVERECORD=5.0.0
- rvm: rbx
env: ACTIVERECORD=5.1.1
allow_failures:
- rvm: rbx
- ACTIVERECORD=5.2.8
jobs:
fast_finish: true
addons:
code_climate:
Expand Down
11 changes: 2 additions & 9 deletions attr_encrypted.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,12 @@ Gem::Specification.new do |s|
s.homepage = 'http://github.com/attr-encrypted/attr_encrypted'
s.license = 'MIT'

s.has_rdoc = false
s.rdoc_options = ['--line-numbers', '--inline-source', '--main', 'README.rdoc']

s.require_paths = ['lib']

s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- test/*`.split("\n")

s.required_ruby_version = '>= 2.0.0'
s.required_ruby_version = '>= 2.6.0'

s.add_dependency('encryptor', ['~> 3.0.0'])
# support for testing with specific active record version
Expand All @@ -42,20 +39,16 @@ Gem::Specification.new do |s|
s.add_development_dependency('rake')
s.add_development_dependency('minitest')
s.add_development_dependency('sequel')
if RUBY_VERSION < '2.1.0'
s.add_development_dependency('nokogiri', '< 1.7.0')
s.add_development_dependency('public_suffix', '< 3.0.0')
end
if defined?(RUBY_ENGINE) && RUBY_ENGINE.to_sym == :jruby
s.add_development_dependency('activerecord-jdbcsqlite3-adapter')
s.add_development_dependency('jdbc-sqlite3', '< 3.8.7') # 3.8.7 is nice and broke
else
s.add_development_dependency('sqlite3')
end
s.add_development_dependency('dm-sqlite-adapter')
s.add_development_dependency('pry')
s.add_development_dependency('simplecov')
s.add_development_dependency('simplecov-rcov')
s.add_development_dependency("codeclimate-test-reporter", '<= 0.6.0')

s.cert_chain = ['certs/saghaulor.pem']
s.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $0 =~ /gem\z/
Expand Down
25 changes: 16 additions & 9 deletions lib/attr_encrypted/adapters/active_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,28 +53,35 @@ def attr_encrypted(*attrs)
super
options = attrs.extract_options!
attr = attrs.pop
attribute attr if ::ActiveRecord::VERSION::STRING >= "5.1.0"
attribute attr
options.merge! encrypted_attributes[attr]

define_method("#{attr}_was") do
attribute_was(attr)
end

if ::ActiveRecord::VERSION::STRING >= "4.1"
define_method("#{attr}_changed?") do |options = {}|
attribute_changed?(attr, options)
end
else
define_method("#{attr}_changed?") do
attribute_changed?(attr)
end
define_method("#{attr}_changed?") do |options = {}|
attribute_changed?(attr, options)
end

define_method("#{attr}_change") do
attribute_change(attr)
end

define_method("#{attr}_with_dirtiness=") do |value|
## Source: https://github.com/priyankatapar/attr_encrypted/commit/7e8702bd5418c927a39d8dd72c0adbea522d5663
# In ActiveRecord 5.2+, due to changes to the way virtual
# attributes are handled, @attributes[attr].value is nil which
# breaks attribute_was. Setting it here returns us to the expected
# behavior.
if ::ActiveRecord::VERSION::STRING >= "5.2"
# This is needed support attribute_was before a record has
# been saved
set_attribute_was(attr, __send__(attr)) if value != __send__(attr)
# This is needed to support attribute_was after a record has
# been saved
@attributes.write_from_user(attr.to_s, value) if value != __send__(attr)
end
attribute_will_change!(attr) if value != __send__(attr)
__send__("#{attr}_without_dirtiness=", value)
end
Expand Down
98 changes: 47 additions & 51 deletions test/active_record_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,14 @@ def create_tables

ActiveRecord::MissingAttributeError = ActiveModel::MissingAttributeError unless defined?(ActiveRecord::MissingAttributeError)

if ::ActiveRecord::VERSION::STRING > "4.0"
module Rack
module Test
class UploadedFile; end
end
module Rack
module Test
class UploadedFile; end
end

require 'action_controller/metal/strong_parameters'
end

require 'action_controller/metal/strong_parameters'

class Person < ActiveRecord::Base
self.attr_encrypted_options[:mode] = :per_attribute_iv_and_salt
attr_encrypted :email, key: SECRET_KEY
Expand Down Expand Up @@ -106,7 +104,6 @@ class PersonWithSerialization < ActiveRecord::Base
class UserWithProtectedAttribute < ActiveRecord::Base
self.table_name = 'users'
attr_encrypted :password, key: SECRET_KEY
attr_protected :is_admin if ::ActiveRecord::VERSION::STRING < "4.0"
end

class PersonUsingAlias < ActiveRecord::Base
Expand Down Expand Up @@ -221,52 +218,53 @@ def test_attribute_was_works_when_options_for_old_encrypted_value_are_different_
assert_equal pw.reverse, account.password
end

if ::ActiveRecord::VERSION::STRING > "4.0"
def test_should_assign_attributes
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
@user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true).permit(:login)
assert_equal 'modified', @user.login
if ::ActiveRecord::VERSION::STRING >= "5.2"
def test_should_create_will_save_change_to_predicate
person = Person.create!(email: 'test@example.com')
refute person.will_save_change_to_email?
person.email = 'test@example.com'
refute person.will_save_change_to_email?
person.email = 'test2@example.com'
assert person.will_save_change_to_email?
end

def test_should_not_assign_protected_attributes
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
@user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true).permit(:login)
assert !@user.is_admin?
def test_should_create_saved_change_to_predicate
person = Person.create!(email: 'test@example.com')
assert person.saved_change_to_email?
person.reload
person.email = 'test@example.com'
refute person.saved_change_to_email?
person.email = nil
refute person.saved_change_to_email?
person.email = 'test2@example.com'
refute person.saved_change_to_email?
person.save
assert person.saved_change_to_email?
end
end

def test_should_raise_exception_if_not_permitted
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
assert_raises ActiveModel::ForbiddenAttributesError do
@user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true)
end
end
def test_should_assign_attributes
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
@user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true).permit(:login)
assert_equal 'modified', @user.login
end

def test_should_raise_exception_on_init_if_not_permitted
assert_raises ActiveModel::ForbiddenAttributesError do
@user = UserWithProtectedAttribute.new ActionController::Parameters.new(login: 'modified', is_admin: true)
end
end
else
def test_should_assign_attributes
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
@user.attributes = { login: 'modified', is_admin: true }
assert_equal 'modified', @user.login
end
def test_should_not_assign_protected_attributes
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
@user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true).permit(:login)
assert !@user.is_admin?
end

def test_should_not_assign_protected_attributes
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
@user.attributes = { login: 'modified', is_admin: true }
assert !@user.is_admin?
def test_should_raise_exception_if_not_permitted
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
assert_raises ActiveModel::ForbiddenAttributesError do
@user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true)
end
end

def test_should_assign_protected_attributes
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
if ::ActiveRecord::VERSION::STRING > "3.1"
@user.send(:assign_attributes, { login: 'modified', is_admin: true }, without_protection: true)
else
@user.send(:attributes=, { login: 'modified', is_admin: true }, false)
end
assert @user.is_admin?
def test_should_raise_exception_on_init_if_not_permitted
assert_raises ActiveModel::ForbiddenAttributesError do
@user = UserWithProtectedAttribute.new ActionController::Parameters.new(login: 'modified', is_admin: true)
end
end

Expand All @@ -291,11 +289,9 @@ def test_should_allow_proc_based_mode
assert_nil @person.encrypted_credentials_iv
end

if ::ActiveRecord::VERSION::STRING > "3.1"
def test_should_allow_assign_attributes_with_nil
@person = Person.new
assert_nil(@person.assign_attributes nil)
end
def test_should_allow_assign_attributes_with_nil
@person = Person.new
assert_nil(@person.assign_attributes nil)
end

def test_that_alias_encrypts_column
Expand Down
22 changes: 15 additions & 7 deletions test/run.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
#!/usr/bin/env sh -e
#!/usr/bin/env bash

for RUBY in 1.9.3 2.0.0 2.1 2.2
set -e

for RUBY in 2.6.10 2.7.6
do
for RAILS in 2.3.8 3.0.0 3.1.0 3.2.0 4.0.0 4.1.0 4.2.0
for ACTIVERECORD in 5.1.1 5.2.8
do
if [[ $RUBY -gt 1.9.3 && $RAILS -lt 4.0.0 ]]; then
continue
fi
RBENV_VERSION=$RUBY ACTIVERECORD=$RAILS bundle && bundle exec rake
echo ">>> Testing with Ruby ${RUBY} and ActiveRecord ${ACTIVERECORD}."
export RBENV_VERSION=$RUBY
export ACTIVERECORD=$ACTIVERECORD

rbenv install $RUBY --skip-existing
bundle install
bundle check
bundle exec rake test
rm Gemfile.lock
echo ">>> Finished testing with Ruby ${RUBY} and ActiveRecord ${ACTIVERECORD}."
done
done
7 changes: 2 additions & 5 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
# frozen_string_literal: true

require 'pry'
require 'simplecov'
require 'simplecov-rcov'
require "codeclimate-test-reporter"

SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
[
SimpleCov::Formatter::HTMLFormatter,
SimpleCov::Formatter::RcovFormatter,
CodeClimate::TestReporter::Formatter
SimpleCov::Formatter::RcovFormatter
]
)

SimpleCov.start do
add_filter 'test'
end

CodeClimate::TestReporter.start

require 'minitest/autorun'

# Rails 4.0.x pins to an old minitest
Expand Down

0 comments on commit 82f6d70

Please sign in to comment.