Skip to content

start integrating Option into ActiveRecord #4

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

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
17 changes: 11 additions & 6 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@ source 'https://rubygems.org'
# Specify your gem's dependencies in errgonomic.gemspec
gemspec

gem 'rake', '~> 13.0', group: :development
gem 'rspec', '~> 3.0', group: :development
gem 'rubocop', group: :development
gem 'rubocop-yard', group: :development
gem 'solargraph', group: :development
group :development do
gem 'rake', '~> 13.0'
gem 'rspec', '~> 3.0'
gem 'rubocop'
gem 'rubocop-yard'
gem 'solargraph'
gem 'activerecord'
gem 'sqlite3'
gem 'minitest'
end

# gem "standard", "~> 1.3", group: :development
# gem "standard", "~> 1.3"
35 changes: 35 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,36 @@ PATH
GEM
remote: https://rubygems.org/
specs:
activemodel (8.0.2)
activesupport (= 8.0.2)
activerecord (8.0.2)
activemodel (= 8.0.2)
activesupport (= 8.0.2)
timeout (>= 0.4.0)
activesupport (8.0.2)
base64
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
uri (>= 0.13.1)
ast (2.4.2)
backport (1.2.0)
base64 (0.2.0)
benchmark (0.4.0)
bigdecimal (3.1.9)
concurrent-ruby (1.3.5)
connection_pool (2.5.1)
diff-lcs (1.6.0)
drb (2.2.1)
i18n (1.14.7)
concurrent-ruby (~> 1.0)
jaro_winkler (1.6.0)
json (2.10.1)
kramdown (2.5.1)
Expand Down Expand Up @@ -69,6 +94,7 @@ GEM
rubocop (~> 1.21)
yard
ruby-progressbar (1.13.0)
securerandom (0.4.1)
solargraph (0.52.0)
backport (~> 1.2)
benchmark
Expand All @@ -88,11 +114,17 @@ GEM
tilt (~> 2.0)
yard (~> 0.9, >= 0.9.24)
yard-solargraph (~> 0.1)
sqlite3 (2.6.0)
mini_portile2 (~> 2.8.0)
thor (1.3.2)
tilt (2.6.0)
timeout (0.4.3)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (3.1.4)
unicode-emoji (~> 4.0, >= 4.0.4)
unicode-emoji (4.0.4)
uri (1.0.3)
yard (0.9.37)
yard-doctest (0.1.17)
minitest
Expand All @@ -104,12 +136,15 @@ PLATFORMS
ruby

DEPENDENCIES
activerecord
errgonomic!
minitest
rake (~> 13.0)
rspec (~> 3.0)
rubocop
rubocop-yard
solargraph
sqlite3
yard (~> 0.9)
yard-doctest (~> 0.1)

