validates_hostname 1.0.13 → 2.0.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: d3a217c6f18b34d7738f6a271bcd257f7a646e79765dc7d80499b4dc4817b8cb
4
- data.tar.gz: 23a45da7c0c7ab2afb06c543410514887a231fb36bd256ceb651f30d8ec78e94
3
+ metadata.gz: 6651611a1d3ae3384586746c26493e22375bee2c0f113cc8c48c86357b4fc5ba
4
+ data.tar.gz: '062741916c49420ea4c6837911d42c8c359d4dbb6407d8a4cf287714132efd2c'
5
5
  SHA512:
6
- metadata.gz: 1ad8e9409b9b6ad1500981eb07a71d888962681627decfcaa19bb7f17b4e7628ebbc3c53700e9489301f0b43d0c89141381858f422a3adca0c5f70bc2792187a
7
- data.tar.gz: cfe149c6565f6b8a140ef50cf5e16a54039960f701860a5966dcac8e5b84b8b912cb60ccb99e155c6eea5bad882c45adfbbc5fe67ff5c6915030685763e82455
6
+ metadata.gz: bfcb29a9a7c09bfcbbe5cc3d5f77bff624dada6afc390231a319f76e6ff00526544fec53b228ff7ca9f58e26277fbd798872eae594faa9ec6df4eb8d152f6caf
7
+ data.tar.gz: f5f59f302cac79e116a5967d81e28debac146122aa4c212cd40eab2f93c6d3904ea684624011b8069c608e7bba05ec277ca0da1d6e3b749a138c244b1c372d50
@@ -0,0 +1,23 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ tags: [v*]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ ruby-version: ["3.0", "3.1", "3.2", "3.3", "3.4"]
15
+ steps:
16
+ - uses: actions/checkout@v5
17
+ - name: Set up Ruby
18
+ uses: ruby/setup-ruby@v1
19
+ with:
20
+ ruby-version: ${{ matrix.ruby-version }}
21
+ bundler-cache: true
22
+ - name: Run tests
23
+ run: bundle exec rspec
@@ -0,0 +1,37 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v[0-9]+.[0-9]+.[0-9]+*"
7
+
8
+ jobs:
9
+ release:
10
+ name: Release to RubyGems.org
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ contents: read
14
+
15
+ steps:
16
+ - name: Checkout code
17
+ uses: actions/checkout@v5
18
+
19
+ - name: Set up Ruby
20
+ uses: ruby/setup-ruby@v1
21
+ with:
22
+ ruby-version: ".ruby-version"
23
+
24
+ - name: Configure RubyGems Credentials
25
+ run: |
26
+ mkdir -p $HOME/.gem
27
+ touch $HOME/.gem/credentials
28
+ chmod 0600 $HOME/.gem/credentials
29
+ printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
30
+ env:
31
+ GEM_HOST_API_KEY: ${{ secrets.GEM_HOST_API_KEY }}
32
+
33
+ - name: Build gem
34
+ run: gem build *.gemspec
35
+
36
+ - name: Push gem to RubyGems.org
37
+ run: gem push *.gem
@@ -0,0 +1,59 @@
1
+ name: Automated TLD Update and Release
2
+
3
+ on:
4
+ schedule:
5
+ - cron: "0 0 * * 0"
6
+ workflow_dispatch:
7
+
8
+ jobs:
9
+ update_and_release:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - name: Checkout code
13
+ uses: actions/checkout@v5
14
+ with:
15
+ token: ${{ secrets.GH_PAT }}
16
+
17
+ - name: Set up Ruby
18
+ uses: ruby/setup-ruby@v1
19
+ with:
20
+ ruby-version: ".ruby-version"
21
+ bundler-cache: true
22
+
23
+ - name: Update TLD list from IANA
24
+ run: bundle exec rake tlds:update
25
+
26
+ - name: Check for changes
27
+ id: git_diff
28
+ run: |
29
+ git diff --quiet data/tlds.txt || echo "changed=true" >> $GITHUB_OUTPUT
30
+
31
+ - name: Configure Git
32
+ if: steps.git_diff.outputs.changed == 'true'
33
+ run: |
34
+ git config user.name "github-actions[bot]"
35
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
36
+
37
+ - name: Bump version and push changes
38
+ if: steps.git_diff.outputs.changed == 'true'
39
+ run: |
40
+ # Extract the current version string, e.g., '2.0.0'
41
+ current_version=$(grep -oP "VERSION = '\K[^']+" lib/validates_hostname/version.rb)
42
+ echo "Current version: $current_version"
43
+
44
+ # Bump the patch version using Ruby
45
+ new_version=$(ruby -e "v = '$current_version'.split('.'); v[-1] = v[-1].to_i + 1; puts v.join('.')")
46
+ echo "New version: $new_version"
47
+
48
+ # Update the version file
49
+ sed -i "s/VERSION = '$current_version'/VERSION = '$new_version'/" lib/validates_hostname/version.rb
50
+
51
+ # Commit the changes
52
+ git add data/tlds.txt lib/validates_hostname/version.rb
53
+ git commit -m "chore: Update TLD list and bump version to v${new_version}" -m "This is an automated commit."
54
+
55
+ # Tag the new version
56
+ git tag "v${new_version}"
57
+
58
+ # Push the commit and the tag, triggering the release workflow
59
+ git push origin main --follow-tags
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ /pkg/
2
+ /tmp/
3
+ *.gem
4
+
5
+ .DS_Store
6
+ .vscode/
7
+ .idea/
8
+ .env
9
+
10
+ Gemfile.lock
11
+
12
+ /.yardoc/
13
+ /doc/
14
+ /rdoc/
15
+
16
+ /.rspec_status
17
+ coverage
18
+ /
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,35 @@
1
+ plugins:
2
+ - rubocop-rake
3
+ - rubocop-rspec
4
+
5
+ AllCops:
6
+ NewCops: enable
7
+ Exclude:
8
+ - "bin/*"
9
+ - "db/**/*"
10
+ - "config/**/*"
11
+ - "script/**/*"
12
+ - "vendor/**/*"
13
+ - "tmp/**/*"
14
+ - "node_modules/**/*"
15
+
16
+ Metrics/MethodLength:
17
+ Exclude:
18
+ - "lib/validates_hostname.rb"
19
+
20
+ Metrics/AbcSize:
21
+ Exclude:
22
+ - "lib/validates_hostname.rb"
23
+
24
+ Metrics/CyclomaticComplexity:
25
+ Exclude:
26
+ - "lib/validates_hostname.rb"
27
+
28
+ Metrics/PerceivedComplexity:
29
+ Exclude:
30
+ - "lib/validates_hostname.rb"
31
+
32
+ Metrics/BlockLength:
33
+ Exclude:
34
+ - "spec/hostname_validator_spec.rb"
35
+ - "validates_hostname.gemspec"
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.4.6
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ - 2.0.0 [2025-09-22] - new major release - decouple from ActiveRecord and modernize for ActiveModel
2
+ - 1.0.13 [2022-10-14] - allow for conditional validation, controlled with model method
3
+ - 1.0.11 [2020-08-18] - fixes for ruby 2.7
4
+ - 1.0.0 [2011-01-12]
5
+ - Initial commit
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ group :development, :test do
8
+ gem 'guard', '~> 2.19'
9
+ gem 'guard-rspec', '~> 4.7'
10
+ gem 'rake', '~> 13.0'
11
+ gem 'rspec', '~> 3.13'
12
+ gem 'rspec-collection_matchers', '~> 1.2'
13
+ gem 'rubocop', '~> 1.80'
14
+ gem 'rubocop-rake', '~> 0.7'
15
+ gem 'rubocop-rspec', '~> 3.7'
16
+ gem 'simplecov', '~> 0.21'
17
+ end
data/Guardfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ guard :rspec, cmd: 'rbenv exec bundle exec rspec' do
4
+ # Watch spec files
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+
7
+ # Watch lib files and run the corresponding spec
8
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
9
+
10
+ # Watch the spec_helper and run all specs
11
+ watch('spec/spec_helper.rb') { 'spec' }
12
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2009-2025 Kim Nørgaard
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,349 @@
1
+ # ValidatesHostname
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/validates_hostname.svg)](https://badge.fury.io/rb/validates_hostname)
4
+ [![CI](https://github.com/KimNorgaard/validates_hostname/actions/workflows/ci.yml/badge.svg)](https://github.com/KimNorgaard/validates_hostname/actions/workflows/ci.yml)
5
+
6
+ ## Description
7
+
8
+ Extension to ActiveModel for validating hostnames and domain names.
9
+
10
+ ## Requirements
11
+
12
+ - Ruby >= 3.0.0
13
+ - Active Model >= 6.0
14
+
15
+ ## Features
16
+
17
+ - Adds validation for hostnames to ActiveModel
18
+ - Supports I18n for the error messages
19
+
20
+ ## Installation
21
+
22
+ As a gem:
23
+
24
+ ```bash
25
+ # in Gemfile
26
+ gem 'validates_hostname', '~> 2.0'
27
+
28
+ # Run bundler
29
+ bundle install
30
+ ```
31
+
32
+ ## Validations Performed
33
+
34
+ The following validations are performed on the hostname:
35
+
36
+ - The maximum length of the hostname is 255 characters.
37
+ - The maximum length of each hostname label is 63 characters.
38
+ - The allowed characters in hostname labels are `a-z`, `A-Z`, `0-9` and hyphen (`-`).
39
+ - Labels do not begin or end with a hyphen.
40
+ - Labels do not consist of numeric values only.
41
+
42
+ ## Options
43
+
44
+ The validator can be configured with the following options:
45
+
46
+ - `allow_underscore`: Allows for underscores in hostname labels.
47
+ - `require_valid_tld`: Requires that the last label is a valid TLD.
48
+ - `valid_tlds`: A list of valid TLDs. This option requires `require_valid_tld` to be `true`.
49
+ - `allow_numeric_hostname`: Allows numeric values in the first label of the hostname.
50
+ - `allow_wildcard_hostname`: Allows for a wildcard hostname in the first label.
51
+ - `allow_root_label`: Allows for a trailing dot (root label) in the hostname.
52
+
53
+ See also http://www.zytrax.com/books/dns/apa/names.html
54
+
55
+ ## How to Use
56
+
57
+ Simple usage:
58
+
59
+ ```ruby
60
+ class Record
61
+ include ActiveModel::Validations
62
+ attr_accessor :name
63
+
64
+ def self.model_name
65
+ ActiveModel::Name.new(self, nil, "Record")
66
+ end
67
+
68
+ validates :name, hostname: true
69
+ end
70
+ ```
71
+
72
+ With options:
73
+
74
+ ```ruby
75
+ class Record
76
+ include ActiveModel::Validations
77
+ attr_accessor :name
78
+
79
+ def self.model_name
80
+ ActiveModel::Name.new(self, nil, "Record")
81
+ end
82
+
83
+ validates :name, hostname: { allow_underscore: true }
84
+ end
85
+ ```
86
+
87
+ ## Options and Their Defaults
88
+
89
+ - `allow_underscore`: Permits underscore characters (`_`) in hostname labels. (default: `false`)
90
+ - `require_valid_tld`: Ensures that the hostname's last label is a recognized Top-Level Domain (TLD). (default: `false`)
91
+ - `valid_tlds`: An array of specific Top-Level Domains (TLDs) that are considered valid. This option requires `require_valid_tld` to be `true` to take effect. (default: List from `data/tlds.txt`)
92
+ - `allow_numeric_hostname`: Allows hostname labels to consist solely of numeric digits (e.g., `123.example.com`). Note: A hostname cannot consist of a single numeric label (e.g., `123` is always invalid). (default: `false`)
93
+ - `allow_wildcard_hostname`: Permits a wildcard character (`*`) as the first label of the hostname (e.g., `*.example.com`). (default: `false`)
94
+ - `allow_root_label`: Permits a trailing dot (root label) in the hostname (e.g., `example.com.`). (default: `false`)
95
+
96
+ ## Examples
97
+
98
+ Without options:
99
+
100
+ ```ruby
101
+ class Record
102
+ include ActiveModel::Validations
103
+ attr_accessor :name
104
+
105
+ def self.model_name
106
+ ActiveModel::Name.new(self, nil, "Record")
107
+ end
108
+
109
+ validates :name, hostname: true
110
+ end
111
+
112
+ >> @record = Record.new(name: "horse")
113
+ >> @record.save
114
+ => true
115
+
116
+ >> @record2 = Record.new(name: "_horse")
117
+ >> @record2.save
118
+ => false
119
+ ```
120
+
121
+ With `:allow_underscore`:
122
+
123
+ ```ruby
124
+ class Record
125
+ include ActiveModel::Validations
126
+ attr_accessor :name
127
+
128
+ def self.model_name
129
+ ActiveModel::Name.new(self, nil, "Record")
130
+ end
131
+
132
+ validates :name, hostname: { allow_underscore: true }
133
+ end
134
+
135
+ >> @record3 = Record.new(name: "_horse")
136
+ >> @record3.save
137
+ => true
138
+ ```
139
+
140
+ With `:require_valid_tld`:
141
+
142
+ ```ruby
143
+ class Record
144
+ include ActiveModel::Validations
145
+ attr_accessor :name
146
+
147
+ def self.model_name
148
+ ActiveModel::Name.new(self, nil, "Record")
149
+ end
150
+
151
+ validates :name, hostname: { require_valid_tld: true }
152
+ end
153
+
154
+ >> @record4 = Record.new(name: "horse")
155
+ >> @record4.save
156
+ => false
157
+
158
+ >> @record5 = Record.new(name: "horse.com")
159
+ >> @record5.save
160
+ => true
161
+ ```
162
+
163
+ With `:valid_tlds`:
164
+
165
+ ```ruby
166
+ class Record
167
+ include ActiveModel::Validations
168
+ attr_accessor :name
169
+
170
+ def self.model_name
171
+ ActiveModel::Name.new(self, nil, "Record")
172
+ end
173
+
174
+ validates :name, hostname: { require_valid_tld: true, valid_tlds: %w(com org net) }
175
+ end
176
+
177
+ >> @record6 = Record.new(name: "horse.info")
178
+ >> @record6.save
179
+ => false
180
+ ```
181
+
182
+ With `:allow_numeric_hostname`:
183
+
184
+ ```ruby
185
+ class Record
186
+ include ActiveModel::Validations
187
+ attr_accessor :name
188
+
189
+ def self.model_name
190
+ ActiveModel::Name.new(self, nil, "Record")
191
+ end
192
+
193
+ validates :name, hostname: { allow_numeric_hostname: false }
194
+ end
195
+
196
+ >> @record7 = Record.new(name: "123.info")
197
+ >> @record7.save
198
+ => false
199
+ ```
200
+
201
+ With `:allow_wildcard_hostname`:
202
+
203
+ ```ruby
204
+ class Record
205
+ include ActiveModel::Validations
206
+ attr_accessor :name
207
+
208
+ def self.model_name
209
+ ActiveModel::Name.new(self, nil, "Record")
210
+ end
211
+
212
+ validates :name, hostname: { allow_wildcard_hostname: true }
213
+ end
214
+
215
+ >> @record8 = Record.new(name: "*.123.info")
216
+ >> @record8.save
217
+ => true
218
+ ```
219
+
220
+ With `:allow_root_label`:
221
+
222
+ ```ruby
223
+ class Record
224
+ include ActiveModel::Validations
225
+ attr_accessor :name
226
+
227
+ def self.model_name
228
+ ActiveModel::Name.new(self, nil, "Record")
229
+ end
230
+
231
+ validates :name, hostname: { allow_root_label: true }
232
+ end
233
+
234
+ >> @record9 = Record.new(name: "example.com.")
235
+ >> @record9.save
236
+ => true
237
+ ```
238
+
239
+ ## Extra Validators
240
+
241
+ A few extra validators are included.
242
+
243
+ ### domainname
244
+
245
+ Sets `require_valid_tld` to `true`.
246
+
247
+ Sets `allow_numeric_hostname` to `true`. This option cannot be changed by the user.
248
+
249
+ Returns error if there is only one label and this label is numeric.
250
+
251
+ ```ruby
252
+ class Record
253
+ include ActiveModel::Validations
254
+ attr_accessor :name
255
+
256
+ def self.model_name
257
+ ActiveModel::Name.new(self, nil, "Record")
258
+ end
259
+
260
+ validates :name, domainname: true
261
+ end
262
+
263
+ >> @record = Record.new(name: "123.com")
264
+ >> @record.save
265
+ => true
266
+
267
+ >> @record2 = Record.new(name: "123")
268
+ >> @record2.save
269
+ => false
270
+ ```
271
+
272
+ ### fqdn
273
+
274
+ Sets `require_valid_tld` to `true`.
275
+
276
+ ```ruby
277
+ class Record
278
+ include ActiveModel::Validations
279
+ attr_accessor :name
280
+
281
+ def self.model_name
282
+ ActiveModel::Name.new(self, nil, "Record")
283
+ end
284
+
285
+ validates :name, fqdn: true
286
+ end
287
+
288
+ >> @record = Record.new(name: "example.com")
289
+ >> @record.save
290
+ => true
291
+
292
+ >> @record2 = Record.new(name: "example")
293
+ >> @record2.save
294
+ => false
295
+ ```
296
+
297
+ ### wildcard
298
+
299
+ Sets `allow_wildcard_hostname` to `true`.
300
+
301
+ ```ruby
302
+ class Record
303
+ include ActiveModel::Validations
304
+ attr_accessor :name
305
+
306
+ def self.model_name
307
+ ActiveModel::Name.new(self, nil, "Record")
308
+ end
309
+
310
+ validates :name, wildcard: true
311
+ end
312
+
313
+ >> @record = Record.new(name: "*.example.com")
314
+ >> @record.save
315
+ => true
316
+ ```
317
+
318
+ ## Error Messages
319
+
320
+ The gem uses the I18n system for error messages. You can provide your own
321
+ translations in your application's locale files (e.g., `config/locales/en.yml`).
322
+
323
+ Example of a custom error message in `config/locales/en.yml`:
324
+
325
+ ```yaml
326
+ en:
327
+ errors:
328
+ messages:
329
+ invalid_hostname_length: "is not a valid hostname length"
330
+ ```
331
+
332
+ The gem comes with the following built-in translations:
333
+
334
+ - English (en)
335
+ - Spanish (es)
336
+ - German (de)
337
+ - French (fr)
338
+ - Simplified Chinese (zh)
339
+
340
+ The `%{valid_chars}` interpolator is available for the
341
+ `label_contains_invalid_characters` message.
342
+
343
+ ## Maintainers
344
+
345
+ - [Kim Nørgaard](mailto:jasen@jasen.dk)
346
+
347
+ ## License
348
+
349
+ Copyright (c) 2009-2025 Kim Nørgaard, released under the MIT license.