timed_lru 0.4.0 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 256a5775aadc75a4ba0151c3b2530d77b6fe66d8a80163bd4a51500008fc81c4
4
- data.tar.gz: 2e46aa41b37eac70b04bcabac5abf3d160af09c4da00f8fa89b5e35223b9bf6a
3
+ metadata.gz: 32262a349b2bcc96380ae8cb5684ba4276ff2dd867b2d54b1f5fc92f537d0a1c
4
+ data.tar.gz: 0536c7d764505d25c48e7b0041051499f32166ac0ae259f30770d2d2dc58dbd5
5
5
  SHA512:
6
- metadata.gz: 225fa64f43a2d8c4d730060df4af035697a628f4080c06542828fef00b58c9c7f53d0b871bb60d27cf203f5a0fd34cb47540e4eb3655fe06a192df9a8d1f12ba
7
- data.tar.gz: 9a24526b95949e25e55b919d66a393a2fe7a1f0fcdd0315c7e8edf0c662038fdd9198d0a0fe808e54b4a66ac534763e6ca798a71f07238232ceeb0ef3214ea2d
6
+ metadata.gz: e61acf070a81d2b389131302435d49b9f7c0b663dc9840948cd63686bbea01e145a6b2f0df48ab4a72b52855b888c98a502f533b665423aa17d2f00d00d9f780
7
+ data.tar.gz: fda206b6600397bc0b486cfabb5a07b56bbdb67424da829ae14938e4025553f4c000ff2cbb3b3706d62d30b34c7cec78abeb5dfaf8bc7ee5949bd717d3d045c8
@@ -0,0 +1,21 @@
1
+ name: Ruby
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ ruby-version: ["2.6", "2.7", "3.0"]
15
+ steps:
16
+ - uses: actions/checkout@v2
17
+ - uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: ${{ matrix.ruby-version }}
20
+ bundler-cache: true
21
+ - run: bundle exec rake
data/.rubocop.yml CHANGED
@@ -1,8 +1,10 @@
1
- inherit_from:
2
- - https://gitlab.com/bsm/misc/raw/master/rubocop/default.yml
3
-
1
+ inherit_gem:
2
+ rubocop-bsm:
3
+ - default.yml
4
+ inherit_mode:
5
+ merge:
6
+ - Exclude
4
7
  AllCops:
5
- TargetRubyVersion: "2.4"
6
-
8
+ TargetRubyVersion: "2.6"
7
9
  Naming/MemoizedInstanceVariableName:
8
- Enabled: false
10
+ Enabled: false
data/Gemfile CHANGED
@@ -1,5 +1,2 @@
1
1
  source 'http://rubygems.org'
2
2
  gemspec