Expand Down
136 changes: 136 additions & 0 deletions gemset.nix
Original file line number Diff line number Diff line change
@@ -1,4 +1,37 @@
{
activemodel = {
dependencies = ["activesupport"];
groups = ["default" "development"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0v35y2jzqlfy1wnrzlzj2cxylhnz09vykaa1l2dnkq7sl5zzpq8a";
type = "gem";
};
version = "8.0.2";
};
activerecord = {
dependencies = ["activemodel" "activesupport" "timeout"];
groups = ["development"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "02nrya34qviawdkssyahb3mg08kqdc461b320a6ikr245jwp0d3r";
type = "gem";
};
version = "8.0.2";
};
activesupport = {
dependencies = ["base64" "benchmark" "bigdecimal" "concurrent-ruby" "connection_pool" "drb" "i18n" "logger" "minitest" "securerandom" "tzinfo" "uri"];
groups = ["default" "development"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0pm40y64wfc50a9sj87kxvil2102rmpdcbv82zf0r40vlgdwsrc5";
type = "gem";
};
version = "8.0.2";
};
ast = {
groups = ["default"];
platforms = [];
Expand All @@ -19,6 +52,16 @@
};
version = "1.2.0";
};
base64 = {
groups = ["default" "development"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "01qml0yilb9basf7is2614skjp8384h2pycfx86cr8023arfj98g";
type = "gem";
};
version = "0.2.0";
};
benchmark = {
groups = ["default"];
platforms = [];
Expand All @@ -29,6 +72,16 @@
};
version = "0.4.0";
};
bigdecimal = {
groups = ["default" "development"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1k6qzammv9r6b2cw3siasaik18i6wjc5m0gw5nfdc6jj64h79z1g";
type = "gem";
};
version = "3.1.9";
};
concurrent-ruby = {
groups = ["default"];
platforms = [];
Expand All @@ -39,6 +92,16 @@
};
version = "1.3.5";
};
connection_pool = {
groups = ["default" "development"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "171yzazg2wccbc545hwsx85sba91k7k1imir3c88385mlj82m05f";
type = "gem";
};
version = "2.5.1";
};
diff-lcs = {
groups = ["default"];
platforms = [];
Expand All @@ -49,6 +112,16 @@
};
version = "1.6.0";
};
drb = {
groups = ["default" "development"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0h5kbj9hvg5hb3c7l425zpds0vb42phvln2knab8nmazg2zp5m79";
type = "gem";
};
version = "2.2.1";
};
errgonomic = {
dependencies = ["concurrent-ruby"];
groups = ["default"];
Expand All @@ -59,6 +132,17 @@
};
version = "0.2.0";
};
i18n = {
dependencies = ["concurrent-ruby"];
groups = ["default" "development"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "03sx3ahz1v5kbqjwxj48msw3maplpp2iyzs22l4jrzrqh4zmgfnf";
type = "gem";
};
version = "1.14.7";
};
jaro_winkler = {
groups = ["default"];
platforms = [];
Expand Down Expand Up @@ -362,6 +446,16 @@
};
version = "1.13.0";
};
securerandom = {
groups = ["default" "development"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1cd0iriqfsf1z91qg271sm88xjnfd92b832z49p1nd542ka96lfc";
type = "gem";
};
version = "0.4.1";
};
solargraph = {
dependencies = ["backport" "benchmark" "diff-lcs" "jaro_winkler" "kramdown" "kramdown-parser-gfm" "logger" "observer" "ostruct" "parser" "rbs" "reverse_markdown" "rubocop" "thor" "tilt" "yard" "yard-solargraph"];
groups = ["default"];
Expand All @@ -373,6 +467,17 @@
};
version = "0.52.0";
};
sqlite3 = {
dependencies = ["mini_portile2"];
groups = ["development"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0573vgz5ck0hqr8h132ln0hczx53m21h4w42n1p75rj837qjbim1";
type = "gem";
};
version = "2.6.0";
};
thor = {
groups = ["default"];
platforms = [];
Expand All @@ -393,6 +498,27 @@
};
version = "2.6.0";
};
timeout = {
groups = ["default" "development"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "03p31w5ghqfsbz5mcjzvwgkw3h9lbvbknqvrdliy8pxmn9wz02cm";
type = "gem";
};
version = "0.4.3";
};
tzinfo = {
dependencies = ["concurrent-ruby"];
groups = ["default" "development"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "16w2g84dzaf3z13gxyzlzbf748kylk5bdgg3n1ipvkvvqy685bwd";
type = "gem";
};
version = "2.0.6";
};
unicode-display_width = {
dependencies = ["unicode-emoji"];
groups = ["default"];
Expand All @@ -414,6 +540,16 @@
};
version = "4.0.4";
};
uri = {
groups = ["default" "development"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "04bhfvc25b07jaiaf62yrach7khhr5jlr5bx6nygg8pf11329wp9";
type = "gem";
};
version = "1.0.3";
};
yard = {
groups = ["development"];
platforms = [];
Expand Down
3 changes: 3 additions & 0 deletions lib/errgonomic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
require_relative 'errgonomic/option'
require_relative 'errgonomic/result'

# Rails fu
require_relative 'errgonomic/rails' if defined?(Rails::Railtie)

# Errgonomic adds opinionated abstractions to handle errors in a way that blends
# Rust and Ruby ergonomics. This library leans on Rails conventions for some
# presence-related methods; when in doubt, make those feel like Rails. It also
Expand Down
40 changes: 40 additions & 0 deletions lib/errgonomic/rails.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
require_relative 'option'
require_relative 'rails/active_record_optional'
require_relative 'rails/active_record_delegate_optional'

module Errgonomic
# Rails specific functionality to integrate Errgonomic with minimum fuss.
module Rails
# We provide helper class methods, like `delegate_optional`,
# which need to be included into ActiveRecord::Base before any models are
# evaluated.
def self.setup_before
ActiveRecord::Base.include(Errgonomic::Rails::ActiveRecordDelegateOptional)
end

# Wrapping optional associations requires that we include the module after
# the class is first evaluated, so that it can define its associations for
# later reflection.
def self.setup_after
ActiveRecord::Base.descendants.each do |model|
model.include Errgonomic::Rails::ActiveRecordOptional if model.table_name
end
end
end
end

# TODO: Implement a Railtie to hook in the setup_before and setup_after at the
# appropriate times for the Rails application lifecycle, in dev and prod.
#
# if defined?(Rails::Railtie)
# module Errgonomic::Rails
# class Railtie < Rails::Railtie
# initializer 'errgonomic.rails.setup_before' do
# Errgonomic::Rails.setup_before
# end
# initializer 'errgonomic.rails.setup_after' do
# Errgonomic::Rails.setup_after
# end
# end
# end
# end
22 changes: 22 additions & 0 deletions lib/errgonomic/rails/active_record_delegate_optional.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module Errgonomic
module Rails
module ActiveRecordDelegateOptional
extend ActiveSupport::Concern

class_methods do
def delegate_optional(*methods, to: nil, prefix: nil, private: nil)
return if to.nil?

methods.each do |method_name|
prefixed_method_name = prefix == true ? "#{to}_#{method_name}" : method_name
class_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{prefixed_method_name}
#{to}.map { |obj| obj.send(:#{method_name}) }
end
RUBY
end
end
end
end
end
end
Loading
Loading