Skip to content

Commit 0c346fb

Browse files
committed
Increase Speed & Documentation & Comments
1 parent 03b09d0 commit 0c346fb

11 files changed

Lines changed: 126 additions & 36 deletions

File tree

README.md

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,87 @@
44
[![Code Climate](https://codeclimate.com/github/light-ruby/light-decorator/badges/gpa.svg)](https://codeclimate.com/github/light-ruby/light-decorator)
55
[![Test Coverage](https://codeclimate.com/github/light-ruby/light-decorator/badges/coverage.svg)](https://codeclimate.com/github/light-ruby/light-decorator/coverage)
66

7+
Easiest and fast way to decorate Ruby on Rails models.
8+
9+
Decorator pattern - What is it?
10+
- [Wikipedia](https://en.wikipedia.org/wiki/Decorator_pattern)
11+
- [Thoughtbot](https://robots.thoughtbot.com/evaluating-alternative-decorator-implementations-in)
12+
713
## Installation
814

915
Add this line to your application's Gemfile:
1016

1117
```ruby
12-
gem 'light-decorator'
18+
gem 'light-decorator', '~> 0.5.0'
1319
```
1420

15-
And then execute:
21+
## Usage
1622

17-
$ bundle
23+
Create the `ApplicationDecorator`
1824

19-
Or install it yourself as:
25+
```ruby
26+
# app/decorators/application_decorator.rb
27+
class ApplicationDecorator < Light::Decorator::Decorate
28+
end
29+
```
2030

21-
$ gem install light-decorator
31+
Create decorator for your model. For example we will use the `User` model.
2232

23-
## Usage
33+
```ruby
34+
# app/decorators/user_decorator.rb
35+
class UserDecorator < Application
36+
def full_name
37+
"#{object.first_name} #{object.last_name}"
38+
end
39+
end
40+
```
41+
42+
Decorate your model in controller or anywhere.
2443

25-
TODO: Write usage instructions here
44+
```ruby
45+
# Single record
46+
User.find(params[:id]).decorate
47+
User.find_and_decorate(params[:id])
48+
User.decorate.find(params[:id])
49+
50+
# Collection
51+
User.all.decorate
52+
User.decorate
53+
User.limit(10).decorate
54+
User.decorate.limit(10)
55+
56+
# Options
57+
User.find_and_decorate(params[:id], with: AnotherUserDecorator)
58+
59+
# Associations will be decorated automatically
60+
user = User.find_and_decorate(params[:id])
61+
user.decorated? # true
62+
user.comments.decorated? # true
63+
user.comments.first.decorated? # true
64+
```
65+
66+
Example of Decorator
67+
```ruby
68+
class UserDecorator < ApplicationDecorator
69+
def full_name
70+
"#{object.first_name} #{object.last_name}"
71+
# or
72+
"#{o.first_name} #{o.last_name}"
73+
end
74+
75+
def full_name_link
76+
helpers.link_to full_name, user_path(object)
77+
# or
78+
h.link_to full_name, user_path(object)
79+
end
80+
end
81+
```
2682

27-
## Development
83+
## Next steps
2884

29-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
85+
- [ ] Create rake task `light-decorator:install`
86+
- [ ] Create generators
87+
- [ ] Create configuration file
3088

3189
## Contributing
3290

gemfiles/rails_4_0.gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: ../
33
specs:
4-
light-decorator (0.1.0)
4+
light-decorator (0.5.0)
55
rails (>= 4.0.0)
66
request_store (>= 1.0.0)
77

gemfiles/rails_4_1.gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: ../
33
specs:
4-
light-decorator (0.1.0)
4+
light-decorator (0.5.0)
55
rails (>= 4.0.0)
66
request_store (>= 1.0.0)
77

gemfiles/rails_4_2.gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: ../
33
specs:
4-
light-decorator (0.1.0)
4+
light-decorator (0.5.0)
55
rails (>= 4.0.0)
66
request_store (>= 1.0.0)
77

gemfiles/rails_5_0.gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: ../
33
specs:
4-
light-decorator (0.1.0)
4+
light-decorator (0.5.0)
55
rails (>= 4.0.0)
66
request_store (>= 1.0.0)
77

lib/light/decorator.rb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
require 'rails'
2+
require 'active_record'
13
require 'request_store'
2-
require 'rails/railtie'
3-
require 'active_support/concern'
44

55
require 'light/decorator/version'
66
require 'light/decorator/exceptions'
@@ -13,6 +13,8 @@
1313

1414
module Light
1515
module Decorator
16-
NOT_DELEGATABLE_METHODS = Kernel.methods + [:decorated?, :==, :===, :eql?, :equal?]
16+
NOT_DELEGATABLE_METHODS = (
17+
Kernel.methods + ActiveRecord::Base.methods + [:decorated?, :==, :===, :eql?, :equal?]
18+
).freeze
1719
end
1820
end

lib/light/decorator/concerns/associations/collection_proxy.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ module Associations
55
module CollectionProxy
66
extend ActiveSupport::Concern
77

8+
# Decorate ActiveRecord::Model associations
9+
#
10+
# @param [Hash] options (optional)
11+
# @return [ActiveRecord::Associations::CollectionProxy]
812
def decorate(options = {})
913
@decorated = true
1014

@@ -14,6 +18,9 @@ def decorate(options = {})
1418
self
1519
end
1620

21+
# Check current association is decorated or not
22+
#
23+
# @return [Bool]
1724
def decorated?
1825
!@decorated.nil?
1926
end

lib/light/decorator/concerns/base.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ module Concerns
44
module Base
55
extend ActiveSupport::Concern
66

7+
# Decorate ActiveRecord::Model
8+
#
9+
# @param [Hash] options (optional)
10+
# @return [Object] decorator or self
711
def decorate(options = {})
812
return self if decorated?
913

@@ -14,6 +18,9 @@ def decorate(options = {})
1418
self
1519
end
1620

21+
# Check current ActiveRecord::Model is decorated or not
22+
#
23+
# @return [Bool]
1724
def decorated?
1825
false
1926
end
@@ -39,10 +46,19 @@ def decorator_class(options)
3946
end
4047

4148
module ClassMethods
49+
# Decorate all scope for ActiveRecord::Model
50+
#
51+
# @param [Hash] options (optional)
52+
# @return [ActiveRecord::Relation]
4253
def decorate(options = {})
4354
all.decorate(options)
4455
end
4556

57+
# Find ActiveRecord::Model and decorate it
58+
#
59+
# @param [Integer] id
60+
# @param [Hash] options (optional)
61+
# @return [ActiveRecord::Model]
4662
def find_and_decorate(id, options = {})
4763
find(id).decorate(options)
4864
end

lib/light/decorator/concerns/relation.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ module Concerns
44
module Relation
55
extend ActiveSupport::Concern
66

7+
# Decorate ActiveRecord::Relation
8+
#
9+
# @param [Hash] options
10+
# @return [ActiveRecord::Relation] decorated collection
711
def decorate(options = {})
812
@decorated = true
913

@@ -12,6 +16,9 @@ def decorate(options = {})
1216
self
1317
end
1418

19+
# Check current ActiveRecord::Relation is decorated or not
20+
#
21+
# @return [Bool]
1522
def decorated?
1623
!@decorated.nil?
1724
end

lib/light/decorator/decorate.rb

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
module Light
22
module Decorator
33
class Decorate
4-
extend Forwardable
5-
64
# @return original object
75
attr_reader :object
86

@@ -20,22 +18,21 @@ def initialize(object, options = {})
2018
decorate_associations
2119
end
2220

23-
class << self
24-
alias decorate new
25-
end
26-
21+
# Check current ActiveRecord::Model is decorated or not
22+
#
23+
# @return [Bool]
2724
def decorated?
2825
true
2926
end
3027

28+
# Current view scope
29+
#
30+
# @return [ActionView::Base]
3131
def helpers
3232
return @helpers if defined?(@helpers)
3333
@helpers = Light::Decorator::ViewContext.current
3434
end
3535

36-
alias o object
37-
alias h helpers
38-
3936
def ==(other)
4037
super || object == other
4138
end
@@ -44,22 +41,25 @@ def eql?(other)
4441
super || object.eql?(other)
4542
end
4643

44+
class << self
45+
alias decorate new
46+
end
47+
48+
alias o object
49+
alias h helpers
50+
4751
private
4852

4953
def delegate_methods
50-
methods = object.methods - Light::Decorator::NOT_DELEGATABLE_METHODS
51-
self.class.def_delegators :@object, *methods
54+
# It's more faster than using Forwardable
55+
(object.public_methods - Light::Decorator::NOT_DELEGATABLE_METHODS).each do |method|
56+
define_singleton_method method do |*args, &block|
57+
object.__send__(method, *args, &block)
58+
end
59+
end
5260
end
5361

5462
def decorate_associations
55-
# TODO: Remove it before production
56-
# meta = class << self; self; end
57-
# object._reflections.keys.each do |reflection_name|
58-
# meta.send(:define_method, "#{reflection_name}_a") do
59-
# [4,3,2,1]
60-
# end
61-
# end
62-
6363
object.class.reflect_on_all_associations.map(&:name).each do |reflection_name|
6464
define_singleton_method reflection_name do
6565
object.public_send(reflection_name).decorate(@options.reverse_merge(soft: true))

0 commit comments

Comments
 (0)