active_record-ingress 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 44f2df474320f208c7c2070f366716be97f2057418055d80c54977524c4ca03d
4
+ data.tar.gz: 98540cb40ca317ddcd15cb9a6a73fa1ee922c286f0cb314c5d9dd0f4a550c38f
5
+ SHA512:
6
+ metadata.gz: b39a3673edd55b026c911eb400e065de09e0505fc6a06e48bb289dcc37b947bbc1569a3a81644a0d27505bca48b52229ef389dd78087c32af2c8da5d8f5f86da
7
+ data.tar.gz: be2eeb6bb12243b606712df38f76995fed25db05082d9301b14c6e2447b445c854070dc00be0159b3707666ddb6322968539d0b5acd0b02a971f2b54942bf5dd
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2022-04-27
4
+
5
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in active_record-ingress.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "sqlite3"
11
+
12
+ gem "minitest", "~> 5.0"
13
+ gem "minitest-sprint"
data/Gemfile.lock ADDED
@@ -0,0 +1,44 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ active_record-ingress (0.1.0)
5
+ activerecord (>= 6.1)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activemodel (7.0.2.4)
11
+ activesupport (= 7.0.2.4)
12
+ activerecord (7.0.2.4)
13
+ activemodel (= 7.0.2.4)
14
+ activesupport (= 7.0.2.4)
15
+ activesupport (7.0.2.4)
16
+ concurrent-ruby (~> 1.0, >= 1.0.2)
17
+ i18n (>= 1.6, < 2)
18
+ minitest (>= 5.1)
19
+ tzinfo (~> 2.0)
20
+ concurrent-ruby (1.1.10)
21
+ i18n (1.10.0)
22
+ concurrent-ruby (~> 1.0)
23
+ minitest (5.15.0)
24
+ minitest-sprint (1.2.1)
25
+ path_expander (~> 1.1)
26
+ path_expander (1.1.0)
27
+ rake (13.0.6)
28
+ sqlite3 (1.4.2)
29
+ tzinfo (2.0.4)
30
+ concurrent-ruby (~> 1.0)
31
+
32
+ PLATFORMS
33
+ arm64-darwin-20
34
+ x86_64-linux
35
+
36
+ DEPENDENCIES
37
+ active_record-ingress!
38
+ minitest (~> 5.0)
39
+ minitest-sprint
40
+ rake (~> 13.0)
41
+ sqlite3
42
+
43
+ BUNDLED WITH
44
+ 2.3.11
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Kasper Timm Hansen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # ActiveRecord::Ingress
2
+
3
+ Pass control of Active Record methods to a dedicated object.
4
+
5
+ ## Usage
6
+
7
+ `ActiveRecord::Ingress` adds proxy forwarding method `ingressed` to any `ActiveRecord::Base` instance.
8
+
9
+ So `post.ingressed.update(title: "Updated title")` would look up a `Post::Ingresses::Update` class, instance and execute its `perform` method:
10
+
11
+ ```ruby
12
+ # app/models/post/ingresses/update.rb
13
+ class Post::Ingresses::Update < ActiveRecord::Ingress::Base
14
+ # Each ingress has `params`, containing any passed keyword arguments.
15
+ # This extracts `params[:title]` and Ruby's keyword arguments handling will prevent accepting other arguments.
16
+ def perform(title:)
17
+ post.update(title: title)
18
+ end
19
+ end
20
+ ```
21
+
22
+ Ingresses can be used to create other forwarding too. Here, a `post.ingressed.prepare` is added:
23
+
24
+ ```ruby
25
+ # app/models/post/ingresses/prepare.rb
26
+ class Post::Ingresses::Publish < ActiveRecord::Ingress::Base
27
+ def perform
28
+ # Forwards to `record.transaction`
29
+ transaction do
30
+ post.published!
31
+ Post::Promotions.recognize_recently_published post
32
+ end
33
+ end
34
+ end
35
+ ```
36
+
37
+ It's also possible to annotate an ingress on the model side so it's always used:
38
+
39
+ ```ruby
40
+ class Post < ActiveRecord::Base
41
+ ingressed :publish # defines `publish` that delegates to `ingressed.publish`
42
+ end
43
+ ```
44
+
45
+ ## Installation
46
+
47
+ Install the gem and add to the application's Gemfile by executing:
48
+
49
+ $ bundle add active_record-ingress
50
+
51
+ If bundler is not being used to manage dependencies, install the gem by executing:
52
+
53
+ $ gem install active_record-ingress
54
+
55
+ ## Development
56
+
57
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
58
+
59
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
60
+
61
+ ## Contributing
62
+
63
+ Bug reports and pull requests are welcome on GitHub at https://github.com/kaspth/active_record-ingress.
64
+
65
+ ## License
66
+
67
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/active_record/ingress/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "active_record-ingress"
7
+ spec.version = ActiveRecord::Ingress::VERSION
8
+ spec.authors = ["Kasper Timm Hansen"]
9
+ spec.email = ["hey@kaspth.com"]
10
+
11
+ spec.summary = "Pass control of Active Record methods to a dedicated object."
12
+ spec.homepage = "https://github.com/kaspth/active_record-ingress"
13
+ spec.license = "MIT"
14
+ spec.required_ruby_version = ">= 2.7.0"
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = spec.homepage
18
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
19
+
20
+ # Specify which files should be added to the gem when it is released.
21
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
+ spec.files = Dir.chdir(__dir__) do
23
+ `git ls-files -z`.split("\x0").reject do |f|
24
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
25
+ end
26
+ end
27
+ spec.bindir = "exe"
28
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
29
+ spec.require_paths = ["lib"]
30
+
31
+ spec.add_dependency "activerecord", ">= 6.1"
32
+ end
@@ -0,0 +1,22 @@
1
+ module ActiveRecord::Ingress::Base::Callbacks
2
+ extend ActiveSupport::Concern
3
+ include ActiveSupport::Callbacks
4
+
5
+ included do
6
+ define_callbacks :perform
7
+ end
8
+
9
+ class_methods do
10
+ def before_perform(...)
11
+ set_callback(:perform, :before, ...)
12
+ end
13
+
14
+ def after_perform(...)
15
+ set_callback(:perform, :after, ...)
16
+ end
17
+
18
+ def around_perform(...)
19
+ set_callback(:perform, :around, ...)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,40 @@
1
+ class ActiveRecord::Ingress::Base
2
+ require_relative "base/callbacks"
3
+ include Callbacks
4
+
5
+ singleton_class.attr_reader :perform_with_params
6
+
7
+ def initialize(record, params = {})
8
+ @record, @params = record, params
9
+ end
10
+
11
+ def self.inherited(klass)
12
+ if alias_name = klass.module_parent_name.chomp("::Ingresses").underscore.presence
13
+ alias_method alias_name, :record
14
+ end
15
+ end
16
+
17
+ def self.method_added(name)
18
+ if name == :perform
19
+ if instance_method(:perform).arity.nonzero?
20
+ @perform_with_params = ->(params) { perform(**params.to_h) }
21
+ else
22
+ @perform_with_params = ->(params) { perform }
23
+ end
24
+ end
25
+ end
26
+
27
+ def self.run(...)
28
+ new(...).run
29
+ end
30
+
31
+ def run
32
+ run_callbacks :perform do
33
+ instance_exec(params, &self.class.perform_with_params)
34
+ end
35
+ end
36
+
37
+ private
38
+ attr_reader :record, :params
39
+ delegate :transaction, to: :record
40
+ end
@@ -0,0 +1,16 @@
1
+ class ActiveRecord::Ingress::Proxy
2
+ def initialize(record)
3
+ @__record__ = record
4
+ end
5
+
6
+ def method_missing(name, ...)
7
+ find_record_ingress_named(name).run(__record__, ...)
8
+ end
9
+
10
+ private
11
+ attr_reader :__record__
12
+
13
+ def find_record_ingress_named(name)
14
+ "#{__record__.class.name}::Ingresses::#{name.to_s.classify}".constantize
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Ingress
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "ingress/version"
4
+
5
+ module ActiveRecord::Ingress
6
+ autoload :Base, "active_record/ingress/base"
7
+ autoload :Proxy, "active_record/ingress/proxy"
8
+
9
+ module Integration
10
+ def ingressed
11
+ Proxy.new(self)
12
+ end
13
+ end
14
+
15
+ module Extension
16
+ def ingressed(*names)
17
+ delegate *names, to: :ingressed
18
+ end
19
+ end
20
+ end
21
+
22
+ ActiveSupport.on_load(:active_record) do
23
+ include ActiveRecord::Ingress::Integration
24
+ extend ActiveRecord::Ingress::Extension
25
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_record-ingress
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kasper Timm Hansen
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-04-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '6.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '6.1'
27
+ description:
28
+ email:
29
+ - hey@kaspth.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - CHANGELOG.md
35
+ - Gemfile
36
+ - Gemfile.lock
37
+ - LICENSE.txt
38
+ - README.md
39
+ - Rakefile
40
+ - active_record-ingress.gemspec
41
+ - lib/active_record/ingress.rb
42
+ - lib/active_record/ingress/base.rb
43
+ - lib/active_record/ingress/base/callbacks.rb
44
+ - lib/active_record/ingress/proxy.rb
45
+ - lib/active_record/ingress/version.rb
46
+ homepage: https://github.com/kaspth/active_record-ingress
47
+ licenses:
48
+ - MIT
49
+ metadata:
50
+ homepage_uri: https://github.com/kaspth/active_record-ingress
51
+ source_code_uri: https://github.com/kaspth/active_record-ingress
52
+ changelog_uri: https://github.com/kaspth/active_record-ingress/blob/main/CHANGELOG.md
53
+ post_install_message:
54
+ rdoc_options: []
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 2.7.0
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ requirements: []
68
+ rubygems_version: 3.3.11
69
+ signing_key:
70
+ specification_version: 4
71
+ summary: Pass control of Active Record methods to a dedicated object.
72
+ test_files: []