in_time_scope 0.1.5 → 0.1.6

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: 3938b69e9b635a2d488513fbba9a0af9171e163accf5a776357f837f93783830
4
- data.tar.gz: eb16bb16cb6681cc8ffa67b10aa32b8e349f5df87734436a6e5d8ff7afebd26a
3
+ metadata.gz: f46c50d90f896b920a86f45ea49329a9629843c4c7550e065f22c4b20df35149
4
+ data.tar.gz: 6c927de51e73ba689314a7caaf5f419a23af0f61f35b80c09f1c5d4cfa63273d
5
5
  SHA512:
6
- metadata.gz: 0cea4dc04116f248f8343902d9aeeb875e6a3cac9dc6c772a9462daea7d99a526862d715af5e94fa45826896ab5cd832a55b7f31fb7b1a94e12649a0ea059984
7
- data.tar.gz: e55bc250bd8d38b6cc7fb5a2b1d81d808948244defe93aa4715fb052967f8b3318d62b5dd58e614b03ddaf528a3ddb7ef4ae07786f9dbc67e2eced0c28065d9d
6
+ metadata.gz: 4d861b025f3f455367ef485e40df6f98d83e55b1fd3c3b5fdf2cc6f57bbae2dd3dec94586bb1265b76859a83a3bd0c782a523315cf5188e3ccf9f62a8dcb6b2f
7
+ data.tar.gz: f712f1b0e82dfa596c1d805ef5f7ddd715bc39eb1fffee564df6eb98a68582f21d1f9822f7980471d91c70823e86c1e693599adcb2d77eb96c909059e7d90576
data/.rubocop.yml CHANGED
@@ -16,7 +16,7 @@ Metrics/AbcSize:
16
16
  Enabled: false
17
17
 
18
18
  Metrics/MethodLength:
19
- Max: 35
19
+ Max: 40
20
20
 
21
21
  Metrics/ModuleLength:
22
22
  Enabled: false
@@ -0,0 +1,46 @@
1
+ ---
2
+ targets:
3
+ - claudecode
4
+ description: Translate README.md and sync docs for all languages (ja, zh, fr, de)
5
+ ---
6
+
7
+ # Translate Documentation
8
+
9
+ Translate and sync documentation for multiple languages.
10
+
11
+ ## Instructions
12
+
13
+ ### 1. Sync English Documentation
14
+
15
+ 1. Read the current `README.md`
16
+ 2. Copy content to `docs/src/index.md`:
17
+ - Remove the language links line (`[English](README.md) | [日本語]...`)
18
+ - Keep everything else
19
+
20
+ ### 2. Translate to Other Languages
21
+
22
+ For each language directory (`docs/ja/`, `docs/zh/`, `docs/fr/`, `docs/de/`):
23
+
24
+ 1. Translate `docs/src/index.md` to `docs/{lang}/index.md`
25
+ 2. Translate `docs/src/point-system.md` to `docs/{lang}/point-system.md`
26
+ 3. Translate `docs/src/user-name-history.md` to `docs/{lang}/user-name-history.md`
27
+ 4. Update `docs/{lang}/SUMMARY.md` with translated titles
28
+
29
+ ### 3. Translation Guidelines
30
+
31
+ For each translation:
32
+ - Keep all code blocks unchanged
33
+ - Translate all text content naturally (not literal translation)
34
+ - Keep the same markdown structure
35
+ - Keep URLs and links unchanged
36
+ - Do NOT include language links in docs files
37
+ - Translate headings and navigation text in SUMMARY.md
38
+
39
+ ### 4. Language Codes
40
+
41
+ - `ja` - Japanese (日本語)
42
+ - `zh` - Chinese (中文)
43
+ - `fr` - French (Français)
44
+ - `de` - German (Deutsch)
45
+
46
+ $ARGUMENTS
@@ -1,8 +1,10 @@
1
- # CLAUDE.md
1
+ ---
2
+ targets:
3
+ - claudecode
4
+ root: true
5
+ ---
2
6
 
3
- This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
-
5
- ## Project Overview
7
+ # Project Overview
6
8
 
7
9
  InTimeScope is a Ruby gem that adds time-window scopes to ActiveRecord models. It provides a convenient way to query records that fall within specific time periods (between `start_at` and `end_at` timestamps), with support for nullable columns, custom column names, and multiple scopes per model.
8
10
 
@@ -39,7 +41,7 @@ bundle exec rake install
39
41
 
40
42
  ## Code Style
41
43
 
