gifted 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2ece94319acfed183417eba523628e5114f26bcfd5c2a73d4bd0463c233147dd
4
+ data.tar.gz: 5dbbab9578f5e6f0019757fe4d6edd70c202030f43f17db6d69bcf88d1470e84
5
+ SHA512:
6
+ metadata.gz: 770cdc16ca0bd4e9cd5a04e4eb22dcad4e2202a0b2da3373a8ac3764354931d7736cb984654afd8b3f74c2be4e09bcec537d1947209a7827a0eea298cc058abb
7
+ data.tar.gz: 744873ea14f98a727f68fe9bdfffdaf4284615fab164c9781ead73bbe7c134855e9fc70be82e8cec9777afe5602cfd04731869673cdcf1edb50dc32194a5a87e
data/.DS_Store ADDED
Binary file
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.6.3
7
+ before_install: gem install bundler -v 2.0.1
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in gifted.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,176 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ gifted (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ actioncable (5.2.3)
10
+ actionpack (= 5.2.3)
11
+ nio4r (~> 2.0)
12
+ websocket-driver (>= 0.6.1)
13
+ actionmailer (5.2.3)
14
+ actionpack (= 5.2.3)
15
+ actionview (= 5.2.3)
16
+ activejob (= 5.2.3)
17
+ mail (~> 2.5, >= 2.5.4)
18
+ rails-dom-testing (~> 2.0)
19
+ actionpack (5.2.3)
20
+ actionview (= 5.2.3)
21
+ activesupport (= 5.2.3)
22
+ rack (~> 2.0)
23
+ rack-test (>= 0.6.3)
24
+ rails-dom-testing (~> 2.0)
25
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
26
+ actionview (5.2.3)
27
+ activesupport (= 5.2.3)
28
+ builder (~> 3.1)
29
+ erubi (~> 1.4)
30
+ rails-dom-testing (~> 2.0)
31
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
32
+ activejob (5.2.3)
33
+ activesupport (= 5.2.3)
34
+ globalid (>= 0.3.6)
35
+ activemodel (5.2.3)
36
+ activesupport (= 5.2.3)
37
+ activerecord (5.2.3)
38
+ activemodel (= 5.2.3)
39
+ activesupport (= 5.2.3)
40
+ arel (>= 9.0)
41
+ activestorage (5.2.3)
42
+ actionpack (= 5.2.3)
43
+ activerecord (= 5.2.3)
44
+ marcel (~> 0.3.1)
45
+ activesupport (5.2.3)
46
+ concurrent-ruby (~> 1.0, >= 1.0.2)
47
+ i18n (>= 0.7, < 2)
48
+ minitest (~> 5.1)
49
+ tzinfo (~> 1.1)
50
+ addressable (2.6.0)
51
+ public_suffix (>= 2.0.2, < 4.0)
52
+ arel (9.0.0)
53
+ builder (3.2.3)
54
+ byebug (11.0.1)
55
+ capybara (3.24.0)
56
+ addressable
57
+ mini_mime (>= 0.1.3)
58
+ nokogiri (~> 1.8)
59
+ rack (>= 1.6.0)
60
+ rack-test (>= 0.6.3)
61
+ regexp_parser (~> 1.5)
62
+ xpath (~> 3.2)
63
+ childprocess (1.0.1)
64
+ rake (< 13.0)
65
+ concurrent-ruby (1.1.5)
66
+ crass (1.0.4)
67
+ erubi (1.8.0)
68
+ globalid (0.4.2)
69
+ activesupport (>= 4.2.0)
70
+ i18n (1.6.0)
71
+ concurrent-ruby (~> 1.0)
72
+ json (2.2.0)
73
+ loofah (2.2.3)
74
+ crass (~> 1.0.2)
75
+ nokogiri (>= 1.5.9)
76
+ mail (2.7.1)
77
+ mini_mime (>= 0.1.1)
78
+ marcel (0.3.3)
79
+ mimemagic (~> 0.3.2)
80
+ method_source (0.9.2)
81
+ mimemagic (0.3.3)
82
+ mini_mime (1.0.1)
83
+ mini_portile2 (2.4.0)
84
+ minitest (5.11.3)
85
+ nio4r (2.3.1)
86
+ nokogiri (1.10.3)
87
+ mini_portile2 (~> 2.4.0)
88
+ power_assert (1.1.4)
89
+ public_suffix (3.1.0)
90
+ puma (3.12.1)
91
+ rack (2.0.7)
92
+ rack-test (1.1.0)
93
+ rack (>= 1.0, < 3)
94
+ rails (5.2.3)
95
+ actioncable (= 5.2.3)
96
+ actionmailer (= 5.2.3)
97
+ actionpack (= 5.2.3)
98
+ actionview (= 5.2.3)
99
+ activejob (= 5.2.3)
100
+ activemodel (= 5.2.3)
101
+ activerecord (= 5.2.3)
102
+ activestorage (= 5.2.3)
103
+ activesupport (= 5.2.3)
104
+ bundler (>= 1.3.0)
105
+ railties (= 5.2.3)
106
+ sprockets-rails (>= 2.0.0)
107
+ rails-dom-testing (2.0.3)
108
+ activesupport (>= 4.2.0)
109
+ nokogiri (>= 1.6)
110
+ rails-html-sanitizer (1.0.4)
111
+ loofah (~> 2.2, >= 2.2.2)
112
+ railties (5.2.3)
113
+ actionpack (= 5.2.3)
114
+ activesupport (= 5.2.3)
115
+ method_source
116
+ rake (>= 0.8.7)
117
+ thor (>= 0.19.0, < 2.0)
118
+ rake (10.5.0)
119
+ regexp_parser (1.5.1)
120
+ rr (1.2.1)
121
+ rubyzip (1.2.3)
122
+ selenium-webdriver (3.142.3)
123
+ childprocess (>= 0.5, < 2.0)
124
+ rubyzip (~> 1.2, >= 1.2.2)
125
+ sprockets (3.7.2)
126
+ concurrent-ruby (~> 1.0)
127
+ rack (> 1, < 3)
128
+ sprockets-rails (3.2.1)
129
+ actionpack (>= 4.0)
130
+ activesupport (>= 4.0)
131
+ sprockets (>= 3.0.0)
132
+ sqlite3 (1.4.1)
133
+ test-unit (3.3.3)
134
+ power_assert
135
+ test-unit-activesupport (1.0.9)
136
+ activesupport
137
+ test-unit
138
+ test-unit-capybara (1.0.7)
139
+ capybara (>= 2.1.0)
140
+ json
141
+ test-unit (>= 2.5.3)
142
+ test-unit-rails (5.2.2)
143
+ rails (>= 5.1.2)
144
+ test-unit (>= 3.1.7)
145
+ test-unit-activesupport (>= 1.0.8)
146
+ test-unit-capybara (>= 1.0.5)
147
+ test-unit-rr (>= 1.0.4)
148
+ test-unit-rr (1.0.5)
149
+ rr (>= 1.1.1)
150
+ test-unit (>= 2.5.2)
151
+ thor (0.20.3)
152
+ thread_safe (0.3.6)
153
+ tzinfo (1.2.5)
154
+ thread_safe (~> 0.1)
155
+ websocket-driver (0.7.1)
156
+ websocket-extensions (>= 0.1.0)
157
+ websocket-extensions (0.1.4)
158
+ xpath (3.2.0)
159
+ nokogiri (~> 1.8)
160
+
161
+ PLATFORMS
162
+ ruby
163
+
164
+ DEPENDENCIES
165
+ bundler (~> 2.0)
166
+ byebug
167
+ capybara
168
+ gifted!
169
+ puma
170
+ rake
171
+ selenium-webdriver
172
+ sqlite3
173
+ test-unit-rails
174
+
175
+ BUNDLED WITH
176
+ 2.0.1
data/README.md ADDED
@@ -0,0 +1,126 @@
1
+ # Gifted
2
+
3
+ Simple, yet powerful decorators for Ruby on Rails, inspired (and forked) from [ActiveDecorator](https://github.com/amatsuda/active_decorator). It has the following goals:
4
+
5
+ 1. Fast and efficient.
6
+ 2. Implicit decorators.
7
+ 3. Explicit decoration.
8
+
9
+ ## Features
10
+
11
+ Gifted has an almost identical feature set to ActiveDecorator...
12
+
13
+ 1. Automatically mixes decorator module into corresponding model only when:
14
+ 1. Passing a model or collection of models or an instance of ActiveRecord::Relation from controllers to views
15
+ 2. rendering partials with models (using `:collection` or `:object` or `:locals` explicitly or implicitly)
16
+ 3. fetching already decorated Active Record model object's association
17
+ 2. the decorator module runs in the model's context. So, you can directly call any attributes or methods in the decorator module
18
+ 3. since decorators are considered as sort of helpers, you can also call any ActionView's helper methods such as `content_tag` or `link_to`
19
+
20
+ But with the following differences...
21
+
22
+ 1. Decorator methods are name-spaced to a single `gift` method. This avoids confusion and collision.
23
+ 2. Decorators are mixed into SimpleDelegator classes, which themselves delegate to the decorated object.
24
+ 2. Decorator Views allow you to create child decorators.
25
+ 3. Only works with Rails.
26
+
27
+ ## Installation
28
+
29
+ Gifted requires Rails >= 5.
30
+
31
+ Add this line to your application's Gemfile:
32
+
33
+ ```ruby
34
+ gem 'gifted'
35
+ ```
36
+
37
+ And then execute:
38
+
39
+ $ bundle
40
+
41
+ Or install it yourself as:
42
+
43
+ $ gem install gifted
44
+
45
+ ## Usage
46
+
47
+ Create your Decorators into `/app/decorators` for each model you want decorated, and define methods. For example, a model `User`, can have a decorator `UserDecorator`:
48
+
49
+ * Model
50
+ ```ruby
51
+ class User < ActiveRecord::Base
52
+ # first_name:string last_name:string
53
+ end
54
+ ```
55
+
56
+ * Controller
57
+ ```ruby
58
+ class UsersController < ApplicationController
59
+ def show
60
+ @user = User.find(params[:id])
61
+ end
62
+ end
63
+ ```
64
+
65
+ * Decorator
66
+ ```ruby
67
+ # I can call any method from the decorated object, and because I am mixed into SimpleDelegator, I
68
+ # can access the decorated object directly at __getobj__.
69
+ module UserDecorator
70
+ # This is a Decorator View, and can be access by passing the name of the view (:admin) to `#gift`.
71
+ module AdminDecorator
72
+ def full_name
73
+ "#{first_name} #{last_initial} (administrator)"
74
+ end
75
+ end
76
+
77
+ def full_name
78
+ "#{first_name} #{last_initial}"
79
+ end
80
+
81
+ def first_name
82
+ first_name.titleize
83
+ end
84
+
85
+ def last_initial
86
+ last_name[0]
87
+ end
88
+ end
89
+ ```
90
+
91
+ * View
92
+ ```erb
93
+ <!-- @user here is auto-decorated in between the controller and the view -->
94
+
95
+ <!-- @user.gift.full_name will use the method #full_name from the decorator. -->
96
+ <p><%= @user.gift.full_name %></p>
97
+
98
+ <!--
99
+ @user.gift.last_name will use the method #last_name from the model, because @user.gift delegates
100
+ to the model.
101
+ -->
102
+ <p><%= @user.gift.last_name %></p>
103
+
104
+ <!--
105
+ Calling gift with a symbol as an argument, will decorate the object with a Decorator view.
106
+ So @user.gift(:admin).last_name will use the method #full_name from UserDecorator::AdminDecorator.
107
+ -->
108
+ <p><%= @user.gift(:admin).full_name %></p>
109
+
110
+ <!-- @user.last_name will use the method #last_name from the model. -->
111
+ <p><%= @user.last_name %></p>
112
+ ```
113
+
114
+ ## Development
115
+
116
+ 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.
117
+
118
+ 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 tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
119
+
120
+ ## Contributing
121
+
122
+ Bug reports and pull requests are welcome on GitHub at https://github.com/joelmoss/gifted.
123
+
124
+ ## Thanks!
125
+
126
+ This gem is hugely inspired by and (in parts) copied from [ActiveDecorator](https://github.com/amatsuda/active_decorator).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/*_test.rb"]
10
+ end
11
+
12
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "gifted"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/gifted.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("../lib", __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require "gifted/version"
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "gifted"
9
+ spec.version = Gifted::VERSION
10
+ spec.authors = ["Joel Moss"]
11
+ spec.email = ["joel@developwithstyle.com"]
12
+
13
+ spec.summary = %q{Simple, yet Powerful Rails Decorators}
14
+ spec.description = %q{Simple, yet Powerful Rails Decorators}
15
+ spec.homepage = 'https://github.com/joelmoss/gifted'
16
+
17
+ # Specify which files should be added to the gem when it is released.
18
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
20
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
+ end
22
+ spec.bindir = "exe"
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_development_dependency 'bundler', '~> 2.0'
27
+ spec.add_development_dependency 'test-unit-rails'
28
+ spec.add_development_dependency 'selenium-webdriver'
29
+ spec.add_development_dependency 'puma'
30
+ spec.add_development_dependency 'capybara'
31
+ spec.add_development_dependency 'sqlite3'
32
+ spec.add_development_dependency 'rake'
33
+ spec.add_development_dependency 'byebug'
34
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A no-op module to mark an AR model instance as a "decorated" object.
4
+ module Gifted::Decorated
5
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'singleton'
4
+ require 'gifted/view_helpers'
5
+ require 'gifted/decorated'
6
+ require 'gifted/gift'
7
+
8
+ module Gifted
9
+ class Decorator
10
+ include Singleton
11
+
12
+ def initialize
13
+ @@decorators = {}
14
+ end
15
+
16
+ def decorate(obj)
17
+ if obj.is_a?(Array)
18
+ obj.each { |r| decorate r }
19
+ elsif obj.is_a?(Hash)
20
+ obj.each_value { |v| decorate v }
21
+ elsif obj.is_a?(ActiveRecord::Relation)
22
+ extend_with_relation_decorator obj
23
+ else
24
+ extend_with_decorated obj
25
+
26
+ return obj unless (d = decorator_for(obj.class))
27
+
28
+ # !! The original monkey patched code.
29
+ # obj.extend d unless obj.is_a? d
30
+
31
+ # The new hotness, which mixes in a single "parent" method called `gift`, that isolates all
32
+ # decorated methods; avoiding confusion as to which methods are decorated and which are not.
33
+ #
34
+ # Example:
35
+ # object.gift.my_decorated_method
36
+ # object.my_non_decorated_method
37
+ #
38
+ # Instead of extending (decorating) the given object with the decorator module, this extends
39
+ # it with Gifted::Gift, and sets the default decorator as the calculated decorator module
40
+ # above. Gifted::Gift extends the object with one method; `gift`, which returns the
41
+ # default decorator.
42
+ obj.extend(::Gifted::Gift).default_decorator = d unless obj.is_a? ::Gifted::Gift
43
+ end
44
+
45
+ obj
46
+ end
47
+
48
+ # Decorates AR model object's association only when the object was decorated.
49
+ # Returns the association instance.
50
+ def decorate_association(owner, target)
51
+ owner.is_a?(Gifted::Decorated) ? decorate(target) : target
52
+ end
53
+
54
+ private
55
+
56
+ # Returns a decorator module for the given class.
57
+ # Returns `nil` if no decorator module was found.
58
+ def decorator_for(model_class)
59
+ return @@decorators[model_class] if @@decorators.key? model_class
60
+
61
+ decorator_name = "#{model_class.name}Decorator"
62
+ d = Object.const_get decorator_name, false
63
+ unless Class === d
64
+ d.send :include, Gifted::ViewHelpers
65
+ @@decorators[model_class] = d
66
+ else
67
+ # Cache nil results
68
+ @@decorators[model_class] = nil
69
+ end
70
+ rescue NameError
71
+ # This handles ActiveRecord STI models which don't have a decorator class - looking up it's
72
+ # base class.
73
+
74
+ if model_class.respond_to?(:base_class) && (model_class.base_class != model_class)
75
+ @@decorators[model_class] = decorator_for model_class.base_class
76
+ else
77
+ # Cache nil results
78
+ @@decorators[model_class] = nil
79
+ end
80
+ end
81
+
82
+ def extend_with_relation_decorator(obj)
83
+ return if obj.is_a? Gifted::RelationDecorator
84
+
85
+ obj.extend Gifted::RelationDecorator
86
+ end
87
+
88
+ def extend_with_decorated(obj)
89
+ return if !obj.is_a?(ActiveRecord::Base) || obj.is_a?(Gifted::Decorated)
90
+
91
+ obj.extend Gifted::Decorated
92
+ end
93
+ end
94
+
95
+ module RelationDecorator
96
+ def records
97
+ arr = super
98
+ Gifted::Decorator.instance.decorate arr
99
+ arr
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gifted
4
+ module Gift
5
+ attr_accessor :default_decorator
6
+
7
+ def gift(view = nil)
8
+ @decorator_views ||= { default: gift_delegator }
9
+
10
+ if view
11
+ @decorator_views[view] ||= gift_delegator(view)
12
+ else
13
+ @decorator_views[:default]
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def gift_delegator(view = nil)
20
+ decorator = default_decorator
21
+
22
+ if view
23
+ decorator = default_decorator.const_get("#{view.to_s.camelcase}Decorator")
24
+ decorator.send :include, Gifted::ViewContext unless decorator.is_a?(Class)
25
+ end
26
+
27
+ SimpleDelegator.new(self).extend decorator
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A monkey-patch for Rails controllers/mailers that auto-decorates ivars
4
+ # that are passed to views.
5
+ module Gifted
6
+ module Monkey
7
+ module AbstractController
8
+ module Rendering
9
+ def view_assigns
10
+ hash = super
11
+ hash.each_value do |v|
12
+ Gifted::Decorator.instance.decorate v
13
+ end
14
+ hash
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A monkey-patch for Action Controller to pass the controller view_context over
4
+ # to `render` invocation in `rescue_from` block.
5
+ module Gifted
6
+ module Monkey
7
+ module ActionController
8
+ module Base
9
+ def rescue_with_handler(*)
10
+ Gifted::ViewContext.push(view_context)
11
+ super
12
+ ensure
13
+ Gifted::ViewContext.pop
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A monkey-patch for Action View `render :partial` that auto-decorates `locals` values.
4
+ module Gifted
5
+ module Monkey
6
+ module ActionView
7
+ module PartialRenderer
8
+ private
9
+
10
+ def setup(*)
11
+ super
12
+
13
+ @locals.each_value do |v|
14
+ Gifted::Decorator.instance.decorate v
15
+ end if @locals
16
+ Gifted::Decorator.instance.decorate @object if @object
17
+ Gifted::Decorator.instance.decorate @collection unless @collection.blank?
18
+
19
+ self
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A monkey-patch for Active Record that enables association auto-decoration.
4
+ module Gifted
5
+ module Monkey
6
+ module ActiveRecord
7
+ module Associations
8
+ module Association
9
+ def target
10
+ Gifted::Decorator.instance.decorate_association(owner, super)
11
+ end
12
+ end
13
+
14
+ module CollectionProxy
15
+ def take(*)
16
+ Gifted::Decorator.instance.decorate_association(@association.owner, super)
17
+ end
18
+
19
+ def last(*)
20
+ Gifted::Decorator.instance.decorate_association(@association.owner, super)
21
+ end
22
+
23
+ private
24
+
25
+ def find_nth_with_limit(*)
26
+ Gifted::Decorator.instance.decorate_association(@association.owner, super)
27
+ end
28
+
29
+ def find_nth_from_last(*)
30
+ Gifted::Decorator.instance.decorate_association(@association.owner, super)
31
+ end
32
+ end
33
+
34
+ module CollectionAssociation
35
+ private
36
+
37
+ def build_record(*)
38
+ Gifted::Decorator.instance.decorate_association(@owner, super)
39
+ end
40
+ end
41
+ end
42
+
43
+ module AssociationRelation
44
+ def take(*)
45
+ Gifted::Decorator.instance.decorate_association(@association.owner, super)
46
+ end
47
+
48
+ private
49
+
50
+ def find_nth_with_limit(*)
51
+ Gifted::Decorator.instance.decorate_association(@association.owner, super)
52
+ end
53
+
54
+ def find_nth_from_last(*)
55
+ Gifted::Decorator.instance.decorate_association(@association.owner, super)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails'
4
+
5
+ module Gifted
6
+ class Railtie < ::Rails::Railtie
7
+ initializer 'gifted' do
8
+ ActiveSupport.on_load :action_view do
9
+ require 'gifted/monkey/action_view/partial_renderer'
10
+ ActionView::PartialRenderer.send :prepend, Gifted::Monkey::ActionView::PartialRenderer
11
+ end
12
+
13
+ ActiveSupport.on_load :action_controller do
14
+ require 'gifted/monkey/abstract_controller/rendering'
15
+ ActionController::Base.send :prepend, Gifted::Monkey::AbstractController::Rendering
16
+
17
+ require 'gifted/monkey/action_controller/base/rescue_from'
18
+ ActionController::Base.send :prepend, Gifted::Monkey::ActionController::Base
19
+
20
+ require 'gifted/view_context'
21
+ ActionController::Base.send :include, Gifted::ViewContext::Filter
22
+ end
23
+
24
+ ActiveSupport.on_load :action_mailer do
25
+ require 'gifted/monkey/abstract_controller/rendering'
26
+ ActionMailer::Base.send :prepend, Gifted::Monkey::AbstractController::Rendering
27
+
28
+ if ActionMailer::Base.respond_to? :before_action
29
+ require 'gifted/view_context'
30
+ ActionMailer::Base.send :include, Gifted::ViewContext::Filter
31
+ end
32
+ end
33
+
34
+ ActiveSupport.on_load :active_record do
35
+ require 'gifted/monkey/active_record/associations'
36
+
37
+ ActiveRecord::Associations::Association.send :prepend, Gifted::Monkey::ActiveRecord::Associations::Association
38
+ ActiveRecord::AssociationRelation.send :prepend, Gifted::Monkey::ActiveRecord::AssociationRelation
39
+ ActiveRecord::Associations::CollectionProxy.send :prepend, Gifted::Monkey::ActiveRecord::Associations::CollectionProxy
40
+ ActiveRecord::Associations::CollectionAssociation.send :prepend, Gifted::Monkey::ActiveRecord::Associations::CollectionAssociation
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gifted
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A module that carries the controllers' view_context to decorators.
4
+ module Gifted
5
+ module ViewContext
6
+ class << self
7
+ def current
8
+ view_context_stack.last
9
+ end
10
+
11
+ def push(view_context)
12
+ view_context_stack.push view_context
13
+ end
14
+
15
+ def pop
16
+ view_context_stack.pop
17
+ end
18
+
19
+ def view_context_stack
20
+ Thread.current[:gifted_view_contexts] ||= []
21
+ end
22
+
23
+ def run_with(view_context)
24
+ push view_context
25
+ yield
26
+ ensure
27
+ pop
28
+ end
29
+ end
30
+
31
+ module Filter
32
+ extend ActiveSupport::Concern
33
+
34
+ included do
35
+ around_action do |controller, blk|
36
+ Gifted::ViewContext.run_with(controller.view_context) do
37
+ blk.call
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gifted
4
+ module ViewHelpers
5
+ def method_missing(method_name, *args, &block)
6
+ view_context = Gifted::ViewContext.current
7
+ view_context&.respond_to?(method_name) ? view_context.send(method_name, *args, &block) : super
8
+ end
9
+
10
+ def respond_to_missing?(method_name, *args)
11
+ Gifted::ViewContext.current.respond_to?(method_name) || super
12
+ end
13
+ end
14
+ end
data/lib/gifted.rb ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'gifted/version'
4
+ require 'gifted/decorator'
5
+ require 'gifted/railtie'
6
+
7
+ module Gifted
8
+ end
metadata ADDED
@@ -0,0 +1,176 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gifted
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Joel Moss
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-06-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: test-unit-rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: selenium-webdriver
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: puma
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: capybara
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: sqlite3
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: byebug
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Simple, yet Powerful Rails Decorators
126
+ email:
127
+ - joel@developwithstyle.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".DS_Store"
133
+ - ".gitignore"
134
+ - ".travis.yml"
135
+ - Gemfile
136
+ - Gemfile.lock
137
+ - README.md
138
+ - Rakefile
139
+ - bin/console
140
+ - bin/setup
141
+ - gifted.gemspec
142
+ - lib/gifted.rb
143
+ - lib/gifted/decorated.rb
144
+ - lib/gifted/decorator.rb
145
+ - lib/gifted/gift.rb
146
+ - lib/gifted/monkey/abstract_controller/rendering.rb
147
+ - lib/gifted/monkey/action_controller/base/rescue_from.rb
148
+ - lib/gifted/monkey/action_view/partial_renderer.rb
149
+ - lib/gifted/monkey/active_record/associations.rb
150
+ - lib/gifted/railtie.rb
151
+ - lib/gifted/version.rb
152
+ - lib/gifted/view_context.rb
153
+ - lib/gifted/view_helpers.rb
154
+ homepage: https://github.com/joelmoss/gifted
155
+ licenses: []
156
+ metadata: {}
157
+ post_install_message:
158
+ rdoc_options: []
159
+ require_paths:
160
+ - lib
161
+ required_ruby_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ required_rubygems_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
171
+ requirements: []
172
+ rubygems_version: 3.0.3
173
+ signing_key:
174
+ specification_version: 4
175
+ summary: Simple, yet Powerful Rails Decorators
176
+ test_files: []