3
-
4
- gem 'coveralls', require: false, group: :test
5
- gem 'json', '>= 1.7.7', require: false, group: :test
data/Gemfile.lock CHANGED
@@ -1,70 +1,88 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- timed_lru (0.4.0)
4
+ timed_lru (0.5.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
8
8
  specs:
9
- ast (2.4.0)
10
- coveralls (0.8.23)
11
- json (>= 1.8, < 3)
12
- simplecov (~> 0.16.1)
13
- term-ansicolor (~> 1.3)
14
- thor (>= 0.19.4, < 2.0)
15
- tins (~> 1.6)
16
- diff-lcs (1.3)
17
- docile (1.3.2)
18
- jaro_winkler (1.5.3)
19
- json (2.2.0)
20
- parallel (1.17.0)
21
- parser (2.6.3.0)
22
- ast (~> 2.4.0)
9
+ activesupport (6.1.3)
10
+ concurrent-ruby (~> 1.0, >= 1.0.2)
11
+ i18n (>= 1.6, < 2)
12
+ minitest (>= 5.1)
13
+ tzinfo (~> 2.0)
14
+ zeitwerk (~> 2.3)
15
+ ast (2.4.2)
16
+ concurrent-ruby (1.1.8)
17
+ diff-lcs (1.4.4)
18
+ i18n (1.8.9)
19
+ concurrent-ruby (~> 1.0)
20
+ minitest (5.14.4)
21
+ parallel (1.20.1)
22
+ parser (3.0.0.0)
23
+ ast (~> 2.4.1)
24
+ rack (2.2.3)
23
25
  rainbow (3.0.0)
24
- rake (12.3.3)
25
- rspec (3.8.0)
26
- rspec-core (~> 3.8.0)
27
- rspec-expectations (~> 3.8.0)
28
- rspec-mocks (~> 3.8.0)
29
- rspec-core (3.8.2)
30
- rspec-support (~> 3.8.0)
31
- rspec-expectations (3.8.4)
26
+ rake (13.0.3)
27
+ regexp_parser (2.1.1)
28
+ rexml (3.2.4)
29
+ rspec (3.10.0)
30
+ rspec-core (~> 3.10.0)
31
+ rspec-expectations (~> 3.10.0)
32
+ rspec-mocks (~> 3.10.0)
33
+ rspec-core (3.10.1)
34
+ rspec-support (~> 3.10.0)
35
+ rspec-expectations (3.10.1)
32
36
  diff-lcs (>= 1.2.0, < 2.0)
33
- rspec-support (~> 3.8.0)
34
- rspec-mocks (3.8.1)
37
+ rspec-support (~> 3.10.0)
38
+ rspec-mocks (3.10.2)
35
39
  diff-lcs (>= 1.2.0, < 2.0)
36
- rspec-support (~> 3.8.0)
37
- rspec-support (3.8.2)
38
- rubocop (0.71.0)
39
- jaro_winkler (~> 1.5.1)
40
+ rspec-support (~> 3.10.0)
41
+ rspec-support (3.10.2)
42
+ rubocop (1.11.0)
40
43
  parallel (~> 1.10)
41
- parser (>= 2.6)
44
+ parser (>= 3.0.0.0)
42
45
  rainbow (>= 2.2.2, < 4.0)
46
+ regexp_parser (>= 1.8, < 3.0)
47
+ rexml
48
+ rubocop-ast (>= 1.2.0, < 2.0)
43
49
  ruby-progressbar (~> 1.7)
44
- unicode-display_width (>= 1.4.0, < 1.7)
45
- ruby-progressbar (1.10.1)
46
- simplecov (0.16.1)
47
- docile (~> 1.1)
48
- json (>= 1.8, < 3)
49
- simplecov-html (~> 0.10.0)
50
- simplecov-html (0.10.2)
51
- term-ansicolor (1.7.1)
52
- tins (~> 1.0)
53
- thor (0.20.3)
54
- tins (1.21.1)
55
- unicode-display_width (1.6.0)
50
+ unicode-display_width (>= 1.4.0, < 3.0)
51
+ rubocop-ast (1.4.1)
52
+ parser (>= 2.7.1.5)
53
+ rubocop-bsm (0.5.4)
54
+ rubocop (~> 1.0)
55
+ rubocop-performance
56
+ rubocop-rails
57
+ rubocop-rake
58
+ rubocop-rspec
59
+ rubocop-performance (1.10.1)
60
+ rubocop (>= 0.90.0, < 2.0)
61
+ rubocop-ast (>= 0.4.0)
62
+ rubocop-rails (2.9.1)
63
+ activesupport (>= 4.2.0)
64
+ rack (>= 1.1)
65
+ rubocop (>= 0.90.0, < 2.0)
66
+ rubocop-rake (0.5.1)
67
+ rubocop
68
+ rubocop-rspec (2.2.0)
69
+ rubocop (~> 1.0)
70
+ rubocop-ast (>= 1.1.0)
71
+ ruby-progressbar (1.11.0)
72
+ tzinfo (2.0.4)
73
+ concurrent-ruby (~> 1.0)
74
+ unicode-display_width (2.0.0)
75
+ zeitwerk (2.4.2)
56
76
 
57
77
  PLATFORMS
58
78
  ruby
59
79
 
60
80
  DEPENDENCIES
61
81
  bundler
62
- coveralls
63
- json (>= 1.7.7)
64
82
  rake
65
83
  rspec
66
- rubocop
84
+ rubocop-bsm
67
85
  timed_lru!
68
86
 
69
87
  BUNDLED WITH
70
- 2.0.1
88
+ 2.1.4
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2021 Black Square Media Ltd
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md CHANGED
@@ -1,16 +1,13 @@
1
- Timed LRU
2
- =========
1
+ # Timed LRU
3
2
 
4
3
  [![Build Status](https://travis-ci.org/bsm/timed_lru.png)](https://travis-ci.org/bsm/timed_lru)
5
4
  [![Dependency Status](https://gemnasium.com/bsm/timed_lru.png)](https://gemnasium.com/bsm/timed_lru)
6
- [![Coverage Status](https://coveralls.io/repos/bsm/timed_lru/badge.png)](https://coveralls.io/r/bsm/timed_lru)
7
5
 
8
6
  My implementation of a simple, thread-safe LRU with (optional) TTLs
9
7
  and constant time operations. There are many LRUs for Ruby available but
10
8
  I was unable to find one that matches all three requirements.
11
9
 
12
- Install
13
- -------
10
+ ## Install
14
11
 
15
12
  Install it via `gem`:
16
13
 
@@ -20,8 +17,7 @@ gem install timed_lru
20
17
 
21
18
  Or just bundle it with your project.
22
19
 
23
- Usage Example
24
- -------------
20
+ ## Usage Example
25
21
 
26
22
  ```ruby
27
23
  # Initialize with a max size (default: 100) and a TTL (default: none)
@@ -45,29 +41,3 @@ sleep(4)
45
41
  lru["c"] # => "value 3"
46
42
  lru.keys # => ["c", "d"]
47
43
  ```
48
-
49
- Licence
50
- -------
51
-
52
- ```
53
- Copyright (c) 2013 Black Square Media Ltd
54
-
55
- Permission is hereby granted, free of charge, to any person obtaining
56
- a copy of this software and associated documentation files (the
57
- "Software"), to deal in the Software without restriction, including
58
- without limitation the rights to use, copy, modify, merge, publish,
59
- distribute, sublicense, and/or sell copies of the Software, and to
60
- permit persons to whom the Software is furnished to do so, subject to
61
- the following conditions:
62
-
63
- The above copyright notice and this permission notice shall be
64
- included in all copies or substantial portions of the Software.
65
-
66
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
67
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
68
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
69
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
70
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
71
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
72
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
73
- ```
data/lib/timed_lru.rb CHANGED
@@ -23,22 +23,22 @@ class TimedLRU
23
23
  # @param [Hash] opts options
24
24
  # @option opts [Integer] max_size
25
25
  # maximum allowed number of items, defaults to 100
26
+ # @option opts [Integer,Float] ttl
27
+ # the TTL in seconds
26
28
  # @option opts [Boolean] thread_safe
27
29
  # true by default, set to false if you are not using threads a *really* need
28
30
  # that extra bit of performance
29
- # @option opts [Integer] ttl
30
- # the TTL in seconds
31
- def initialize(opts={})
31
+ def initialize(max_size: 100, ttl: nil, thread_safe: true)
32
32
  super() # MonitorMixin
33
33
 
34
34
  @hash = {}
35
- @max_size = Integer(opts[:max_size] || 100)
36
- @ttl = Integer(opts[:ttl]) if opts[:ttl]
35
+ @max_size = Integer(max_size)
36
+ @ttl = Float(ttl) if ttl
37
37
 
38
38
  raise ArgumentError, 'Option :max_size must be > 0' unless max_size.positive?
39
39
  raise ArgumentError, 'Option :ttl must be > 0' unless ttl.nil? || ttl.positive?
40
40
 
41
- extend ThreadUnsafe if opts[:thread_safe] == false
41
+ extend ThreadUnsafe if thread_safe == false
42
42
  end
43
43
 
44
44
  # Stores a `value` by `key`
@@ -84,8 +84,7 @@ class TimedLRU
84
84
 
85
85
  def compact!
86
86
  remove(@tail) while @hash.size > max_size
87
-
88
- remove(@tail) while ttl && @tail.expires_at < Time.now.to_i
87
+ remove(@tail) while ttl && @tail.expires_at < Time.now.to_f
89
88
  end
90
89
 
91
90
  def remove(node)
@@ -98,7 +97,7 @@ class TimedLRU
98
97
  end
99
98
 
100
99
  def touch(node)
101
- node.expires_at = Time.now.to_i + ttl if ttl
100
+ node.expires_at = Time.now.to_f + ttl if ttl
102
101
  return if node == @head
103
102
 
104
103
  left = node.left
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe TimedLRU do
4
-
5
4
  subject { described_class.new max_size: 4 }
6
5
 
7
6
  def full_chain
@@ -38,11 +37,13 @@ describe TimedLRU do
38
37
 
39
38
  describe '#max_size' do
40
39
  subject { super().max_size }
40
+
41
41
  it { is_expected.to be(100) }
42
42
  end
43
43
 
44
44
  describe '#ttl' do
45
45
  subject { super().ttl }
46
+
46
47
  it { is_expected.to be_nil }
47
48
  end
48
49
 
@@ -59,16 +60,19 @@ describe TimedLRU do
59
60
 
60
61
  describe '#max_size' do
61
62
  subject { super().max_size }
63
+
62
64
  it { is_expected.to be(25) }
63
65
  end
64
66
 
65
67
  describe '#ttl' do
66
68
  subject { super().ttl }
67
- it { is_expected.to be(120) }
69
+
70
+ it { is_expected.to eq(120.0) }
68
71
  end
72
+
69
73
  it { is_expected.to be_a(described_class::ThreadUnsafe) }
70
74
 
71
- it 'should assert correct option values' do
75
+ it 'asserts correct option values' do
72
76
  expect { described_class.new(max_size: 'X') }.to raise_error(ArgumentError)
73
77
  expect { described_class.new(max_size: -1) }.to raise_error(ArgumentError)
74
78
  expect { described_class.new(max_size: 0) }.to raise_error(ArgumentError)
@@ -80,46 +84,43 @@ describe TimedLRU do
80
84
  end
81
85
 
82
86
  describe 'storing' do
83
-
84
- it 'should set head + tail on first item' do
87
+ it 'sets head + tail on first item' do
85
88
  expect do
86
89
  expect(subject.store('a', 1)).to eq(1)
87
90
  end.to change { chain }.from([]).to(['a'])
88
91
  end
89
92
 
90
- it 'should shift chain when new items are added' do
93
+ it 'shifts chain when new items are added' do
91
94
  subject['a'] = 1
92
95
  expect { subject['b'] = 2 }.to change { chain }.from(%w[a]).to(%w[b a])
93
96
  expect { subject['c'] = 3 }.to change { chain }.to(%w[c b a])
94
97
  expect { subject['d'] = 4 }.to change { chain }.to(%w[d c b a])
95
98
  end
96
99
 
97
- it 'should expire LRU items when chain exceeds max size' do
100
+ it 'expires LRU items when chain exceeds max size' do
98
101
  ('a'..'d').each {|x| subject[x] = 1 }
99
102
  expect { subject['e'] = 5 }.to change { chain }.to(%w[e d c b])
100
103
  expect { subject['f'] = 6 }.to change { chain }.to(%w[f e d c])
101
104
  end
102
105
 
103
- it 'should update items' do
106
+ it 'updates items' do
104
107
  ('a'..'d').each {|x| subject[x] = 1 }
105
108
  expect { subject['d'] = 2 }.not_to change { chain }
106
109
  expect { subject['c'] = 2 }.to change { chain }.to(%w[c d b a])
107
110
  expect { subject['b'] = 2 }.to change { chain }.to(%w[b c d a])
108
111
  expect { subject['a'] = 2 }.to change { chain }.to(%w[a b c d])
109
112
  end
110
-
111
113
  end
112
114
 
113
115
  describe 'retrieving' do
114
-
115
- it 'should fetch values' do
116
+ it 'fetches values' do
116
117
  expect(subject.fetch('a')).to be_nil
117
118
  expect(subject['a']).to be_nil
118
119
  subject['a'] = 1
119
120
  expect(subject['a']).to eq(1)
120
121
  end
121
122
 
122
- it 'should renew membership on access' do
123
+ it 'renews membership on access' do
123
124
  ('a'..'d').each {|x| subject[x] = 1 }
124
125
  expect { subject['d'] }.not_to change { chain }
125
126
  expect { subject['c'] }.to change { chain }.to(%w[c d b a])
@@ -127,26 +128,23 @@ describe TimedLRU do
127
128
  expect { subject['a'] }.to change { chain }.to(%w[a b c d])
128
129
  expect { subject['x'] }.not_to change { chain }
129
130
  end
130
-
131
131
  end
132
132
 
133
133
  describe 'deleting' do
134
-
135
- it 'should delete an return values' do
134
+ it 'deletes an return values' do
136
135
  expect(subject.delete('a')).to be_nil
137
136
  subject['a'] = 1
138
137
  expect(subject.delete('a')).to eq(1)
139
138
  end
140
139
 
141
- it 'should re-arrange membership chain' do
140
+ it 're-arranges membership chain' do
142
141
  ('a'..'d').each {|x| subject[x] = 1 }
143
142
  expect { subject.delete('x') }.not_to change { chain }
144
143
  expect { subject.delete('c') }.to change { chain }.to(%w[d b a])
145
144
  expect { subject.delete('a') }.to change { chain }.to(%w[d b])
146
145
  expect { subject.delete('d') }.to change { chain }.to(%w[b])
147
- expect { subject.delete('b') }.to change { subject.size }.from(1).to(0)
146
+ expect { subject.delete('b') }.to change(subject, :size).from(1).to(0)
148
147
  end
149
-
150
148
  end
151
149
 
152
150
  describe 'TTL expiration' do
@@ -159,7 +157,7 @@ describe TimedLRU do
159
157
  allow(Time).to receive(:now).and_call_original
160
158
  end
161
159
 
162
- it 'should expire on access' do
160
+ it 'expires on access' do
163
161
  in_past(70) do
164
162
  subject['a'] = 1
165
163
  expect(chain).to eq(%w[a])
@@ -174,7 +172,7 @@ describe TimedLRU do
174
172
  expect(chain).to eq(%w[c b])
175
173
  end
176
174
 
177
- it 'should renew expiration on access' do
175
+ it 'renews expiration on access' do
178
176
  in_past(70) do
179
177
  subject['a'] = 1
180
178
  subject['b'] = 2
@@ -189,7 +187,5 @@ describe TimedLRU do
189
187
  subject['c'] = 3
190
188
  expect(chain).to eq(%w[c a])
191
189
  end
192
-
193
190
  end
194
-
195
191
  end
data/timed_lru.gemspec CHANGED
@@ -1,14 +1,15 @@
1
1
  Gem::Specification.new do |s|
2
- s.required_ruby_version = '>= 2.4.0'
2
+ s.required_ruby_version = '>= 2.6.0'
3
3
 
4
4
  s.name = File.basename(__FILE__, '.gemspec')
5
5
  s.summary = 'Timed LRU'
6
6
  s.description = 'Thread-safe LRU implementation with (optional) TTL and constant time operations'
7
- s.version = '0.4.0'
7
+ s.version = '0.5.0'
8
8
 
9
9
  s.authors = ['Black Square Media']
10
10
  s.email = 'info@blacksquaremedia.com'
11
11
  s.homepage = 'https://github.com/bsm/timed_lru'
12
+ s.license = 'Apache-2.0'
12
13
 
13
14
  s.require_path = 'lib'
14
15
  s.files = `git ls-files`.split("\n")
@@ -17,5 +18,5 @@ Gem::Specification.new do |s|
17
18
  s.add_development_dependency 'bundler'
18
19
  s.add_development_dependency 'rake'
19
20
  s.add_development_dependency 'rspec'
20
- s.add_development_dependency 'rubocop'
21
+ s.add_development_dependency 'rubocop-bsm'
21
22
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timed_lru
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Black Square Media
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-23 00:00:00.000000000 Z
11
+ date: 2021-03-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rubocop
56
+ name: rubocop-bsm
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -73,20 +73,21 @@ executables: []
73
73
  extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
+ - ".github/workflows/ruby.yml"
76
77
  - ".gitignore"
77
78
  - ".rubocop.yml"
78
- - ".travis.yml"
79
79
  - Gemfile
80
80
  - Gemfile.lock
81
+ - LICENSE
81
82
  - README.md
82
83
  - Rakefile
83
84
  - lib/timed_lru.rb
84
- - spec/coverage_helper.rb
85
85
  - spec/spec_helper.rb
86
86
  - spec/timed_lru_spec.rb
87
87
  - timed_lru.gemspec
88
88
  homepage: https://github.com/bsm/timed_lru
89
- licenses: []
89
+ licenses:
90
+ - Apache-2.0
90
91
  metadata: {}
91
92
  post_install_message:
92
93
  rdoc_options: []
@@ -96,14 +97,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
96
97
  requirements:
97
98
  - - ">="
98
99
  - !ruby/object:Gem::Version
99
- version: 2.4.0
100
+ version: 2.6.0
100
101
  required_rubygems_version: !ruby/object:Gem::Requirement
101
102
  requirements:
102
103
  - - ">="
103
104
  - !ruby/object:Gem::Version
104
105
  version: '0'
105
106
  requirements: []
106
- rubygems_version: 3.0.3
107
+ rubygems_version: 3.1.4
107
108
  signing_key:
108
109
  specification_version: 4
109
110
  summary: Timed LRU
data/.travis.yml DELETED
@@ -1,8 +0,0 @@
1
- language: ruby
2
- before_install:
3
- - gem install bundler
4
- rvm:
5
- - 2.4
6
- - 2.5
7
- - 2.6
8
- cache: bundler
@@ -1,4 +0,0 @@
1
- require 'coveralls'
2
-
3
- # Enable coverage
4
- Coveralls.wear!