42
- - Ruby 3.1+ required
44
+ - Ruby 3.0+ required
43
45
  - Use double-quoted strings (enforced by RuboCop)
44
46
  - All files must have `# frozen_string_literal: true` header
45
47
 
@@ -47,8 +49,19 @@ bundle exec rake install
47
49
 
48
50
  Entry point is `lib/in_time_scope.rb` which defines the `InTimeScope` module. When included in an ActiveRecord model, it provides the `in_time_scope` class method that generates:
49
51
 
50
- - Class scope methods: `Model.in_time`, `Model.in_time(timestamp)`
51
- - Instance methods: `instance.in_time?`, `instance.in_time?(timestamp)`
52
+ **Primary scopes (records in time window):**
53
+ - `Model.in_time`, `Model.in_time(timestamp)` - class scope
54
+ - `instance.in_time?`, `instance.in_time?(timestamp)` - instance method
55
+
56
+ **Inverse scopes (records outside time window):**
57
+ - `Model.before_in_time` - records not yet started (`start_at > time`)
58
+ - `Model.after_in_time` - records already ended (`end_at <= time`)
59
+ - `Model.out_of_time` - records outside window (before OR after)
60
+ - Corresponding instance methods: `before_in_time?`, `after_in_time?`, `out_of_time?`
61
+
62
+ **Additional scopes for start-only/end-only patterns:**
63
+ - `Model.latest_in_time(:foreign_key)` - latest record per FK (for `has_one`)
64
+ - `Model.earliest_in_time(:foreign_key)` - earliest record per FK
52
65
 
53
66
  The gem auto-detects column nullability from the database schema to generate optimized SQL queries (simpler queries for NOT NULL columns, NULL-aware queries otherwise).
54
67
 
@@ -59,6 +72,9 @@ Key configuration options for `in_time_scope`:
59
72
 
60
73
  Setting `column: nil` disables that boundary, enabling start-only (history) or end-only (expiration) patterns.
61
74
 
75
+ Named scopes generate all methods with the scope name:
76
+ - `in_time_scope :published` → `in_time_published`, `before_in_time_published`, `after_in_time_published`, `out_of_time_published`
77
+
62
78
  ## Test Structure
63
79
 
64
80
  Tests use RSpec with SQLite3 in-memory database. Test models are defined in `spec/support/create_test_database.rb`:
data/README.md CHANGED
@@ -1,308 +1,191 @@
1
1
  # InTimeScope
2
2
 
3
- A Ruby gem that adds time-window scopes to ActiveRecord models. It provides a convenient way to query records that fall within specific time periods (between `start_at` and `end_at` timestamps), with support for nullable columns, custom column names, and multiple scopes per model.
3
+ [English](README.md) | [日本語](docs/ja/index.md) | [中文](docs/zh/index.md) | [Français](docs/fr/index.md) | [Deutsch](docs/de/index.md)
4
4
 
