activerepresenter 0.2.0 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/activerepresenter.gemspec +2 -2
- data/lib/active_representer/base.rb +115 -43
- data/test/attr_collection_test.rb +11 -1
- data/test/attr_one_test.rb +44 -0
- metadata +9 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ed4527a2a221a276e499bd089f9dc3006ce9cd77df82e3942bf315dc911a0fe
|
4
|
+
data.tar.gz: 44872f2fe052f02eaef244303814a9e62123238d879c140c6ce29a7e010c4f77
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4157653ae694c4c5c60a2dd203037cbc644792a8a32524d96864c71b785a072ce9e34776f5aad38ae390be7ce0be5588322a6a3a0a43e21688e741e5e7c0d6c3
|
7
|
+
data.tar.gz: 05537aca1745b016fef2660ed2693dfac117c3f3c1df85966549be0955fc57ca2a777c930f39f61dc8ce16e4262c2a8b2ec0a672accc41c8a7331d3042e30946
|
data/activerepresenter.gemspec
CHANGED
@@ -24,8 +24,8 @@ Gem::Specification.new do |s|
|
|
24
24
|
s.test_files = s.files.grep(/^test/)
|
25
25
|
|
26
26
|
s.add_dependency "bundler", ">= 1.3"
|
27
|
-
s.add_dependency "activemodel", ">= 5.2", "< 6.
|
28
|
-
s.add_dependency "activesupport", ">= 5.2", "< 6.
|
27
|
+
s.add_dependency "activemodel", ">= 5.2", "< 6.2"
|
28
|
+
s.add_dependency "activesupport", ">= 5.2", "< 6.2"
|
29
29
|
s.add_development_dependency "rake", ">= 12.3.3"
|
30
30
|
s.add_development_dependency "test-unit", ">= 3.3"
|
31
31
|
end
|
@@ -4,69 +4,141 @@ require "active_model"
|
|
4
4
|
require "active_support"
|
5
5
|
|
6
6
|
module ActiveRepresenter
|
7
|
+
# == Action \Representer \Base
|
8
|
+
#
|
9
|
+
# This is a base class for a representer (wrapped object).
|
10
|
+
# It wraps the original object as `wrapped` attribute and
|
11
|
+
# you can add custom methods to the class (using the decorator pattern).
|
12
|
+
#
|
13
|
+
# In addition, `attr_field` / `attr_collection` can be used for attributes.
|
14
|
+
#
|
15
|
+
# attr_field:
|
16
|
+
# Declare additional field and type to the objects.
|
17
|
+
# You can get / set field's value (converted to corresponding).
|
18
|
+
# It uses ActiveModel::Attributes internally.
|
19
|
+
# See examples: AttrFieldTest in test/attr_field_test.
|
20
|
+
#
|
21
|
+
# attr_one:
|
22
|
+
# Declare an associated object like has one association.
|
23
|
+
# If a representer for the object is found, the object will be wrapped by the representer.
|
24
|
+
# See examples: AttrOneTest in test/attr_one_test.
|
25
|
+
#
|
26
|
+
# attr_many:
|
27
|
+
# Declare associated objects like has many association.
|
28
|
+
# If a representer for the objects is found, the objects will be wrapped by the representer.
|
29
|
+
# See examples: AttrCollectionTest in test/attr_collection_test.
|
7
30
|
class Base
|
8
31
|
include ActiveModel::Model
|
9
32
|
include ActiveModel::Attributes
|
10
33
|
|
11
34
|
attribute :wrapped
|
35
|
+
class_attribute :ones, default: {}
|
12
36
|
class_attribute :collections, default: {}
|
13
37
|
|
14
38
|
delegate_missing_to :wrapped
|
15
39
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
instance
|
40
|
+
def self.inherited(subclass)
|
41
|
+
subclass.ones = {}
|
42
|
+
subclass.collections = {}
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.wrap(wrapped)
|
46
|
+
instance = new
|
47
|
+
instance.wrapped = wrapped
|
48
|
+
|
49
|
+
one_names.each do |one_name|
|
50
|
+
next if wrapped[one_name].nil?
|
51
|
+
representer_klass = ones[one_name]
|
52
|
+
one_value = \
|
53
|
+
if representer_klass
|
54
|
+
representer_klass.wrap(wrapped[one_name])
|
55
|
+
else
|
56
|
+
wrapped[one_name]
|
57
|
+
end
|
58
|
+
instance.instance_variable_set("@#{one_name}", one_value)
|
35
59
|
end
|
36
60
|
|
37
|
-
|
38
|
-
|
61
|
+
collection_names.each do |collection_name|
|
62
|
+
next if wrapped[collection_name].nil?
|
63
|
+
representer_klass = collections[collection_name]
|
64
|
+
collection_value = \
|
65
|
+
if representer_klass
|
66
|
+
wrapped[collection_name].map { |item| representer_klass.wrap(item) }
|
67
|
+
else
|
68
|
+
wrapped[collection_name]
|
69
|
+
end
|
70
|
+
instance.instance_variable_set("@#{collection_name}", collection_value)
|
39
71
|
end
|
40
72
|
|
41
|
-
|
42
|
-
|
43
|
-
raise ArgumentError.new("collection's name must be a Symbol or a String")
|
44
|
-
end
|
45
|
-
representer_name = \
|
46
|
-
options[:representer_name] ? options[:representer_name] : guess_representrer_name(name.to_s)
|
47
|
-
raise ArgumentError.new("representer_name must be a String") unless representer_name.is_a?(String)
|
48
|
-
begin
|
49
|
-
representer = representer_name.constantize
|
50
|
-
collections[name.to_sym] = representer
|
51
|
-
rescue NameError => e
|
52
|
-
collections[name.to_sym] = nil
|
53
|
-
end
|
54
|
-
class_eval do
|
55
|
-
attr_reader name.to_sym
|
56
|
-
end
|
73
|
+
attribute_names.each do |attribute_name|
|
74
|
+
instance.send("#{attribute_name}=", wrapped.send(attribute_name))
|
57
75
|
end
|
58
76
|
|
59
|
-
|
60
|
-
|
77
|
+
instance
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.attr_field(name, type = Type::Value.new, **options)
|
81
|
+
attribute(name, type, **options)
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.attr_one(name, **options)
|
85
|
+
check_name_type(name)
|
86
|
+
representer_name = specify_or_guess_representer_name(options[:representer_name], name)
|
87
|
+
|
88
|
+
begin
|
89
|
+
representer = representer_name.constantize
|
90
|
+
ones[name.to_sym] = representer
|
91
|
+
rescue NameError
|
92
|
+
ones[name.to_sym] = nil
|
93
|
+
end
|
94
|
+
|
95
|
+
class_eval do
|
96
|
+
attr_reader name.to_sym
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.attr_collection(name, **options)
|
101
|
+
check_name_type(name)
|
102
|
+
representer_name = specify_or_guess_representer_name(options[:representer_name], name)
|
103
|
+
|
104
|
+
begin
|
105
|
+
representer = representer_name.constantize
|
106
|
+
collections[name.to_sym] = representer
|
107
|
+
rescue NameError
|
108
|
+
collections[name.to_sym] = nil
|
61
109
|
end
|
62
110
|
|
63
|
-
|
64
|
-
|
111
|
+
class_eval do
|
112
|
+
attr_reader name.to_sym
|
65
113
|
end
|
114
|
+
end
|
115
|
+
|
116
|
+
singleton_class.send(:alias_method, :attr_many, :attr_collection)
|
117
|
+
|
118
|
+
def self.one_names
|
119
|
+
ones.keys
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.collection_names
|
123
|
+
collections.keys
|
124
|
+
end
|
66
125
|
|
67
|
-
|
68
|
-
|
126
|
+
def self.attribute_names
|
127
|
+
attribute_types.keys - ["wrapped"]
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.check_name_type(name)
|
131
|
+
unless name.is_a?(Symbol) || name.is_a?(String)
|
132
|
+
raise ArgumentError.new("collection's name must be a Symbol or a String")
|
69
133
|
end
|
70
134
|
end
|
135
|
+
|
136
|
+
def self.guess_representrer_name(name)
|
137
|
+
"#{name.singularize.camelize}Representer"
|
138
|
+
end
|
139
|
+
|
140
|
+
def self.specify_or_guess_representer_name(specified_name, wrapped_name)
|
141
|
+
specified_name ? specified_name.to_s : guess_representrer_name(wrapped_name.to_s)
|
142
|
+
end
|
71
143
|
end
|
72
144
|
end
|
@@ -11,7 +11,7 @@ end
|
|
11
11
|
|
12
12
|
class UserRepresenter < ActiveRepresenter::Base
|
13
13
|
attr_collection :activities
|
14
|
-
|
14
|
+
attr_many :notifications
|
15
15
|
|
16
16
|
def full_name
|
17
17
|
"#{first_name} #{last_name}"
|
@@ -71,4 +71,14 @@ class AttrCollectionTest < Test::Unit::TestCase
|
|
71
71
|
notification = representer.notifications.first
|
72
72
|
assert_instance_of(OpenStruct, notification)
|
73
73
|
end
|
74
|
+
|
75
|
+
test "representer class include :activities and :notifications in collection_names array" do
|
76
|
+
collection_names = UserRepresenter.collection_names
|
77
|
+
assert_equal(collection_names, [:activities, :notifications])
|
78
|
+
end
|
79
|
+
|
80
|
+
test "base class doesn't have any entries in collection_names array" do
|
81
|
+
collection_names = ActiveRepresenter::Base.collection_names
|
82
|
+
assert_equal(collection_names, [])
|
83
|
+
end
|
74
84
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "ostruct"
|
3
|
+
require "active_support/time"
|
4
|
+
require_relative "../lib/active_representer/base.rb"
|
5
|
+
|
6
|
+
class ProfileRepresenter < ActiveRepresenter::Base
|
7
|
+
def email_sent_on
|
8
|
+
email_sent_at.to_date
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class UserRepresenter < ActiveRepresenter::Base
|
13
|
+
attr_one :profile
|
14
|
+
end
|
15
|
+
|
16
|
+
class AttrOneTest < Test::Unit::TestCase
|
17
|
+
test "profile is represented" do
|
18
|
+
user = OpenStruct.new(
|
19
|
+
profile: OpenStruct.new(email_sent_at: Time.now)
|
20
|
+
)
|
21
|
+
representer = UserRepresenter.wrap(user)
|
22
|
+
profile = representer.profile
|
23
|
+
assert_instance_of(ProfileRepresenter, profile)
|
24
|
+
end
|
25
|
+
|
26
|
+
test "profile.email_sent_on is Date.today" do
|
27
|
+
user = OpenStruct.new(
|
28
|
+
profile: OpenStruct.new(email_sent_at: Time.now)
|
29
|
+
)
|
30
|
+
representer = UserRepresenter.wrap(user)
|
31
|
+
profile = representer.profile
|
32
|
+
assert_equal(profile.email_sent_on, Date.today)
|
33
|
+
end
|
34
|
+
|
35
|
+
test "representer class include profile in one_names array" do
|
36
|
+
one_names = UserRepresenter.one_names
|
37
|
+
assert_equal(one_names, [:profile])
|
38
|
+
end
|
39
|
+
|
40
|
+
test "base class doesn't include profile in one_names array" do
|
41
|
+
one_names = ActiveRepresenter::Base.one_names
|
42
|
+
assert_equal(one_names, [])
|
43
|
+
end
|
44
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerepresenter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryo Hashimoto
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-04-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -33,7 +33,7 @@ dependencies:
|
|
33
33
|
version: '5.2'
|
34
34
|
- - "<"
|
35
35
|
- !ruby/object:Gem::Version
|
36
|
-
version: '6.
|
36
|
+
version: '6.2'
|
37
37
|
type: :runtime
|
38
38
|
prerelease: false
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: '5.2'
|
44
44
|
- - "<"
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: '6.
|
46
|
+
version: '6.2'
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: activesupport
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
version: '5.2'
|
54
54
|
- - "<"
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version: '6.
|
56
|
+
version: '6.2'
|
57
57
|
type: :runtime
|
58
58
|
prerelease: false
|
59
59
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -63,7 +63,7 @@ dependencies:
|
|
63
63
|
version: '5.2'
|
64
64
|
- - "<"
|
65
65
|
- !ruby/object:Gem::Version
|
66
|
-
version: '6.
|
66
|
+
version: '6.2'
|
67
67
|
- !ruby/object:Gem::Dependency
|
68
68
|
name: rake
|
69
69
|
requirement: !ruby/object:Gem::Requirement
|
@@ -105,6 +105,7 @@ files:
|
|
105
105
|
- lib/activerepresenter.rb
|
106
106
|
- test/attr_collection_test.rb
|
107
107
|
- test/attr_field_test.rb
|
108
|
+
- test/attr_one_test.rb
|
108
109
|
- test/base_test.rb
|
109
110
|
- test/inheritance_test.rb
|
110
111
|
homepage: https://github.com/ryohashimoto/lightrails
|
@@ -126,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
126
127
|
- !ruby/object:Gem::Version
|
127
128
|
version: 1.8.11
|
128
129
|
requirements: []
|
129
|
-
rubygems_version: 3.
|
130
|
+
rubygems_version: 3.1.4
|
130
131
|
signing_key:
|
131
132
|
specification_version: 4
|
132
133
|
summary: Active Representer provides model objects by decorating objects (part of
|
@@ -134,5 +135,6 @@ summary: Active Representer provides model objects by decorating objects (part o
|
|
134
135
|
test_files:
|
135
136
|
- test/attr_collection_test.rb
|
136
137
|
- test/attr_field_test.rb
|
138
|
+
- test/attr_one_test.rb
|
137
139
|
- test/base_test.rb
|
138
140
|
- test/inheritance_test.rb
|