pbbuilder 0.11.0 → 0.13.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 +4 -4
- data/.github/workflows/test.yml +27 -11
- data/.gitignore +8 -0
- data/.ruby-version +1 -1
- data/Appraisals +5 -1
- data/CHANGELOG.md +28 -0
- data/Gemfile +0 -1
- data/README.md +41 -2
- data/Rakefile +15 -8
- data/gemfiles/rails_6_1.gemfile +1 -1
- data/gemfiles/{rails_7.gemfile → rails_7_0.gemfile} +1 -1
- data/gemfiles/rails_head.gemfile +9 -0
- data/lib/pbbuilder/errors.rb +10 -0
- data/lib/pbbuilder/pbbuilder.rb +7 -0
- data/lib/pbbuilder/railtie.rb +1 -0
- data/lib/pbbuilder/template.rb +95 -0
- data/lib/pbbuilder.rb +56 -5
- data/pbbuilder.gemspec +8 -3
- data/test/pbbuilder_template_test.rb +139 -0
- data/test/test_helper.rb +13 -7
- metadata +54 -11
- data/gemfiles/rails_6_1.gemfile.lock +0 -152
- data/gemfiles/rails_7.gemfile.lock +0 -170
- data/lib/tasks/pbbuilder_tasks.rake +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e4a4d405e3fe428fa8de8ba8609f62211a0224d76fe13bc32d7caf2a07e089c
|
4
|
+
data.tar.gz: 35cf4c2ed96cbb643dfb22db3de4d6ff035cc420f78806489d329b42fd14f88e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5aa3d1b2e64745042fdc1e828ee295d9e14c9891ab3a826d7af64563451b31e2dff28b744419cbb54db31e564dff5e960a2270ab98f480baeca4aeee71373e5e
|
7
|
+
data.tar.gz: 26d816822376f1857cd517c81ac88df26f2cf52cc0aa82dc602249e67f33a446bd8c10aec1cff544638484cb58c03121f15145af7f4ea3af05c13d45f770e29d
|
data/.github/workflows/test.yml
CHANGED
@@ -1,25 +1,41 @@
|
|
1
1
|
name: ruby
|
2
|
-
on: push
|
2
|
+
on: [push]
|
3
3
|
|
4
4
|
jobs:
|
5
5
|
test:
|
6
|
+
name: Ruby ${{ matrix.ruby }} (${{ matrix.gemfile }})
|
6
7
|
runs-on: ubuntu-latest
|
8
|
+
continue-on-error: ${{ matrix.experimental }}
|
9
|
+
env:
|
10
|
+
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
|
11
|
+
BUNDLE_JOBS: 4
|
12
|
+
BUNDLE_RETRY: 3
|
7
13
|
strategy:
|
14
|
+
fail-fast: false
|
8
15
|
matrix:
|
9
|
-
ruby: ["2.7
|
10
|
-
|
16
|
+
ruby: ["2.7", "3.0", "3.1", "3.2"]
|
17
|
+
|
18
|
+
gemfile: [ "rails_6_1", "rails_7_0"]
|
19
|
+
experimental: [false]
|
20
|
+
|
21
|
+
#include:
|
22
|
+
# - ruby: '2.7'
|
23
|
+
# gemfile: rails_head
|
24
|
+
# experimental: true
|
25
|
+
# - ruby: '3.0'
|
26
|
+
# gemfile: rails_head
|
27
|
+
# experimental: true
|
28
|
+
# - ruby: '3.1'
|
29
|
+
# gemfile: rails_head
|
30
|
+
# experimental: true
|
31
|
+
|
11
32
|
steps:
|
12
|
-
-
|
13
|
-
uses: actions/checkout@v2
|
33
|
+
- uses: actions/checkout@v3
|
14
34
|
|
15
|
-
-
|
16
|
-
uses: ruby/setup-ruby@v1
|
35
|
+
- uses: ruby/setup-ruby@v1
|
17
36
|
with:
|
18
37
|
bundler-cache: true
|
19
38
|
ruby-version: ${{ matrix.ruby }}
|
20
39
|
|
21
|
-
- name: Setup Appraisal
|
22
|
-
run: bundle exec appraisal install
|
23
|
-
|
24
40
|
- name: Run tests
|
25
|
-
run: bundle exec
|
41
|
+
run: bundle exec rake
|
data/.gitignore
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.1.
|
1
|
+
3.1.2
|
data/Appraisals
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Pbbuilder Changelog
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
This format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
5
|
+
|
6
|
+
## 0.13.0 2023.01.18
|
7
|
+
### Added
|
8
|
+
- #merge! method added for PbbuilderTemplate class
|
9
|
+
- ActiveSupport added as a dependency for gem
|
10
|
+
- Fragment Caching support added, with #cache! and #cache_if! methods in PbbuilderTemplate class.
|
11
|
+
|
12
|
+
|
13
|
+
### Changed
|
14
|
+
- Appraisal is properly configured to run against all rubies and rails combinations.
|
15
|
+
- Supported ruby version's are 2.7, 3.0, 3.1
|
16
|
+
- Superclass for pbbuilder is now active_support/proxy_object, with a fallback to active_support/basic_object.
|
17
|
+
- Library upgrade: All gems are updated to the latest possible version. Most notable upgrades:
|
18
|
+
- `rails` from version 6.1.4.4 to 6.1.7, and from version 7.0.1 to 7.0.4
|
19
|
+
- `google-protobuf` is let loose
|
20
|
+
- `bundler` from version 2.3.4 to 2.3.22
|
21
|
+
|
22
|
+
### Removed
|
23
|
+
- TestUnit dependency
|
24
|
+
|
25
|
+
|
26
|
+
## 0.12.0 Prior to 2022-10-14
|
27
|
+
|
28
|
+
A templating language, for protobuf, for Rails, inspired by [Jbuilder](https://github.com/rails/jbuilder)
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,47 @@
|
|
1
1
|
# Pbbuilder
|
2
|
-
|
2
|
+
PBBuilder generates [Protobuf](https://developers.google.com/protocol-buffers) Messages with a simple DSL similar to [JBuilder](https://rubygems.org/gems/jbuilder) gem.
|
3
3
|
|
4
4
|
## Usage
|
5
|
-
|
5
|
+
It basically works exactly like jbuilder. The main difference is that it can use introspection to figure out what kind of protobuf message it needs to create.
|
6
|
+
|
7
|
+
|
8
|
+
Following Pbbuilder code
|
9
|
+
```
|
10
|
+
person = RPC::Person.new
|
11
|
+
Pbbuilder.new(person) do |pb|
|
12
|
+
pb.name "Hello"
|
13
|
+
pb.friends [1, 2, 3] do |number|
|
14
|
+
pb.name "Friend ##{number}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
```
|
18
|
+
Would produce this message:
|
19
|
+
|
20
|
+
```
|
21
|
+
message Person {
|
22
|
+
string name = 1;
|
23
|
+
repeated Person friends = 2;
|
24
|
+
}
|
25
|
+
```
|
26
|
+
|
27
|
+
|
28
|
+
### Caching
|
29
|
+
Fragment caching is supported, it uses Rails.cache and works like caching in HTML templates:
|
30
|
+
|
31
|
+
```
|
32
|
+
pb.cache! "cache-key", expires_in: 10.minutes do
|
33
|
+
pb.name @person.name
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
You can also conditionally cache a block by using cache_if! like this:
|
38
|
+
|
39
|
+
```
|
40
|
+
pb.cache_if! !admin?, "cache-key", expires_in: 10.minutes do
|
41
|
+
pb.name @person.name
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
6
45
|
|
7
46
|
## Installation
|
8
47
|
Add this line to your application's Gemfile:
|
data/Rakefile
CHANGED
@@ -1,11 +1,18 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
require "bundler/gem_tasks"
|
1
3
|
require "rake/testtask"
|
2
|
-
require "appraisal"
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
if !ENV["APPRAISAL_INITIALIZED"] && !ENV["CI"]
|
6
|
+
require "appraisal/task"
|
7
|
+
Appraisal::Task.new
|
8
|
+
task default: :appraisal
|
9
|
+
else
|
10
|
+
Rake::TestTask.new(:test) do |t|
|
11
|
+
t.libs << "test"
|
12
|
+
t.pattern = "test/**/*_test.rb"
|
13
|
+
t.verbose = false
|
14
|
+
t.warning = false
|
15
|
+
end
|
10
16
|
|
11
|
-
task default: :test
|
17
|
+
task default: :test
|
18
|
+
end
|
data/gemfiles/rails_6_1.gemfile
CHANGED
data/lib/pbbuilder/railtie.rb
CHANGED
data/lib/pbbuilder/template.rb
CHANGED
@@ -47,8 +47,103 @@ class PbbuilderTemplate < Pbbuilder
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
+
# Caches fragment of message. Can be called like the following:
|
51
|
+
# 'pb.cache! "cache-key" do; end'
|
52
|
+
# 'pb.cache! "cache-key", expire_in: 1.min do; end'
|
53
|
+
#
|
54
|
+
# @param key String
|
55
|
+
# @param options Hash
|
56
|
+
#
|
57
|
+
# @return nil
|
58
|
+
def cache!(key=nil, options={})
|
59
|
+
if @context.controller.perform_caching
|
60
|
+
value = _cache_fragment_for(key, options) do
|
61
|
+
_scope(target!) { yield self }.to_h.compact_blank
|
62
|
+
end
|
63
|
+
|
64
|
+
merge! value
|
65
|
+
else
|
66
|
+
yield
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Conditionally caches the protobuf message depending on the condition given as first parameter. Has the same
|
71
|
+
# signature as the `cache` helper method in `ActionView::Helpers::CacheHelper` and so can be used in
|
72
|
+
# the same way.
|
73
|
+
#
|
74
|
+
# Example:
|
75
|
+
#
|
76
|
+
# pb.cache_if! !admin?, @person, expires_in: 10.minutes do
|
77
|
+
# pb.extract! @person, :name, :age
|
78
|
+
# end
|
79
|
+
def cache_if!(condition, *args, &block)
|
80
|
+
condition ? cache!(*args, &block) : yield
|
81
|
+
end
|
82
|
+
|
50
83
|
private
|
51
84
|
|
85
|
+
# Writes to cache, if cache with keys is missing.
|
86
|
+
#
|
87
|
+
# @return fragment value
|
88
|
+
|
89
|
+
def _cache_fragment_for(key, options, &block)
|
90
|
+
key = _cache_key(key, options)
|
91
|
+
_read_fragment_cache(key, options) || _write_fragment_cache(key, options, &block)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Reads from cache
|
95
|
+
#
|
96
|
+
# @param key string
|
97
|
+
# @params options hash
|
98
|
+
#
|
99
|
+
# @return string
|
100
|
+
def _read_fragment_cache(key, options = nil)
|
101
|
+
@context.controller.instrument_fragment_cache :read_fragment, key do
|
102
|
+
::Rails.cache.read(key, options)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Writes into cache and returns value
|
107
|
+
#
|
108
|
+
# @param key string
|
109
|
+
# @params options hash
|
110
|
+
#
|
111
|
+
# @return string
|
112
|
+
def _write_fragment_cache(key, options = nil)
|
113
|
+
@context.controller.instrument_fragment_cache :_write_fragment, key do
|
114
|
+
yield.tap do |value|
|
115
|
+
::Rails.cache.write(key, value, options)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# Composes full cache key for internal storage
|
121
|
+
#
|
122
|
+
# @param key string
|
123
|
+
# @param options hash
|
124
|
+
#
|
125
|
+
# @return string
|
126
|
+
def _cache_key(key, options)
|
127
|
+
name_options = options.slice(:skip_digest, :virtual_path)
|
128
|
+
key = _fragment_name_with_digest(key, name_options)
|
129
|
+
|
130
|
+
if @context.respond_to?(:combined_fragment_cache_key)
|
131
|
+
key = @context.combined_fragment_cache_key(key)
|
132
|
+
else
|
133
|
+
key = url_for(key).split('://', 2).last if ::Hash === key
|
134
|
+
end
|
135
|
+
|
136
|
+
::ActiveSupport::Cache.expand_cache_key(key, :ppbuilder)
|
137
|
+
end
|
138
|
+
|
139
|
+
def _fragment_name_with_digest(key, options)
|
140
|
+
if @context.respond_to?(:cache_fragment_name)
|
141
|
+
@context.cache_fragment_name(key, **options)
|
142
|
+
else
|
143
|
+
key
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
52
147
|
def _is_active_model?(object)
|
53
148
|
object.class.respond_to?(:model_name) && object.respond_to?(:to_partial_path)
|
54
149
|
end
|
data/lib/pbbuilder.rb
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
require "pbbuilder/pbbuilder"
|
2
|
+
require 'pbbuilder/errors'
|
3
|
+
require "pbbuilder/protobuf_extension"
|
4
|
+
require "pbbuilder/railtie" if defined?(Rails)
|
5
|
+
|
6
|
+
|
1
7
|
# Pbbuilder makes it easy to create a protobuf message using the builder pattern
|
2
8
|
# It is heavily inspired by jbuilder
|
3
9
|
#
|
@@ -21,7 +27,7 @@
|
|
21
27
|
# It basically works exactly like jbuilder. The main difference is that it can use introspection to figure out what kind
|
22
28
|
# of protobuf message it needs to create.
|
23
29
|
|
24
|
-
class Pbbuilder
|
30
|
+
class Pbbuilder
|
25
31
|
def initialize(message)
|
26
32
|
@message = message
|
27
33
|
|
@@ -101,12 +107,54 @@ class Pbbuilder < BasicObject
|
|
101
107
|
end
|
102
108
|
end
|
103
109
|
|
110
|
+
# Merges object into a protobuf message, mainly used for caching.
|
111
|
+
#
|
112
|
+
# @param object [Hash]
|
113
|
+
def merge!(object)
|
114
|
+
::Kernel.raise ::MergeError.build(target!, object) unless object.class == ::Hash
|
115
|
+
|
116
|
+
object.each_key do |key|
|
117
|
+
if object[key].empty?
|
118
|
+
::Kernel.raise ::MergeError.build(target!, object)
|
119
|
+
end
|
120
|
+
|
121
|
+
if object[key].class == ::String
|
122
|
+
# pb.fields {"one" => "two"}
|
123
|
+
@message[key.to_s] = object[key]
|
124
|
+
elsif object[key].class == ::Array
|
125
|
+
# pb.tags ['test', 'ok']
|
126
|
+
@message[key.to_s].replace object[key]
|
127
|
+
elsif ( obj = object[key]).class == ::Hash
|
128
|
+
# pb.field_name do
|
129
|
+
# pb.tags ["ok", "cool"]
|
130
|
+
# end
|
131
|
+
#
|
132
|
+
|
133
|
+
# optional empty fields don't show up in @message object,
|
134
|
+
# we recreate empty message, so we can fill it with values
|
135
|
+
if @message[key.to_s].nil?
|
136
|
+
field_descriptor = @message.class.descriptor.lookup(key.to_s)
|
137
|
+
@message[key.to_s] = _new_message_from_descriptor(field_descriptor)
|
138
|
+
end
|
139
|
+
|
140
|
+
@message[key.to_s] = _scope(@message[key.to_s]) { self.merge!(obj) }
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# @return Initialized message object
|
104
146
|
def target!
|
105
147
|
@message
|
106
148
|
end
|
107
149
|
|
108
150
|
private
|
109
151
|
|
152
|
+
# Appends protobuf message with existing @message object
|
153
|
+
#
|
154
|
+
# @param name string
|
155
|
+
# @param descriptor Google::Protobuf::FieldDescriptor
|
156
|
+
# @param collection hash
|
157
|
+
# @param &block
|
110
158
|
def _append_repeated(name, descriptor, collection, &block)
|
111
159
|
::Kernel.raise ::ArgumentError, "expected Enumerable" unless collection.respond_to?(:map)
|
112
160
|
elements = collection.map do |element|
|
@@ -117,6 +165,9 @@ class Pbbuilder < BasicObject
|
|
117
165
|
@message[name].push(*elements)
|
118
166
|
end
|
119
167
|
|
168
|
+
# Yields an Protobuf object in a scope of message and provided values.
|
169
|
+
#
|
170
|
+
# @param message Google::Protobuf::(field_type)
|
120
171
|
def _scope(message)
|
121
172
|
old_message = @message
|
122
173
|
@message = message
|
@@ -126,6 +177,9 @@ class Pbbuilder < BasicObject
|
|
126
177
|
@message = old_message
|
127
178
|
end
|
128
179
|
|
180
|
+
# Build up empty protobuf message based on descriptor
|
181
|
+
#
|
182
|
+
# @param descriptor Google::Protobuf::FieldDescriptor
|
129
183
|
def _new_message_from_descriptor(descriptor)
|
130
184
|
::Kernel.raise ::ArgumentError, "can't pass block to non-message field" unless descriptor.type == :message
|
131
185
|
|
@@ -134,7 +188,4 @@ class Pbbuilder < BasicObject
|
|
134
188
|
message_class = message_descriptor.msgclass
|
135
189
|
message_class.new
|
136
190
|
end
|
137
|
-
end
|
138
|
-
|
139
|
-
require "pbbuilder/protobuf_extension"
|
140
|
-
require "pbbuilder/railtie" if defined?(Rails)
|
191
|
+
end
|
data/pbbuilder.gemspec
CHANGED
@@ -1,14 +1,19 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = "pbbuilder"
|
3
|
-
spec.version = "0.
|
3
|
+
spec.version = "0.13.0"
|
4
4
|
spec.authors = ["Bouke van der Bijl"]
|
5
5
|
spec.email = ["bouke@cheddar.me"]
|
6
6
|
spec.homepage = "https://github.com/cheddar-me/pbbuilder"
|
7
|
-
spec.summary = "Generate Protobuf
|
7
|
+
spec.summary = "Generate Protobuf Messages with a simple DSL similar to JBuilder"
|
8
8
|
spec.license = "MIT"
|
9
9
|
|
10
|
+
spec.required_ruby_version = '>= 2.7'
|
11
|
+
|
10
12
|
spec.files = `git ls-files`.split("\n")
|
11
13
|
spec.test_files = `git ls-files -- test/*`.split("\n")
|
12
14
|
|
13
|
-
spec.add_dependency "google-protobuf"
|
15
|
+
spec.add_dependency "google-protobuf"
|
16
|
+
spec.add_dependency "activesupport"
|
17
|
+
spec.add_development_dependency 'm'
|
18
|
+
spec.add_development_dependency "pry"
|
14
19
|
end
|
@@ -21,6 +21,8 @@ class PbbuilderTemplateTest < ActiveSupport::TestCase
|
|
21
21
|
"_person.html.erb" => "Hello world!"
|
22
22
|
}
|
23
23
|
|
24
|
+
setup { Rails.cache.clear }
|
25
|
+
|
24
26
|
test "basic template" do
|
25
27
|
result = render('pb.name "hello"')
|
26
28
|
assert_equal "hello", result.name
|
@@ -77,6 +79,143 @@ class PbbuilderTemplateTest < ActiveSupport::TestCase
|
|
77
79
|
assert_equal "Max Verstappen", result.best_friend.name
|
78
80
|
end
|
79
81
|
|
82
|
+
test "support for merge! method" do
|
83
|
+
result = render('pb.merge! "name" => "suslik"')
|
84
|
+
|
85
|
+
assert_equal("suslik", result.name)
|
86
|
+
end
|
87
|
+
|
88
|
+
test "support for merge! method in a block" do
|
89
|
+
result = render(<<-PBBUILDER)
|
90
|
+
pb.best_friend do
|
91
|
+
pb.merge! "name" => "Manuelo"
|
92
|
+
end
|
93
|
+
PBBUILDER
|
94
|
+
|
95
|
+
assert_equal("Manuelo", result.best_friend.name)
|
96
|
+
end
|
97
|
+
|
98
|
+
test "should raise Error in merge! an empty hash" do
|
99
|
+
assert_raise(ActionView::Template::Error) {
|
100
|
+
render(<<-PBBUILDER)
|
101
|
+
pb.merge! "name" => {}
|
102
|
+
PBBUILDER
|
103
|
+
}
|
104
|
+
|
105
|
+
assert_raise(ActionView::Template::Error) {
|
106
|
+
render(<<-PBBUILDER)
|
107
|
+
pb.merge! "" => {}
|
108
|
+
PBBUILDER
|
109
|
+
}
|
110
|
+
end
|
111
|
+
|
112
|
+
test "empty fragment caching" do
|
113
|
+
render 'pb.cache! "nothing" do; end'
|
114
|
+
|
115
|
+
result = nil
|
116
|
+
|
117
|
+
assert_nothing_raised do
|
118
|
+
result = render(<<-JBUILDER)
|
119
|
+
pb.name "suslik"
|
120
|
+
pb.cache! "nothing" do; end
|
121
|
+
JBUILDER
|
122
|
+
end
|
123
|
+
|
124
|
+
assert_equal "suslik", result["name"]
|
125
|
+
end
|
126
|
+
|
127
|
+
test "object fragment caching" do
|
128
|
+
render(<<-PBBUILDER)
|
129
|
+
pb.cache! "cache-key" do
|
130
|
+
pb.name "Hit"
|
131
|
+
end
|
132
|
+
PBBUILDER
|
133
|
+
|
134
|
+
hit = render('pb.cache! "cache-key" do; end ')
|
135
|
+
assert_equal "Hit", hit["name"]
|
136
|
+
end
|
137
|
+
|
138
|
+
test "fragment caching for arrays" do
|
139
|
+
render <<-PBBUILDER
|
140
|
+
pb.cache! "cache-key" do
|
141
|
+
pb.tags ["ok", "cool"]
|
142
|
+
end
|
143
|
+
PBBUILDER
|
144
|
+
|
145
|
+
result = render('pb.cache! "cache-key" do; end')
|
146
|
+
|
147
|
+
assert_equal(['ok', 'cool'], result.tags)
|
148
|
+
end
|
149
|
+
|
150
|
+
test "optional array fragment caching" do
|
151
|
+
render <<-PBBUILDER
|
152
|
+
pb.cache! "cache-key" do
|
153
|
+
pb.field_mask do
|
154
|
+
pb.paths ["ok", "that's", "cool"]
|
155
|
+
end
|
156
|
+
end
|
157
|
+
PBBUILDER
|
158
|
+
|
159
|
+
result = render('pb.cache! "cache-key" do; end')
|
160
|
+
|
161
|
+
assert_equal(["ok", "that's", "cool"], result.field_mask.paths)
|
162
|
+
end
|
163
|
+
|
164
|
+
test "object fragment caching with expiry" do
|
165
|
+
travel_to Time.iso8601("2018-05-12T11:29:00-04:00")
|
166
|
+
|
167
|
+
render <<-PBBUILDER
|
168
|
+
pb.cache! "cache-key", expires_in: 1.minute do
|
169
|
+
pb.name "Hit"
|
170
|
+
end
|
171
|
+
PBBUILDER
|
172
|
+
|
173
|
+
travel 30.seconds
|
174
|
+
|
175
|
+
result = render(<<-PBBUILDER)
|
176
|
+
pb.cache! "cache-key", expires_in: 1.minute do
|
177
|
+
pb.name "Miss"
|
178
|
+
end
|
179
|
+
PBBUILDER
|
180
|
+
|
181
|
+
assert_equal "Hit", result["name"]
|
182
|
+
|
183
|
+
travel 31.seconds
|
184
|
+
|
185
|
+
result = render(<<-PBBUILDER)
|
186
|
+
pb.cache! "cache-key", expires_in: 1.minute do
|
187
|
+
pb.name "Miss"
|
188
|
+
end
|
189
|
+
PBBUILDER
|
190
|
+
|
191
|
+
assert_equal "Miss", result["name"]
|
192
|
+
end
|
193
|
+
|
194
|
+
test "conditional object fragment caching" do
|
195
|
+
render(<<-JBUILDER)
|
196
|
+
pb.cache_if! true, "cache-key" do
|
197
|
+
pb.name "Hit"
|
198
|
+
end
|
199
|
+
|
200
|
+
pb.cache_if! false, "cache-key" do
|
201
|
+
pb.last_name "Hit"
|
202
|
+
end
|
203
|
+
JBUILDER
|
204
|
+
|
205
|
+
result = render(<<-JBUILDER)
|
206
|
+
pb.cache_if! true, "cache-key" do
|
207
|
+
pb.name "Miss"
|
208
|
+
end
|
209
|
+
|
210
|
+
pb.cache_if! false, "cache-key" do
|
211
|
+
pb.last_name "Miss"
|
212
|
+
end
|
213
|
+
JBUILDER
|
214
|
+
|
215
|
+
assert_equal "Hit", result["name"]
|
216
|
+
assert_equal "Miss", result["last_name"]
|
217
|
+
end
|
218
|
+
|
80
219
|
private
|
81
220
|
|
82
221
|
def render(*args)
|
data/test/test_helper.rb
CHANGED
@@ -1,9 +1,6 @@
|
|
1
|
-
|
2
|
-
ENV["RAILS_ENV"] = "test"
|
1
|
+
require "bundler/setup"
|
3
2
|
|
4
3
|
require "rails"
|
5
|
-
require "rails/test_help"
|
6
|
-
require "rails/test_unit/reporter"
|
7
4
|
|
8
5
|
require "active_support"
|
9
6
|
require "active_support/core_ext/array/access"
|
@@ -11,24 +8,27 @@ require "active_support/cache/memory_store"
|
|
11
8
|
require "active_support/json"
|
12
9
|
require "active_model"
|
13
10
|
require "action_view"
|
14
|
-
require "rails/version"
|
15
11
|
|
16
12
|
require "pbbuilder"
|
17
13
|
|
18
|
-
Rails::TestUnitReporter.executable = "bin/test"
|
19
|
-
|
20
14
|
require "google/protobuf"
|
21
15
|
require "google/protobuf/field_mask_pb"
|
22
16
|
|
17
|
+
require "active_support/testing/autorun"
|
18
|
+
|
19
|
+
ActiveSupport.test_order = :random
|
20
|
+
|
23
21
|
Google::Protobuf::DescriptorPool.generated_pool.build do
|
24
22
|
add_file("pbbuilder.proto", syntax: :proto3) do
|
25
23
|
add_message "pbbuildertest.Person" do
|
26
24
|
optional :name, :string, 1
|
25
|
+
optional :last_name, :string, 8
|
27
26
|
repeated :friends, :message, 2, "pbbuildertest.Person"
|
28
27
|
optional :best_friend, :message, 3, "pbbuildertest.Person"
|
29
28
|
repeated :nicknames, :string, 4
|
30
29
|
optional :field_mask, :message, 5, "google.protobuf.FieldMask"
|
31
30
|
map :favourite_foods, :string, :string, 6
|
31
|
+
repeated :tags, :string, 7
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
@@ -37,6 +37,12 @@ module API
|
|
37
37
|
Person = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pbbuildertest.Person").msgclass
|
38
38
|
end
|
39
39
|
|
40
|
+
class << Rails
|
41
|
+
def cache
|
42
|
+
@cache ||= ActiveSupport::Cache::MemoryStore.new
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
40
46
|
class Racer < Struct.new(:id, :name, :friends, :best_friend)
|
41
47
|
extend ActiveModel::Naming
|
42
48
|
include ActiveModel::Conversion
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pbbuilder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bouke van der Bijl
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: google-protobuf
|
@@ -16,14 +16,56 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
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: m
|
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: pry
|
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'
|
27
69
|
description:
|
28
70
|
email:
|
29
71
|
- bouke@cheddar.me
|
@@ -36,6 +78,7 @@ files:
|
|
36
78
|
- ".gitignore"
|
37
79
|
- ".ruby-version"
|
38
80
|
- Appraisals
|
81
|
+
- CHANGELOG.md
|
39
82
|
- Gemfile
|
40
83
|
- MIT-LICENSE
|
41
84
|
- README.md
|
@@ -44,15 +87,15 @@ files:
|
|
44
87
|
- bin/test
|
45
88
|
- gemfiles/.bundle/config
|
46
89
|
- gemfiles/rails_6_1.gemfile
|
47
|
-
- gemfiles/
|
48
|
-
- gemfiles/
|
49
|
-
- gemfiles/rails_7.gemfile.lock
|
90
|
+
- gemfiles/rails_7_0.gemfile
|
91
|
+
- gemfiles/rails_head.gemfile
|
50
92
|
- lib/pbbuilder.rb
|
93
|
+
- lib/pbbuilder/errors.rb
|
51
94
|
- lib/pbbuilder/handler.rb
|
95
|
+
- lib/pbbuilder/pbbuilder.rb
|
52
96
|
- lib/pbbuilder/protobuf_extension.rb
|
53
97
|
- lib/pbbuilder/railtie.rb
|
54
98
|
- lib/pbbuilder/template.rb
|
55
|
-
- lib/tasks/pbbuilder_tasks.rake
|
56
99
|
- pbbuilder.gemspec
|
57
100
|
- test/pbbuilder_template_test.rb
|
58
101
|
- test/pbbuilder_test.rb
|
@@ -70,17 +113,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
70
113
|
requirements:
|
71
114
|
- - ">="
|
72
115
|
- !ruby/object:Gem::Version
|
73
|
-
version: '
|
116
|
+
version: '2.7'
|
74
117
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
118
|
requirements:
|
76
119
|
- - ">="
|
77
120
|
- !ruby/object:Gem::Version
|
78
121
|
version: '0'
|
79
122
|
requirements: []
|
80
|
-
rubygems_version: 3.3.
|
123
|
+
rubygems_version: 3.3.7
|
81
124
|
signing_key:
|
82
125
|
specification_version: 4
|
83
|
-
summary: Generate Protobuf
|
126
|
+
summary: Generate Protobuf Messages with a simple DSL similar to JBuilder
|
84
127
|
test_files:
|
85
128
|
- test/pbbuilder_template_test.rb
|
86
129
|
- test/pbbuilder_test.rb
|
@@ -1,152 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: ..
|
3
|
-
specs:
|
4
|
-
pbbuilder (0.10.0)
|
5
|
-
google-protobuf (>= 3.19.2)
|
6
|
-
|
7
|
-
GEM
|
8
|
-
remote: https://rubygems.org/
|
9
|
-
specs:
|
10
|
-
actioncable (6.1.4.4)
|
11
|
-
actionpack (= 6.1.4.4)
|
12
|
-
activesupport (= 6.1.4.4)
|
13
|
-
nio4r (~> 2.0)
|
14
|
-
websocket-driver (>= 0.6.1)
|
15
|
-
actionmailbox (6.1.4.4)
|
16
|
-
actionpack (= 6.1.4.4)
|
17
|
-
activejob (= 6.1.4.4)
|
18
|
-
activerecord (= 6.1.4.4)
|
19
|
-
activestorage (= 6.1.4.4)
|
20
|
-
activesupport (= 6.1.4.4)
|
21
|
-
mail (>= 2.7.1)
|
22
|
-
actionmailer (6.1.4.4)
|
23
|
-
actionpack (= 6.1.4.4)
|
24
|
-
actionview (= 6.1.4.4)
|
25
|
-
activejob (= 6.1.4.4)
|
26
|
-
activesupport (= 6.1.4.4)
|
27
|
-
mail (~> 2.5, >= 2.5.4)
|
28
|
-
rails-dom-testing (~> 2.0)
|
29
|
-
actionpack (6.1.4.4)
|
30
|
-
actionview (= 6.1.4.4)
|
31
|
-
activesupport (= 6.1.4.4)
|
32
|
-
rack (~> 2.0, >= 2.0.9)
|
33
|
-
rack-test (>= 0.6.3)
|
34
|
-
rails-dom-testing (~> 2.0)
|
35
|
-
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
36
|
-
actiontext (6.1.4.4)
|
37
|
-
actionpack (= 6.1.4.4)
|
38
|
-
activerecord (= 6.1.4.4)
|
39
|
-
activestorage (= 6.1.4.4)
|
40
|
-
activesupport (= 6.1.4.4)
|
41
|
-
nokogiri (>= 1.8.5)
|
42
|
-
actionview (6.1.4.4)
|
43
|
-
activesupport (= 6.1.4.4)
|
44
|
-
builder (~> 3.1)
|
45
|
-
erubi (~> 1.4)
|
46
|
-
rails-dom-testing (~> 2.0)
|
47
|
-
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
48
|
-
activejob (6.1.4.4)
|
49
|
-
activesupport (= 6.1.4.4)
|
50
|
-
globalid (>= 0.3.6)
|
51
|
-
activemodel (6.1.4.4)
|
52
|
-
activesupport (= 6.1.4.4)
|
53
|
-
activerecord (6.1.4.4)
|
54
|
-
activemodel (= 6.1.4.4)
|
55
|
-
activesupport (= 6.1.4.4)
|
56
|
-
activestorage (6.1.4.4)
|
57
|
-
actionpack (= 6.1.4.4)
|
58
|
-
activejob (= 6.1.4.4)
|
59
|
-
activerecord (= 6.1.4.4)
|
60
|
-
activesupport (= 6.1.4.4)
|
61
|
-
marcel (~> 1.0.0)
|
62
|
-
mini_mime (>= 1.1.0)
|
63
|
-
activesupport (6.1.4.4)
|
64
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
65
|
-
i18n (>= 1.6, < 2)
|
66
|
-
minitest (>= 5.1)
|
67
|
-
tzinfo (~> 2.0)
|
68
|
-
zeitwerk (~> 2.3)
|
69
|
-
appraisal (2.4.1)
|
70
|
-
bundler
|
71
|
-
rake
|
72
|
-
thor (>= 0.14.0)
|
73
|
-
builder (3.2.4)
|
74
|
-
concurrent-ruby (1.1.9)
|
75
|
-
crass (1.0.6)
|
76
|
-
erubi (1.10.0)
|
77
|
-
globalid (1.0.0)
|
78
|
-
activesupport (>= 5.0)
|
79
|
-
google-protobuf (3.19.2)
|
80
|
-
i18n (1.8.11)
|
81
|
-
concurrent-ruby (~> 1.0)
|
82
|
-
loofah (2.13.0)
|
83
|
-
crass (~> 1.0.2)
|
84
|
-
nokogiri (>= 1.5.9)
|
85
|
-
mail (2.7.1)
|
86
|
-
mini_mime (>= 0.1.1)
|
87
|
-
marcel (1.0.2)
|
88
|
-
method_source (1.0.0)
|
89
|
-
mini_mime (1.1.2)
|
90
|
-
mini_portile2 (2.7.1)
|
91
|
-
minitest (5.15.0)
|
92
|
-
nio4r (2.5.8)
|
93
|
-
nokogiri (1.13.0)
|
94
|
-
mini_portile2 (~> 2.7.0)
|
95
|
-
racc (~> 1.4)
|
96
|
-
racc (1.6.0)
|
97
|
-
rack (2.2.3)
|
98
|
-
rack-test (1.1.0)
|
99
|
-
rack (>= 1.0, < 3)
|
100
|
-
rails (6.1.4.4)
|
101
|
-
actioncable (= 6.1.4.4)
|
102
|
-
actionmailbox (= 6.1.4.4)
|
103
|
-
actionmailer (= 6.1.4.4)
|
104
|
-
actionpack (= 6.1.4.4)
|
105
|
-
actiontext (= 6.1.4.4)
|
106
|
-
actionview (= 6.1.4.4)
|
107
|
-
activejob (= 6.1.4.4)
|
108
|
-
activemodel (= 6.1.4.4)
|
109
|
-
activerecord (= 6.1.4.4)
|
110
|
-
activestorage (= 6.1.4.4)
|
111
|
-
activesupport (= 6.1.4.4)
|
112
|
-
bundler (>= 1.15.0)
|
113
|
-
railties (= 6.1.4.4)
|
114
|
-
sprockets-rails (>= 2.0.0)
|
115
|
-
rails-dom-testing (2.0.3)
|
116
|
-
activesupport (>= 4.2.0)
|
117
|
-
nokogiri (>= 1.6)
|
118
|
-
rails-html-sanitizer (1.4.2)
|
119
|
-
loofah (~> 2.3)
|
120
|
-
railties (6.1.4.4)
|
121
|
-
actionpack (= 6.1.4.4)
|
122
|
-
activesupport (= 6.1.4.4)
|
123
|
-
method_source
|
124
|
-
rake (>= 0.13)
|
125
|
-
thor (~> 1.0)
|
126
|
-
rake (13.0.6)
|
127
|
-
sprockets (4.0.2)
|
128
|
-
concurrent-ruby (~> 1.0)
|
129
|
-
rack (> 1, < 3)
|
130
|
-
sprockets-rails (3.4.2)
|
131
|
-
actionpack (>= 5.2)
|
132
|
-
activesupport (>= 5.2)
|
133
|
-
sprockets (>= 3.0.0)
|
134
|
-
thor (1.2.1)
|
135
|
-
tzinfo (2.0.4)
|
136
|
-
concurrent-ruby (~> 1.0)
|
137
|
-
websocket-driver (0.7.5)
|
138
|
-
websocket-extensions (>= 0.1.0)
|
139
|
-
websocket-extensions (0.1.5)
|
140
|
-
zeitwerk (2.5.3)
|
141
|
-
|
142
|
-
PLATFORMS
|
143
|
-
ruby
|
144
|
-
|
145
|
-
DEPENDENCIES
|
146
|
-
appraisal
|
147
|
-
pbbuilder!
|
148
|
-
rails (~> 6.1.0)
|
149
|
-
rake
|
150
|
-
|
151
|
-
BUNDLED WITH
|
152
|
-
2.3.4
|
@@ -1,170 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: ..
|
3
|
-
specs:
|
4
|
-
pbbuilder (0.10.0)
|
5
|
-
google-protobuf (>= 3.19.2)
|
6
|
-
|
7
|
-
GEM
|
8
|
-
remote: https://rubygems.org/
|
9
|
-
specs:
|
10
|
-
actioncable (7.0.1)
|
11
|
-
actionpack (= 7.0.1)
|
12
|
-
activesupport (= 7.0.1)
|
13
|
-
nio4r (~> 2.0)
|
14
|
-
websocket-driver (>= 0.6.1)
|
15
|
-
actionmailbox (7.0.1)
|
16
|
-
actionpack (= 7.0.1)
|
17
|
-
activejob (= 7.0.1)
|
18
|
-
activerecord (= 7.0.1)
|
19
|
-
activestorage (= 7.0.1)
|
20
|
-
activesupport (= 7.0.1)
|
21
|
-
mail (>= 2.7.1)
|
22
|
-
net-imap
|
23
|
-
net-pop
|
24
|
-
net-smtp
|
25
|
-
actionmailer (7.0.1)
|
26
|
-
actionpack (= 7.0.1)
|
27
|
-
actionview (= 7.0.1)
|
28
|
-
activejob (= 7.0.1)
|
29
|
-
activesupport (= 7.0.1)
|
30
|
-
mail (~> 2.5, >= 2.5.4)
|
31
|
-
net-imap
|
32
|
-
net-pop
|
33
|
-
net-smtp
|
34
|
-
rails-dom-testing (~> 2.0)
|
35
|
-
actionpack (7.0.1)
|
36
|
-
actionview (= 7.0.1)
|
37
|
-
activesupport (= 7.0.1)
|
38
|
-
rack (~> 2.0, >= 2.2.0)
|
39
|
-
rack-test (>= 0.6.3)
|
40
|
-
rails-dom-testing (~> 2.0)
|
41
|
-
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
42
|
-
actiontext (7.0.1)
|
43
|
-
actionpack (= 7.0.1)
|
44
|
-
activerecord (= 7.0.1)
|
45
|
-
activestorage (= 7.0.1)
|
46
|
-
activesupport (= 7.0.1)
|
47
|
-
globalid (>= 0.6.0)
|
48
|
-
nokogiri (>= 1.8.5)
|
49
|
-
actionview (7.0.1)
|
50
|
-
activesupport (= 7.0.1)
|
51
|
-
builder (~> 3.1)
|
52
|
-
erubi (~> 1.4)
|
53
|
-
rails-dom-testing (~> 2.0)
|
54
|
-
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
55
|
-
activejob (7.0.1)
|
56
|
-
activesupport (= 7.0.1)
|
57
|
-
globalid (>= 0.3.6)
|
58
|
-
activemodel (7.0.1)
|
59
|
-
activesupport (= 7.0.1)
|
60
|
-
activerecord (7.0.1)
|
61
|
-
activemodel (= 7.0.1)
|
62
|
-
activesupport (= 7.0.1)
|
63
|
-
activestorage (7.0.1)
|
64
|
-
actionpack (= 7.0.1)
|
65
|
-
activejob (= 7.0.1)
|
66
|
-
activerecord (= 7.0.1)
|
67
|
-
activesupport (= 7.0.1)
|
68
|
-
marcel (~> 1.0)
|
69
|
-
mini_mime (>= 1.1.0)
|
70
|
-
activesupport (7.0.1)
|
71
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
72
|
-
i18n (>= 1.6, < 2)
|
73
|
-
minitest (>= 5.1)
|
74
|
-
tzinfo (~> 2.0)
|
75
|
-
appraisal (2.4.1)
|
76
|
-
bundler
|
77
|
-
rake
|
78
|
-
thor (>= 0.14.0)
|
79
|
-
builder (3.2.4)
|
80
|
-
concurrent-ruby (1.1.9)
|
81
|
-
crass (1.0.6)
|
82
|
-
digest (3.1.0)
|
83
|
-
erubi (1.10.0)
|
84
|
-
globalid (1.0.0)
|
85
|
-
activesupport (>= 5.0)
|
86
|
-
google-protobuf (3.19.2)
|
87
|
-
i18n (1.8.11)
|
88
|
-
concurrent-ruby (~> 1.0)
|
89
|
-
io-wait (0.2.1)
|
90
|
-
loofah (2.13.0)
|
91
|
-
crass (~> 1.0.2)
|
92
|
-
nokogiri (>= 1.5.9)
|
93
|
-
mail (2.7.1)
|
94
|
-
mini_mime (>= 0.1.1)
|
95
|
-
marcel (1.0.2)
|
96
|
-
method_source (1.0.0)
|
97
|
-
mini_mime (1.1.2)
|
98
|
-
mini_portile2 (2.7.1)
|
99
|
-
minitest (5.15.0)
|
100
|
-
net-imap (0.2.3)
|
101
|
-
digest
|
102
|
-
net-protocol
|
103
|
-
strscan
|
104
|
-
net-pop (0.1.1)
|
105
|
-
digest
|
106
|
-
net-protocol
|
107
|
-
timeout
|
108
|
-
net-protocol (0.1.2)
|
109
|
-
io-wait
|
110
|
-
timeout
|
111
|
-
net-smtp (0.3.1)
|
112
|
-
digest
|
113
|
-
net-protocol
|
114
|
-
timeout
|
115
|
-
nio4r (2.5.8)
|
116
|
-
nokogiri (1.13.0)
|
117
|
-
mini_portile2 (~> 2.7.0)
|
118
|
-
racc (~> 1.4)
|
119
|
-
racc (1.6.0)
|
120
|
-
rack (2.2.3)
|
121
|
-
rack-test (1.1.0)
|
122
|
-
rack (>= 1.0, < 3)
|
123
|
-
rails (7.0.1)
|
124
|
-
actioncable (= 7.0.1)
|
125
|
-
actionmailbox (= 7.0.1)
|
126
|
-
actionmailer (= 7.0.1)
|
127
|
-
actionpack (= 7.0.1)
|
128
|
-
actiontext (= 7.0.1)
|
129
|
-
actionview (= 7.0.1)
|
130
|
-
activejob (= 7.0.1)
|
131
|
-
activemodel (= 7.0.1)
|
132
|
-
activerecord (= 7.0.1)
|
133
|
-
activestorage (= 7.0.1)
|
134
|
-
activesupport (= 7.0.1)
|
135
|
-
bundler (>= 1.15.0)
|
136
|
-
railties (= 7.0.1)
|
137
|
-
rails-dom-testing (2.0.3)
|
138
|
-
activesupport (>= 4.2.0)
|
139
|
-
nokogiri (>= 1.6)
|
140
|
-
rails-html-sanitizer (1.4.2)
|
141
|
-
loofah (~> 2.3)
|
142
|
-
railties (7.0.1)
|
143
|
-
actionpack (= 7.0.1)
|
144
|
-
activesupport (= 7.0.1)
|
145
|
-
method_source
|
146
|
-
rake (>= 12.2)
|
147
|
-
thor (~> 1.0)
|
148
|
-
zeitwerk (~> 2.5)
|
149
|
-
rake (13.0.6)
|
150
|
-
strscan (3.0.1)
|
151
|
-
thor (1.2.1)
|
152
|
-
timeout (0.2.0)
|
153
|
-
tzinfo (2.0.4)
|
154
|
-
concurrent-ruby (~> 1.0)
|
155
|
-
websocket-driver (0.7.5)
|
156
|
-
websocket-extensions (>= 0.1.0)
|
157
|
-
websocket-extensions (0.1.5)
|
158
|
-
zeitwerk (2.5.3)
|
159
|
-
|
160
|
-
PLATFORMS
|
161
|
-
ruby
|
162
|
-
|
163
|
-
DEPENDENCIES
|
164
|
-
appraisal
|
165
|
-
pbbuilder!
|
166
|
-
rails (~> 7.0.0)
|
167
|
-
rake
|
168
|
-
|
169
|
-
BUNDLED WITH
|
170
|
-
2.3.4
|