5
- ## Motivation
6
-
7
- This gem is inspired by [onk/shibaraku](https://github.com/onk/shibaraku). While shibaraku is a great gem, I wanted to extend it with additional features:
8
-
9
- - **Nullable column handling**: shibaraku generates SQL with `OR` conditions when columns allow `NULL`, which can impact query performance. InTimeScope auto-detects column nullability from the schema and generates optimized queries.
10
- - **Named scopes**: shibaraku only provides `in_time` method. InTimeScope allows multiple named scopes like `in_time_published`, `in_time_featured` per model.
11
- - **Start-only / End-only patterns**: Support for versioned records (start_at only, no end_at) and expiration patterns (end_at only, no start_at).
12
- - **has_one association support**: `latest_in_time` and `earliest_in_time` scopes optimized for `has_one` with `includes`, using NOT EXISTS subqueries.
13
-
14
- These features required significant architectural changes, so I created a new gem rather than extending shibaraku.
15
-
16
- ## Installation
17
-
18
- Install the gem and add to the application's Gemfile by executing:
19
-
20
- ```bash
21
- bundle add in_time_scope
22
- ```
23
-
24
- If bundler is not being used to manage dependencies, install the gem by executing:
25
-
26
- ```bash
27
- gem install in_time_scope
28
- ```
29
-
30
- ## Usage
31
-
32
- ### Basic: Nullable Time Window
33
- Use the defaults (`start_at` / `end_at`) even when the columns allow `NULL`.
5
+ Are you writing this every time in Rails?
34
6
 
35
7
  ```ruby
36
- create_table :events do |t|
37
- t.datetime :start_at, null: true
38
- t.datetime :end_at, null: true
39
-
40
- t.timestamps
41
- end
8
+ # Before
9
+ Event.where("start_at <= ? AND (end_at IS NULL OR end_at > ?)", Time.current, Time.current)
42
10
 
11
+ # After
43
12
  class Event < ActiveRecord::Base
44
- # Uses start_at / end_at by default
45
13
  in_time_scope
46
14
  end
47
15
 
48
16
  Event.in_time
49
- # => SELECT "events".* FROM "events" WHERE ("events"."start_at" IS NULL OR "events"."start_at" <= '2026-01-24 19:50:05.738232') AND ("events"."end_at" IS NULL OR "events"."end_at" > '2026-01-24 19:50:05.738232')
50
-
51
- # Check at a specific time
52
- Event.in_time(Time.parse("2024-06-01 12:00:00"))
53
-
54
- # Is the current time within the window?
55
- event = Event.first
56
- event.in_time?
57
- #=> true or false
58
-
59
- # Check any arbitrary timestamp
60
- event.in_time?(Time.parse("2024-06-01 12:00:00"))
61
- #=> true or false
62
17
  ```
63
18
 
64
- ### Basic: Non-Nullable Time Window
65
- When both timestamps are required (no `NULL`s), the generated query is simpler and faster.
19
+ That's it. One line of DSL, zero raw SQL in your models.
66
20
 
67
- ```ruby
68
- create_table :events do |t|
69
- t.datetime :start_at, null: false
70
- t.datetime :end_at, null: false
21
+ **This is a simple, thin gem that just provides scopes. No learning curve required.**
71
22
 
72
- t.timestamps
73
- end
23
+ ## Why This Gem?
74
24
 
75
- # Column metadata is read when Rails boots; SQL is optimized for NOT NULL columns.
76
- Event.in_time
77
- # => SELECT "events".* FROM "events" WHERE ("events"."start_at" <= '2026-01-24 19:50:05.738232') AND ("events"."end_at" > '2026-01-24 19:50:05.738232')
25
+ This gem exists to:
78
26
 
79
- # Check at a specific time
80
- Event.in_time(Time.parse("2024-06-01 12:00:00"))
81
- # => SELECT "events".* FROM "events" WHERE ("events"."start_at" <= '2024-06-01 12:00:00.000000') AND ("events"."end_at" > '2024-06-01 12:00:00.000000')
82
-
83
- class Event < ActiveRecord::Base
84
- # Explicitly mark columns as NOT NULL (even if the DB allows NULL)
85
- in_time_scope start_at: { null: false }, end_at: { null: false }
86
- end
87
- ```
27
+ - **Keep time-range logic consistent** across your entire codebase
28
+ - **Avoid copy-paste SQL** that's easy to get wrong
29
+ - **Make time a first-class domain concept** with named scopes like `in_time_published`
30
+ - **Auto-detect nullability** from your schema for optimized queries
88
31
 
89
- ### Options Reference
90
- Use these options in `in_time_scope` to customize column behavior.
32
+ ## Recommended For
91
33
 
92
- | Option | Applies to | Type | Default | Description | Example |
93
- | --- | --- | --- | --- | --- | --- |
94
- | `:scope_name` (1st arg) | in_time | `Symbol` | `:in_time` | Creates a named scope like `in_time_published` | `in_time_scope :published` |
95
- | `start_at: { column: ... }` | start_at | `Symbol` / `nil` | `:start_at` (or `:"<scope>_start_at"` when `:scope_name` is set) | Use a custom column name; set `nil` to disable `start_at` | `start_at: { column: :available_at }` |
96
- | `end_at: { column: ... }` | end_at | `Symbol` / `nil` | `:end_at` (or `:"<scope>_end_at"` when `:scope_name` is set) | Use a custom column name; set `nil` to disable `end_at` | `end_at: { column: nil }` |
97
- | `start_at: { null: ... }` | start_at | `true/false` | auto (schema) | Force NULL-aware vs NOT NULL behavior | `start_at: { null: false }` |
98
- | `end_at: { null: ... }` | end_at | `true/false` | auto (schema) | Force NULL-aware vs NOT NULL behavior | `end_at: { null: true }` |
99
- | `prefix: true` | scope_name | `true/false` | `false` | Use prefix style method name like `published_in_time` instead of `in_time_published` | `in_time_scope :published, prefix: true` |
34
+ - New Rails applications with validity periods
35
+ - Models with `start_at` / `end_at` columns
36
+ - Teams that want consistent time logic without scattered `where` clauses
100
37
 
101
- ### Alternative: Start-Only History (No `end_at`)
102
- Use this when periods never overlap and you want exactly one "current" row.
38
+ ## Installation
103
39
 
104
- **Requirements:**
105
- - `start_at` must be NOT NULL (a `ConfigurationError` is raised otherwise)
106
- - periods never overlap (validated)
107
- - the latest row is the current one
40
+ ```bash
41
+ bundle add in_time_scope
42
+ ```
108
43
 
109
- If your table still has an `end_at` column but you want to ignore it, disable it via options:
44
+ ## Quick Start
110
45
 
111
46
  ```ruby
112
47
  class Event < ActiveRecord::Base
113
- # Ignore end_at even if the column exists
114
- in_time_scope start_at: { null: false }, end_at: { column: nil }
48
+ in_time_scope
115
49
  end
116
50
 
117
- Event.in_time(Time.parse("2024-06-01 12:00:00"))
118
- # => SELECT "events".* FROM "events" WHERE "events"."start_at" <= '2024-06-01 12:00:00.000000'
119
-
120
- # Use .first with order to get the most recent single record
121
- Event.in_time.order(start_at: :desc).first
122
- ```
123
-
124
- With no `end_at`, each row implicitly ends at the next row's `start_at`.
125
- The scope returns all matching records (WHERE only, no ORDER), so:
126
- - Add `.order(start_at: :desc).first` for a single latest record
127
- - Use `latest_in_time` for efficient `has_one` associations
128
-
129
- Recommended index:
51
+ # Class scope
52
+ Event.in_time # Records active now
53
+ Event.in_time(Time.parse("2024-06-01")) # Records active at specific time
130
54
 
131
- ```sql
132
- CREATE INDEX index_events_on_start_at ON events (start_at);
55
+ # Instance method
56
+ event.in_time? # Is this record active now?
57
+ event.in_time?(some_time) # Was it active at that time?
133
58
  ```
134
59
 
135
- ### Alternative: End-Only Expiration (No `start_at`)
136
- Use this when a record is active immediately and expires at `end_at`.
60
+ ## Features
137
61
 
138
- **Requirements:**
139
- - `end_at` must be NOT NULL (a `ConfigurationError` is raised otherwise)
140
- - `start_at` is not used (implicit "always active")
62
+ ### Auto-Optimized SQL
141
63
 
142
- If your table still has a `start_at` column but you want to ignore it, disable it via options:
64
+ The gem reads your schema and generates the right SQL:
143
65
 
144
66
  ```ruby
145
- class Event < ActiveRecord::Base
146
- # Ignore start_at and only use end_at
147
- in_time_scope start_at: { column: nil }, end_at: { null: false }
148
- end
67
+ # NULL-allowed columns → NULL-aware query
68
+ WHERE (start_at IS NULL OR start_at <= ?) AND (end_at IS NULL OR end_at > ?)
149
69
 
150
- Event.in_time(Time.parse("2024-06-01 12:00:00"))
151
- # => SELECT "events".* FROM "events" WHERE "events"."end_at" > '2024-06-01 12:00:00.000000'
70
+ # NOT NULL columns → simple query
71
+ WHERE start_at <= ? AND end_at > ?
152
72
  ```
153
73
 
154
- Recommended index:
74
+ ### Named Scopes
155
75
 
156
- ```sql
157
- CREATE INDEX index_events_on_end_at ON events (end_at);
158
- ```
159
-
160
- ### Advanced: Custom Columns and Multiple Scopes
161
- Customize which columns are used and define more than one time window per model.
76
+ Multiple time windows per model:
162
77
 
163
78
  ```ruby
164
- create_table :events do |t|
165
- t.datetime :available_at, null: true
166
- t.datetime :expired_at, null: true
167
- t.datetime :published_start_at, null: false
168
- t.datetime :published_end_at, null: false
169
-
170
- t.timestamps
79
+ class Article < ActiveRecord::Base
80
+ in_time_scope :published # Article.in_time_published
81
+ in_time_scope :featured # Article.in_time_featured
171
82
  end
172
-
173
- class Event < ActiveRecord::Base
174
- # Use different column names
175
- in_time_scope start_at: { column: :available_at }, end_at: { column: :expired_at }
176
-
177
- # Define an additional scope - uses published_start_at / published_end_at by default
178
- in_time_scope :published
179
- end
180
-
181
- Event.in_time
182
- # => uses available_at / expired_at
183
-
184
- Event.in_time_published
185
- # => uses published_start_at / published_end_at
186
83
  ```
187
84
 
188
- ### Using `prefix: true` Option
189
- Use the `prefix: true` option if you prefer the scope name as a prefix instead of suffix.
85
+ ### Custom Columns
190
86
 
191
87
  ```ruby
192
- class Event < ActiveRecord::Base
193
- # With prefix: true, the method name becomes published_in_time instead of in_time_published
194
- in_time_scope :published, prefix: true
88
+ class Campaign < ActiveRecord::Base
89
+ in_time_scope start_at: { column: :available_at },
90
+ end_at: { column: :expired_at }
195
91
  end
196
-
197
- Event.published_in_time
198
- # => uses published_start_at / published_end_at
199
92
  ```
200
93
 
201
- ### Using with `has_one` Associations
202
-
203
- The start-only and end-only patterns provide `latest_in_time` and `earliest_in_time` scopes for efficient `has_one` associations.
204
-
205
- **Note:** These scopes are NOT available for full time window patterns (both `start_at` and `end_at`), because the concept of "latest" or "earliest" is ambiguous when there's a time range.
94
+ ### Start-Only Pattern (Version History)
206
95
 
207
- #### Simple approach: `in_time` + `order`
208
-
209
- `in_time` provides WHERE only. Add `order` externally:
96
+ For records where each row is valid until the next one:
210
97
 
211
98
  ```ruby
212
99
  class Price < ActiveRecord::Base
213
- belongs_to :user
214
-
215
100
  in_time_scope start_at: { null: false }, end_at: { column: nil }
216
101
  end
217
102
 
103
+ # Bonus: efficient has_one with NOT EXISTS
218
104
  class User < ActiveRecord::Base
219
- has_many :prices
220
-
221
- # in_time is WHERE only, add order externally
222
- has_one :current_price,
223
- -> { in_time.order(start_at: :desc) },
224
- class_name: "Price"
105
+ has_one :current_price, -> { latest_in_time(:user_id) }, class_name: "Price"
225
106
  end
107
+
108
+ User.includes(:current_price) # No N+1, fetches only latest per user
226
109
  ```
227
110
 
228
- This works but loads all matching records into memory when using `includes`.
111
+ ### End-Only Pattern (Expiration)
229
112
 
230
- #### Efficient approach: `latest_in_time` (NOT EXISTS) - Recommended
113
+ For records that are active until they expire:
231
114
 
232
115
  ```ruby
233
- class User < ActiveRecord::Base
234
- has_many :prices
235
-
236
- # Uses NOT EXISTS subquery - only loads the latest record per user
237
- has_one :current_price,
238
- -> { latest_in_time(:user_id) },
239
- class_name: "Price"
240
- end
241
-
242
- # Direct access
243
- user.current_price
244
- # => Returns the most recent price where start_at <= Time.current
245
-
246
- # Efficient with includes (only fetches latest record per user from DB)
247
- User.includes(:current_price).each do |user|
248
- puts user.current_price&.amount
116
+ class Coupon < ActiveRecord::Base
117
+ in_time_scope start_at: { column: nil }, end_at: { null: false }
249
118
  end
250
119
  ```
251
120
 
252
- The `latest_in_time(:foreign_key)` scope uses a `NOT EXISTS` subquery to filter at the database level, avoiding loading unnecessary records into memory.
121
+ ### Inverse Scopes
253
122
 
254
- #### Getting the earliest record: `earliest_in_time`
123
+ Query records outside the time window:
255
124
 
256
125
  ```ruby
257
- class User < ActiveRecord::Base
258
- has_many :prices
126
+ # Records not yet started (start_at > time)
127
+ Event.before_in_time
128
+ event.before_in_time?
259
129
 
260
- # Uses NOT EXISTS subquery - only loads the earliest record per user
261
- has_one :first_price,
262
- -> { earliest_in_time(:user_id) },
263
- class_name: "Price"
264
- end
130
+ # Records already ended (end_at <= time)
131
+ Event.after_in_time
132
+ event.after_in_time?
265
133
 
266
- # Direct access
267
- user.first_price
268
- # => Returns the earliest price where start_at <= Time.current
134
+ # Records outside time window (before OR after)
135
+ Event.out_of_time
136
+ event.out_of_time? # Logical inverse of in_time?
137
+ ```
269
138
 
270
- # Efficient with includes
271
- User.includes(:first_price).each do |user|
272
- puts user.first_price&.amount
273
- end
139
+ Works with named scopes too:
140
+
141
+ ```ruby
142
+ Article.before_in_time_published # Not yet published
143
+ Article.after_in_time_published # Publication ended
144
+ Article.out_of_time_published # Not currently published
274
145
  ```
275
146
 
276
- The `earliest_in_time(:foreign_key)` scope uses a `NOT EXISTS` subquery to find records where no earlier record exists for the same foreign key.
147
+ ## Options Reference
277
148
 
278
- ### Error Handling
149
+ | Option | Default | Description | Example |
150
+ | --- | --- | --- | --- |
151
+ | `scope_name` (1st arg) | `:in_time` | Named scope like `in_time_published` | `in_time_scope :published` |
152
+ | `start_at: { column: }` | `:start_at` | Custom column name, `nil` to disable | `start_at: { column: :available_at }` |
153
+ | `end_at: { column: }` | `:end_at` | Custom column name, `nil` to disable | `end_at: { column: nil }` |
154
+ | `start_at: { null: }` | auto-detect | Force NULL handling | `start_at: { null: false }` |
155
+ | `end_at: { null: }` | auto-detect | Force NULL handling | `end_at: { null: true }` |
279
156
 
280
- If you specify a scope name but the expected columns don't exist, a `ColumnNotFoundError` is raised at class load time:
157
+ ## Acknowledgements
281
158
 
282
- ```ruby
283
- class Event < ActiveRecord::Base
284
- # This will raise ColumnNotFoundError if hoge_start_at or hoge_end_at columns don't exist
285
- in_time_scope :hoge
286
- end
287
- # => InTimeScope::ColumnNotFoundError: Column 'hoge_start_at' does not exist on table 'events'
288
- ```
159
+ Inspired by [onk/shibaraku](https://github.com/onk/shibaraku). This gem extends the concept with:
289
160
 
290
- This helps catch configuration errors early during development.
161
+ - Schema-aware NULL handling for optimized queries
162
+ - Multiple named scopes per model
163
+ - Start-only / End-only patterns
164
+ - `latest_in_time` / `earliest_in_time` for efficient `has_one` associations
165
+ - Inverse scopes: `before_in_time`, `after_in_time`, `out_of_time`
291
166
 
292
167
  ## Development
293
168
 
294
- After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
169
+ ```bash
170
+ # Install dependencies
171
+ bin/setup
295
172
 
296
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
173
+ # Run tests
174
+ bundle exec rspec
297
175
 
298
- ## Contributing
176
+ # Run linting
177
+ bundle exec rubocop
299
178
 
300
- Bug reports and pull requests are welcome on GitHub at https://github.com/kyohah/in_time_scope. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/kyohah/in_time_scope/blob/main/CODE_OF_CONDUCT.md).
179
+ # Generate CLAUDE.md (for AI coding assistants)
180
+ npx rulesync generate
181
+ ```
301
182
 
302
- ## License
183
+ This project uses [rulesync](https://github.com/dyoshikawa/rulesync) to manage AI assistant rules. Edit `.rulesync/rules/*.md` and run `npx rulesync generate` to update `CLAUDE.md`.
303
184
 
304
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
185
+ ## Contributing
305
186
 
306
- ## Code of Conduct
187
+ Bug reports and pull requests are welcome on [GitHub](https://github.com/kyohah/in_time_scope).
188
+
189
+ ## License
307
190
 
308
- Everyone interacting in the InTimeScope project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/kyohah/in_time_scope/blob/main/CODE_OF_CONDUCT.md).
191
+ MIT License
data/docs/book.toml ADDED
@@ -0,0 +1,14 @@
1
+ [book]
2
+ title = "InTimeScope"
3
+ authors = ["kyohah"]
4
+ language = "en"
5
+ src = "src"
6
+
7
+ [build]
8
+ build-dir = "book"
9
+
10
+ [output.html]
11
+ default-theme = "light"
12
+ preferred-dark-theme = "navy"
13
+ git-repository-url = "https://github.com/kyohah/in_time_scope"
14
+ edit-url-template = "https://github.com/kyohah/in_time_scope/edit/main/docs/{path}"
@@ -0,0 +1,5 @@
1
+ # Inhaltsverzeichnis
2
+
3
+ - [Einführung](./index.md)
4
+ - [Punktesystem mit Ablaufdatum](./point-system.md)
5
+ - [Benutzernamen-Historie](./user-name-history.md)