Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Rails >= 6.0 and Ruby >= 3 #4

Merged
merged 9 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/ruby.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby

name: Ruby

on:
push:
branches: ['master']
pull_request:
branches: ['master']
schedule:
- cron: '0 0 * * 0'

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
ruby-version: ['3.0', '3.1']
activerecord: ['6.0', '6.1', '7.0', '7.1']
env:
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/rails_${{ matrix.activerecord }}.gemfile
steps:
- uses: actions/checkout@v3
- name: Set up Ruby
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
# change this to (see https://github.com/ruby/setup-ruby#versioning):
# uses: ruby/setup-ruby@v1
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby-version }}
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- name: Run tests
run: bundle exec rake
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@
*.sqlite3
/.rdoc
/spec/examples.txt
.ruby-version
gemfiles/*.lock
Gemfile.lock
coverage/*
1 change: 1 addition & 0 deletions .ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.0.6
35 changes: 0 additions & 35 deletions .travis.yml

This file was deleted.

19 changes: 19 additions & 0 deletions Appraisals
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
appraise "rails-6.0" do
gem 'rails', '~> 6.0'
gem "rspec-rails", '~> 5'
cysjonathan marked this conversation as resolved.
Show resolved Hide resolved
end

appraise "rails-6.1" do
gem 'rails', '~> 6.1'
gem "rspec-rails", '>= 6'
end

appraise "rails-7.0" do
gem 'rails', '~> 7.0'
gem "rspec-rails", '>= 6'
end

appraise "rails-7.1" do
gem 'rails', '~> 7.1'
gem "rspec-rails", '>= 6'
end
66 changes: 39 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,46 @@

## Overview

Userstamp extends `ActiveRecord::Base` to add automatic updating of `creator`, `updater`, and
Userstamp extends `ActiveRecord::Base` to add automatic updating of `creator`, `updater`, and
`deleter` attributes. It is based loosely on `ActiveRecord::Timestamp`.

Two class methods (`model_stamper` and `stampable`) are implemented in this gem. The `model_stamper`
method is used in models that are responsible for creating, updating, or deleting other objects.
Typically this would be the `User` model of your application. The `stampable` method is used in
Typically this would be the `User` model of your application. The `stampable` method is used in
models that are subject to being created, updated, or deleted by stampers.

## Forkception

This is a fork of:

- the [magiclabs-userstamp](https://github.com/magiclabs/userstamp) gem
- which is a fork of [Michael Grosser's](https://github.com/grosser)
[userstamp gem] (https://github.com/grosser/userstamp)
- which is a fork of the original [userstamp plugin](https://github.com/delynn/userstamp) by
[delynn](https://github.com/delynn)
- the [magiclabs-userstamp](https://github.com/magiclabs/userstamp) gem
- which is a fork of [Michael Grosser's](https://github.com/grosser)
[userstamp gem] (https://github.com/grosser/userstamp)
- which is a fork of the original [userstamp plugin](https://github.com/delynn/userstamp) by
[delynn](https://github.com/delynn)

In addition to these, I have cherry picked ideas and changes from the following forks:

- [simplificator](https://github.com/simplificator/userstamp)
- [akm](https://github.com/akm/magic_userstamp)
- [konvenit](https://github.com/konvenit/userstamp)
- [simplificator](https://github.com/simplificator/userstamp)
- [akm](https://github.com/akm/magic_userstamp)
- [konvenit](https://github.com/konvenit/userstamp)

Finally, this gem only supports Ruby 2.0 and above. Yes, you really should upgrade to a supported
version of Ruby. This gem is tested only on Rails 4.2; but it should work with Rails 4+.
Finally, this gem only supports Ruby 3.0 and 3.1. Yes, you really should upgrade to a supported
version of Ruby. This gem is tested only on Rails 6 - 7; thus far, we have successfully tested it
to be compatible with Rails 6.0, 6.1, 7.0, and 7.1

## Features

### Soft-deletes

The reason for this is because the original userstamp plugin does not support databases utilising
soft deletes. They are not tested explicitly within this gem, but it is expected to work with the
following gems:

- [acts_as_paranoid](https://github.com/ActsAsParanoid/acts_as_paranoid)
- [paranoia](https://github.com/radar/paranoia)
- [acts_as_paranoid](https://github.com/ActsAsParanoid/acts_as_paranoid)
- [paranoia](https://github.com/radar/paranoia)

The `stampable` method has been modified to allow additional arguments to be passed to the
The `stampable` method has been modified to allow additional arguments to be passed to the
creator/updater relations. This allows declarations like:

```ruby
Expand All @@ -51,16 +54,18 @@ to result in a `belongs_to` relation which looks like:
belongs_to :creator, class_name: '::User', foreign_key: :created_by, with_deleted: true
```

Do create a ticket if it is broken, with a pull-request if possible.
Do create a ticket if it is broken, with a pull-request if possible.

### Customisable column names/types

While examining the userstamp gem's network on Github, it was noticed that quite a few forks were
made to allow customisability in the name and type of the column with the database migration.

This gem now supports customised column names. See the [usage](#usage) section on the
configuration options supported.

### Saving before validation

This fork includes changes to perform model stamping before validation. This allows models to
enforce the presence of stamp attributes:

Expand All @@ -73,7 +78,8 @@ Furthermore, the `creator` attribute is set only if the value is blank allowing
override.

## Usage
Assume that we are building a blog application, with User and Post objects. Add the following

Assume that we are building a blog application, with User and Post objects. Add the following
to the application's Gemfile:

```ruby
Expand Down Expand Up @@ -135,9 +141,10 @@ Declare the stamper on the User model:
If your stamper is called `User`, that's it; you're done.

## Customisation

The association which is created on each of the `creator_id`, `updater_id`, and `deleter_id` can
be customised. Also, the stamper used by each class can also be customised. For this purpose, the
`ActiveRecord::Base.stampable` method can be used:
`ActiveRecord::Base.stampable` method can be used:

```ruby
class Post < ActiveRecord::Base
Expand All @@ -150,8 +157,10 @@ It also allows you to specify the name of the stamper for the class being declar
arguments are passed to the `belongs_to` declaration.

## Upgrading

### Upgrading from delynn's 1.x/2.x with `compatibility_mode`
The major difference between 1.x and 2.x is the naming of the columns. This version of the gem

The major difference between 1.x and 2.x is the naming of the columns. This version of the gem
allows specifying the name of the column from the gem configuration:

```ruby
Expand All @@ -163,6 +172,7 @@ end
```

### Upgrading from delynn's 2.x without `compatibility_mode`

Within migrations, it was possible to declare `t.userstamps` within a table definition. It used
to accept one argument, which declares whether the deleter column should be created. This has
been changed to respect the gem configuration's `deleter_attribute`. If that is `nil`, then no
Expand All @@ -182,16 +192,18 @@ Configure the gem to use those names (as above) and remove all `stampable` decla
There is no need to include the `Userstamp` module in `ApplicationController`.

## Tests

Run

$ bundle exec rspec

## Authors
- [DeLynn Berry](http://delynnberry.com/): The original idea for this plugin came from the Rails
Wiki article entitled
[Extending ActiveRecord](http://wiki.rubyonrails.com/rails/pages/ExtendingActiveRecordExample)
- [Michael Grosser](http://pragmatig.com)
- [John Dell](http://blog.spovich.com/)
- [Chris Hilton](https://github.com/chrismhilton)
- [Thomas von Deyen](https://github.com/tvdeyen)
- [Joel Low](http://joelsplace.sg)

- [DeLynn Berry](http://delynnberry.com/): The original idea for this plugin came from the Rails
Wiki article entitled
[Extending ActiveRecord](http://wiki.rubyonrails.com/rails/pages/ExtendingActiveRecordExample)
- [Michael Grosser](http://pragmatig.com)
- [John Dell](http://blog.spovich.com/)
- [Chris Hilton](https://github.com/chrismhilton)
- [Thomas von Deyen](https://github.com/tvdeyen)
- [Joel Low](http://joelsplace.sg)
24 changes: 7 additions & 17 deletions activerecord-userstamp.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,29 @@ require 'active_record/userstamp/version'
Gem::Specification.new do |s|
s.name = 'activerecord-userstamp'
s.version = ActiveRecord::Userstamp::VERSION
s.authors = ['Joel Low']
s.email = ['[email protected]']
s.authors = ['Bivan Alzacky Harmanto']
s.email = ['[email protected]']

s.summary = 'Adds magic creator and updater attributes to your ActiveRecord models.'
s.description = 'This gem extends ActiveRecord::Base to add automatic updating of created_by and updated_by attributes of your models in much the same way that the ActiveRecord::Timestamp module updates created_(at/on) and updated_(at/on) attributes.'
s.homepage = 'https://github.com/lowjoel/activerecord-userstamp'
s.homepage = 'https://github.com/Coursemology/activerecord-userstamp'
s.license = 'MIT'

s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
s.require_paths = ['lib']

if ENV['CI'] == 'true'
rails_version =
case ENV['RAILS_VERSION']
when nil, ''
'>= 4.1'
else
"~> #{ENV['RAILS_VERSION']}"
end
else
rails_version = '>= 6'
end
s.add_dependency 'rails', '>= 6'

s.add_dependency 'rails', rails_version
s.required_ruby_version = ">= 3.0"

s.add_development_dependency 'tzinfo-data' if RUBY_PLATFORM =~ /mswin|mingw/
s.add_development_dependency 'rake'
s.add_development_dependency 'rdoc'
s.add_development_dependency 'rspec-rails', '>= 3.3'
s.add_development_dependency 'simplecov'
s.add_development_dependency 'coveralls'
s.add_development_dependency 'codeclimate-test-reporter'
s.add_development_dependency 'sqlite3'
s.add_development_dependency 'sqlite3', "~> 1.7"
s.add_development_dependency "appraisal", "~> 2.1"
end
8 changes: 8 additions & 0 deletions gemfiles/rails_6.0.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# This file was generated by Appraisal

source "https://rubygems.org"

gem "rails", "~> 6.0"
gem "rspec-rails", "~> 5"

gemspec path: "../"
8 changes: 8 additions & 0 deletions gemfiles/rails_6.1.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# This file was generated by Appraisal

source "https://rubygems.org"

gem "rails", "~> 6.1"
gem "rspec-rails", ">= 6"

gemspec path: "../"
8 changes: 8 additions & 0 deletions gemfiles/rails_7.0.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# This file was generated by Appraisal

source "https://rubygems.org"

gem "rails", "~> 7.0"
gem "rspec-rails", ">= 6"

gemspec path: "../"
8 changes: 8 additions & 0 deletions gemfiles/rails_7.1.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# This file was generated by Appraisal

source "https://rubygems.org"

gem "rails", "~> 7.1"
gem "rspec-rails", ">= 6"

gemspec path: "../"
12 changes: 6 additions & 6 deletions lib/active_record/userstamp/migration_additions.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
module ActiveRecord::Userstamp::MigrationHelper
module ActiveRecord::Userstamp::MigrationAdditions
extend ActiveSupport::Concern

def userstamps(*args)
def userstamps(**args)
config = ActiveRecord::Userstamp.config
column(config.creator_attribute, :integer, *args)
column(config.updater_attribute, :integer, *args)
column(config.deleter_attribute, :integer, *args) if config.deleter_attribute.present?
column(config.creator_attribute, :integer, **args)
column(config.updater_attribute, :integer, **args)
column(config.deleter_attribute, :integer, **args) if config.deleter_attribute.present?
end
end

ActiveRecord::ConnectionAdapters::TableDefinition.class_eval do
include ActiveRecord::Userstamp::MigrationHelper
include ActiveRecord::Userstamp::MigrationAdditions
end
3 changes: 1 addition & 2 deletions lib/active_record/userstamp/stampable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@ def add_userstamp_associations(options)
belongs_to :updater, **relation_options.reverse_merge(foreign_key: config.updater_attribute) if
associations.second
if associations.third
relation_options.reverse_merge!(required: false) if ActiveRecord::VERSION::MAJOR >= 5 ||
(ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR >= 2)
relation_options.reverse_merge!(required: false)
belongs_to :deleter, **relation_options.reverse_merge(foreign_key: config.deleter_attribute)
end
end
Expand Down
Loading
Loading