pbbuilder 0.11.0 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|