Skip to content

Commit

Permalink
Feature/alternative configs (#34)
Browse files Browse the repository at this point in the history
* feature/alternative-configs: implement alternative configs with module index method

Signed-off-by: Dusan <[email protected]>

* run formatting

Signed-off-by: Dusan <[email protected]>

* feature/alternative-configs: cleanup tests

Signed-off-by: Dusan <[email protected]>

* feature/alternative-configs: update readme

Signed-off-by: Dusan <[email protected]>

* update deps in gemfile

Signed-off-by: Dusan <[email protected]>

* update sqlite, reset modules between tests

Signed-off-by: Dusan <[email protected]>

* remove sqlite?

Signed-off-by: Dusan <[email protected]>

* use newer sqlite 1.x

Signed-off-by: Dusan <[email protected]>

* feature/alternative-configs: move version constant to Trackstamps

Signed-off-by: Dusan <[email protected]>

* rename test context to describe

Signed-off-by: Dusan <[email protected]>

* fix gemspec

Signed-off-by: Dusan <[email protected]>

* fix gemspec

Signed-off-by: Dusan <[email protected]>

* update email

Signed-off-by: Dusan <[email protected]>

* update email

Signed-off-by: Dusan <[email protected]>

* rubocop fix

Signed-off-by: Dusan <[email protected]>

* fix rubocop

Signed-off-by: Dusan <[email protected]>

* fix rubocop

Signed-off-by: Dusan <[email protected]>

* fix with model version

Signed-off-by: Dusan <[email protected]>

---------

Signed-off-by: Dusan <[email protected]>
  • Loading branch information
uvera authored Aug 25, 2024
1 parent a3e2221 commit 2aaf96b
Show file tree
Hide file tree
Showing 11 changed files with 218 additions and 81 deletions.
12 changes: 8 additions & 4 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ gem "activesupport", rails_version

gem "database_cleaner", "~> 2.0"
gem "rake", "~> 13.0"
gem "rspec", "~> 3.12"
gem "rubocop", "1.57.2"
gem "rspec", "~> 3.13"
gem "rubocop", "1.65.1"
gem "rubocop-packaging", "0.5.2"
gem "rubocop-performance", "1.19.1"
gem "rubocop-rake", "0.6.0"
gem "rubocop-rspec"
gem "sqlite3"
gem "with_model", "~> 2.0"
gem "sqlite3", "~> 1.7.3"
if rails_version == "~> 5.2.0"
gem "with_model", "~> 2.0"
else
gem "with_model", "~> 2.1.7"
end
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,19 @@ class ApplicationController < ActionController::Base

def set_trackstamps_user
Trackstamps::Reborn::Current.user = current_user
# or use your current attributes class with proc override in initializers
YourCurrentAttributesClass.user = current_user
end
end
```

### Override implementation for current user

```ruby
Trackstamps::Reborn.config.get_current_user = -> { YourCurrentAttributesClass.account }
## filename: config/initializers/trackstamps-reborn.rb
Trackstamps::Reborn.config.get_current_user = -> { YourCurrentAttributesClass.user }
# or
Trackstamps::Reborn[:alternative].config.get_current_user = -> { YourAlternativeCurrentAttributesClass.user }
```

### Generate migrations
Expand All @@ -48,9 +53,22 @@ rails generate trackstamps:reborn:migration table_name
```ruby
class Example < ActiveRecord::Base
include Trackstamps::Reborn
# or
include Trackstamps::Reborn[:whatever]
end
```

## Multiple configuration

Multiple configuration is achieved with module builder pattern utilizing `self.[]` method.
Upon calling

```ruby
Trackstamps::Reborn[:whatever]
```

specific module is cached in `::Concurrent::Map` instance.

## Support

If you want to report a bug, or have ideas, feedback or questions about the gem, [let me know via GitHub issues](https://github.com/uvera/trackstamps-reborn/issues/new) and I will do my best to provide a helpful answer. Happy hacking!
Expand Down
10 changes: 5 additions & 5 deletions lib/generators/trackstamps/reborn/migration_generator.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
require 'rails/generators/active_record'
require "rails/generators/active_record"

class Trackstamps::Reborn::MigrationGenerator < ::Rails::Generators::Base
include Rails::Generators::Migration

source_root File.expand_path('../templates', __FILE__)
argument :table, :type => :string, :default => "application"
desc 'Generate migration file required for trackstamps'
source_root File.expand_path("../templates", __FILE__)
argument :table, type: :string, default: "application"
desc "Generate migration file required for trackstamps"

def install
migration_template 'migration.rb', "db/migrate/add_trackstamps_to_#{table}.rb"
migration_template "migration.rb", "db/migrate/add_trackstamps_to_#{table}.rb"
end

def migration_data
Expand Down
84 changes: 84 additions & 0 deletions lib/trackstamps/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
require "active_support"
require "dry-configurable"

# rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/BlockLength, Style/ClassVars
module Trackstamps
module Base
@mixins = ::Concurrent::Map.new

class Current < ::ActiveSupport::CurrentAttributes
attribute :user
end

def self.[](instance_name=:default)
@mixins.fetch_or_store(instance_name.to_s) do
Module.new do
@@trackstamps_target_key = instance_name
const_set(:Current, Trackstamps::Base::Current)

extend Dry::Configurable
extend ActiveSupport::Concern
autoload :VERSION, "trackstamps/reborn/version"

setting :get_current_user, default: -> { Current.user }

setting :user_class_name, default: "User".freeze
setting :updater_foreign_key, default: "updated_by_id".freeze
setting :creator_foreign_key, default: "created_by_id".freeze

def trackstamps_current_user
Trackstamps::Base[@@trackstamps_target_key].config.get_current_user.call
end

def self.inspect
"Trackstamps::Reborn[:#{@@trackstamps_target_key}]"
end

def self.included(base)
trackstamps_module_self = self
base.class_eval do
before_save :trackstamps_set_updater
before_create :trackstamps_set_creator

const_set(:UPDATER_FOREIGN_KEY, trackstamps_module_self.config.updater_foreign_key.dup.freeze)

private_constant :UPDATER_FOREIGN_KEY

belongs_to :updater,
class_name: trackstamps_module_self.config.user_class_name,
foreign_key: const_get(:UPDATER_FOREIGN_KEY),
optional: true

const_set(:CREATOR_FOREIGN_KEY, trackstamps_module_self.config.creator_foreign_key.dup.freeze)
private_constant :CREATOR_FOREIGN_KEY

belongs_to :creator,
class_name: trackstamps_module_self.config.user_class_name,
foreign_key: const_get(:CREATOR_FOREIGN_KEY),
optional: true

def trackstamps_set_updater
return unless trackstamps_current_user

send(:"#{self.class.const_get(:UPDATER_FOREIGN_KEY)}=", trackstamps_current_user.id)
end

def trackstamps_set_creator
return unless trackstamps_current_user

send(:"#{self.class.const_get(:CREATOR_FOREIGN_KEY)}=", trackstamps_current_user.id)
end
end
end

class_methods do
def with_trackstamps
includes(:creator, :updater)
end
end
end
end
end
end
end
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/BlockLength, Style/ClassVars
61 changes: 5 additions & 56 deletions lib/trackstamps/reborn.rb
Original file line number Diff line number Diff line change
@@ -1,61 +1,10 @@
require "active_support"
require "trackstamps/reborn/current"
require "dry-configurable"
require_relative "base"

module Trackstamps
module Reborn
extend Dry::Configurable
extend ActiveSupport::Concern
autoload :VERSION, "trackstamps/reborn/version"

setting :get_current_user, default: -> { Trackstamps::Reborn::Current.user }

setting :user_class_name, default: "User".freeze
setting :updater_foreign_key, default: "updated_by_id".freeze
setting :creator_foreign_key, default: "created_by_id".freeze

def trackstamps_current_user
Trackstamps::Reborn.config.get_current_user.call
end

included do
before_save :trackstamps_set_updater
before_create :trackstamps_set_creator

const_set(:UPDATER_FOREIGN_KEY, Trackstamps::Reborn.config.updater_foreign_key.dup.freeze)

private_constant :UPDATER_FOREIGN_KEY

belongs_to :updater,
class_name: Trackstamps::Reborn.config.user_class_name,
foreign_key: const_get(:UPDATER_FOREIGN_KEY),
optional: true

const_set(:CREATOR_FOREIGN_KEY, Trackstamps::Reborn.config.creator_foreign_key.dup.freeze)
private_constant :CREATOR_FOREIGN_KEY

belongs_to :creator,
class_name: Trackstamps::Reborn.config.user_class_name,
foreign_key: const_get(:CREATOR_FOREIGN_KEY),
optional: true

def trackstamps_set_updater
return unless trackstamps_current_user

send("#{self.class.const_get(:UPDATER_FOREIGN_KEY)}=", trackstamps_current_user.id)
end

def trackstamps_set_creator
return unless trackstamps_current_user

send("#{self.class.const_get(:CREATOR_FOREIGN_KEY)}=", trackstamps_current_user.id)
end
end

class_methods do
def with_trackstamps
includes(:creator, :updater)
end
Reborn = Trackstamps::Base[:default]
Reborn.module_eval do
def self.[](instance_name)
Trackstamps::Base[instance_name]
end
end
end
7 changes: 0 additions & 7 deletions lib/trackstamps/reborn/current.rb

This file was deleted.

5 changes: 0 additions & 5 deletions lib/trackstamps/reborn/version.rb

This file was deleted.

3 changes: 3 additions & 0 deletions lib/trackstamps/version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module Trackstamps
VERSION = "0.1.1".freeze
end
1 change: 1 addition & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

RSpec.configure do |config|
config.before :suite do
RSpec.reset
ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
end

Expand Down
90 changes: 90 additions & 0 deletions spec/trackstamps/reborn_instance_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
RSpec.describe Trackstamps::Reborn do
describe "changing defaults is reflected in itself" do
before do
Trackstamps::Reborn.config.user_class_name = "Account"
end

it "is reflected" do
expect(Trackstamps::Reborn[:default].config.user_class_name).to eq("Account")
end
end

describe "changing another does not interfere with user class name" do
before do
Trackstamps::Reborn.config.user_class_name = "Default"
Trackstamps::Reborn[:alternative].config.user_class_name = "Alternative"
end

it "default is fine" do
expect(Trackstamps::Reborn[:default].config.user_class_name).to eq("Default")
end

it "alternative is fine" do
expect(Trackstamps::Reborn[:alternative].config.user_class_name).to eq("Alternative")
end
end

describe "changing another does not interfere with updater foreign key" do
before do
Trackstamps::Reborn.config.updater_foreign_key = "updater_default_id"
Trackstamps::Reborn[:alternative].config.updater_foreign_key = "updater_alternative_id"
end

it "default is fine" do
expect(Trackstamps::Reborn[:default].config.updater_foreign_key).to eq("updater_default_id")
end

it "alternative is fine" do
expect(Trackstamps::Reborn[:alternative].config.updater_foreign_key).to eq("updater_alternative_id")
end
end

describe "changing another does not interfere with creator foreign key" do
before do
Trackstamps::Reborn.config.creator_foreign_key = "creator_default_id"
Trackstamps::Reborn[:alternative].config.creator_foreign_key = "creator_alternative_id"
end

it "default is fine" do
expect(Trackstamps::Reborn[:default].config.creator_foreign_key).to eq("creator_default_id")
end

it "alternative is fine" do
expect(Trackstamps::Reborn[:alternative].config.creator_foreign_key).to eq("creator_alternative_id")
end
end

describe "changing another does not interfere with get current user proc" do
before do
Trackstamps::Reborn.config.get_current_user = -> { "default" }
Trackstamps::Reborn[:alternative].config.get_current_user = -> { "alternative" }
end

it "default is fine" do
expect(Trackstamps::Reborn[:default].config.get_current_user.call).to eq("default")
end

it "alternative is fine" do
expect(Trackstamps::Reborn[:alternative].config.get_current_user.call).to eq("alternative")
end
end

it "instance is only created once" do
instance_1 = Trackstamps::Reborn[:alternative]
instance_2 = Trackstamps::Reborn[:alternative]

expect(instance_1).to eq(instance_2)
end

it "different instances do not match" do
instance_1 = Trackstamps::Reborn[:default]
instance_2 = Trackstamps::Reborn[:alternative]

expect(instance_1).not_to eq(instance_2)
end

it "inspect works properly" do
instance = Trackstamps::Reborn[:inspected]
expect(instance.inspect).to eq("Trackstamps::Reborn[:inspected]")
end
end
6 changes: 3 additions & 3 deletions trackstamps-reborn.gemspec
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
require_relative "lib/trackstamps/reborn/version"
require_relative "lib/trackstamps/version"

Gem::Specification.new do |spec|
spec.name = "trackstamps-reborn"
spec.version = Trackstamps::Reborn::VERSION
spec.version = Trackstamps::VERSION
spec.authors = ["Dušan"]
spec.email = ["[email protected]"]
spec.email = ["[email protected]"]

spec.summary = ""
spec.homepage = "https://github.com/uvera/trackstamps-reborn"
Expand Down

0 comments on commit 2aaf96b

Please sign in to comment.