get-smart 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +25 -3
- data/lib/get/smart/ai/verifier.rb +99 -0
- data/lib/get/smart/version.rb +1 -1
- metadata +17 -46
- data/files/gems/acts-as-taggable-on/expert/dynamic_tag_contexts.md +0 -31
- data/files/gems/devise/advanced/dynamic_omniauth_providers.md.md +0 -15
- data/files/gems/sidekiq/expert/sidekiq_retry_jitter.md +0 -31
- data/files/rails/active_record_associations/expert/recursive_self_referential_tree.md +0 -15
- data/files/rails/active_record_migrations/expert/squash_and_manage_migration_versions.md +0 -14
- data/files/rails/forms/advanced/stimulus_reflex_real_time_validation.md +0 -24
- data/files/rails/models/advanced/advisory_locks_for_concurrency_control.md +0 -8
- data/files/rails/secrets_and_credentials/advanced/credentials_rotation_workflow.md +0 -22
- data/files/rails/views/expert/i18n_view_precompilation.md +0 -15
- data/files/ruby/compression/expert/parallel_zstd_compression_with_ffi.md +0 -77
- data/files/ruby/concurrency_and_mutexes/expert/hybrid_spinlock.md +0 -53
- data/files/ruby/date_time/expert/leap_second_wrapper.md +0 -36
- data/files/ruby/file_io/expert/descriptor_manipulation.md +0 -25
- data/files/ruby/irb/expert/sandboxed_session.md +0 -17
- data/files/ruby/matrix/expert/cblas_dgemm_acceleration.md +0 -52
- data/files/ruby/matrix/expert/strassen_matrix_multiplication.md +0 -75
- data/files/ruby/strings/advanced/advanced_interpolation.md +0 -1
- data/files/ruby/strings/advanced/complex_escapes.md +0 -1
- data/files/ruby/strings/advanced/emoji_handling.md +0 -1
- data/files/ruby/strings/advanced/literals_stacking.md +0 -1
- data/files/ruby/strings/advanced/safe_concat.md +0 -1
- data/files/ruby/strings/advanced/strip_margin_heredoc.md +0 -1
- data/files/ruby/strings/advanced/unicode_normalization.md +0 -1
- data/files/ruby/strings/expert/ast_pattern_strings.md +0 -1
- data/files/ruby/strings/expert/deep_dup.md +0 -1
- data/files/ruby/strings/expert/demo_continue.md +0 -1
- data/files/ruby/strings/expert/drb_string_marshalling_hash.md +0 -1
- data/files/ruby/strings/expert/fiber_storage_usage.md +0 -1
- data/files/ruby/strings/expert/fstring_eval.md +0 -1
- data/files/ruby/strings/expert/functional_fstrings.md +0 -1
- data/files/ruby/strings/expert/gb_string_increment.md +0 -1
- data/files/ruby/strings/expert/heredoc_inheritance.md +0 -1
- data/files/ruby/strings/expert/opengl_strings.md +0 -1
- data/files/ruby/strings/expert/regex_named_captures.md +0 -1
- data/files/ruby/strings/expert/regex_performance.md +0 -1
- data/files/ruby/strings/expert/sprintf_named.md +0 -1
- data/files/ruby/strings/expert/stateful_sub/",{.md +0 -1
- data/files/ruby/strings/expert/strict_encodings.md +0 -1
- data/files/ruby/strings/expert/string_gc_optimizations.md +0 -1
- data/files/ruby/strings/expert/zero_copy_substring.md +0 -1
- data/files/ruby/strings/middle/demo.json.md +0 -1
- data/files/ruby/strings/middle/logging_demos.md.md +0 -1
- data/files/ruby/strings/middle/session_parse.md +0 -1
- data/files/ruby/syntax/advanced/define_method_with_closure.md +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f53c77e12fb7b9e5e0e9fd3f4990e838bd5d84c48e04c76780bb01c507030ed
|
4
|
+
data.tar.gz: e4c58a6b3e633a0143285a9e9d2cbebad716200ed04f95b0a61025f58ae0e366
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3b1050d969f0500009b220a206f5b695c7d286891f0bc48561e6d744a5e0251ca633b749e329c8a3e143cac052acc264a5fd24f4114a0d16e7d8b3c8759d853
|
7
|
+
data.tar.gz: b43cb1db8beefe010b144c40c00645d43f3211b63b95be987fcb348abf06809a07d5d2d989d1a714d3dab2bdda664b55bb2cd73a5ced4d5b11f7186f3d0dac88
|
data/README.md
CHANGED
@@ -1,14 +1,19 @@
|
|
1
1
|
# Get::Smart - Learn Ruby and Rails by examples
|
2
2
|
|
3
|
+
[](https://www.railsjazz.com)
|
4
|
+
[](https://www.patreon.com/igorkasyanchuk)
|
5
|
+
|
6
|
+
[](https://buymeacoffee.com/igorkasyanchuk)
|
7
|
+
|
3
8
|

|
4
9
|
|
5
10
|
Learn something new every time you boot your Rails application.
|
6
11
|
|
7
|
-
|
12
|
+
Note: all tips were generated by AI (using o4-mini) and stored in markdown files. Quick and dirty. I've validated them a Gemini AI, and some random manually.
|
8
13
|
|
9
14
|
Behind the scenes I have a simple logic to avoid showing the same tip twice and showing contextual tips (based on Gemfile, package.json, etc). Not everything is ready yet, but I'm working on it.
|
10
15
|
|
11
|
-
If you want to contribute, please create a PR with your changes.
|
16
|
+
If you want to contribute, please create a PR with your changes.
|
12
17
|
|
13
18
|
## Usage
|
14
19
|
|
@@ -120,6 +125,12 @@ Example:
|
|
120
125
|
bin/generator "ruby on rails security tips & tricks" "rails/security" 10 "middle"
|
121
126
|
```
|
122
127
|
|
128
|
+
Later you can verify the tips with (see #Verifier for more details).
|
129
|
+
|
130
|
+
```bash
|
131
|
+
bin/verifier files/rails/security
|
132
|
+
```
|
133
|
+
|
123
134
|
## Tree (in Rails app)
|
124
135
|
|
125
136
|
Get a tree of all the tips in the `files` folder (according to the current gem config).
|
@@ -170,9 +181,18 @@ bundle exec bin/generator "file compression in ruby advanced usage examples"
|
|
170
181
|
bundle exec bin/generator "file compression in ruby expert usage examples" "files/ruby/compression" 2 "expert"
|
171
182
|
```
|
172
183
|
|
173
|
-
|
174
184
|
To create folders in files/gems/devise folders (beginner, middle, advanced, expert).
|
175
185
|
|
186
|
+
## Verifier
|
187
|
+
|
188
|
+
Verifier uses Gemini API to verify the tips (an additional step to ensure the quality of the tips). Setup Gemini API key in `.env` file.
|
189
|
+
|
190
|
+
To verify the tips run:
|
191
|
+
|
192
|
+
```bash
|
193
|
+
bin/verifier files/gems/devise
|
194
|
+
```
|
195
|
+
|
176
196
|
## Tasks
|
177
197
|
|
178
198
|
- readme updates, how to use, options, how to contribute, links to other repos
|
@@ -191,3 +211,5 @@ You are welcome to contribute to the gem.
|
|
191
211
|
## License
|
192
212
|
|
193
213
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
214
|
+
|
215
|
+
[](https://buymeacoffee.com/igorkasyanchuk)
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require "faraday"
|
2
|
+
require "json"
|
3
|
+
require "active_support/all"
|
4
|
+
require "colorize"
|
5
|
+
module Get::Smart
|
6
|
+
module Ai
|
7
|
+
class Verifier
|
8
|
+
class GeminiClient
|
9
|
+
BASE_URL = "https://generativelanguage.googleapis.com/v1beta/models/"
|
10
|
+
DEFAULT_MODEL = "gemini-2.0-flash"
|
11
|
+
TEMPERATURE = 1.0
|
12
|
+
|
13
|
+
attr_reader :model
|
14
|
+
|
15
|
+
def initialize(model: DEFAULT_MODEL)
|
16
|
+
@model = model
|
17
|
+
end
|
18
|
+
|
19
|
+
def call(instructions:, prompt:, temperature: TEMPERATURE)
|
20
|
+
Faraday.post("#{BASE_URL}#{model}:generateContent?key=#{ENV.fetch("GEMINI_API_KEY")}") do |req|
|
21
|
+
req.headers["Content-Type"] = "application/json"
|
22
|
+
req.body = {
|
23
|
+
"contents": [ {
|
24
|
+
"parts": [ { "text": prompt } ]
|
25
|
+
} ],
|
26
|
+
"generationConfig": {
|
27
|
+
"response_mime_type": "application/json",
|
28
|
+
"temperature": temperature,
|
29
|
+
"maxOutputTokens": 30000
|
30
|
+
},
|
31
|
+
"system_instruction": {
|
32
|
+
"parts": [ {
|
33
|
+
"text": instructions
|
34
|
+
} ]
|
35
|
+
}
|
36
|
+
}.to_json
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
attr_reader :folder
|
42
|
+
def initialize(folder:)
|
43
|
+
@folder = folder
|
44
|
+
end
|
45
|
+
|
46
|
+
def call
|
47
|
+
files = Dir.glob("#{folder}/**/*.md")
|
48
|
+
files.each do |file|
|
49
|
+
begin
|
50
|
+
content = File.read(file)
|
51
|
+
response = GeminiClient.new.call(instructions: instructions, prompt: content)
|
52
|
+
json = JSON.parse(JSON.parse(response.body).dig("candidates", 0, "content", "parts", 0, "text"))
|
53
|
+
score_txt = json["score"].to_i >= 8 ? json["score"].to_i.to_s.green : json["score"].to_i.to_s.red
|
54
|
+
puts "#{file}: #{score_txt}" + (json["details"].present? ? " #{json["details"]}".yellow : "")
|
55
|
+
sleep 0.1
|
56
|
+
if File.size(file) < 10
|
57
|
+
puts "#{file}: DELETING, size: #{File.size(file)}"
|
58
|
+
File.delete(file)
|
59
|
+
end
|
60
|
+
rescue JSON::ParserError => e
|
61
|
+
puts "#{file}: SKIP"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def instructions
|
67
|
+
<<~INSTRUCTIONS
|
68
|
+
You are a helpful expert in Ruby and Rails, full stack developer with knowledge of Ruby, Rails, HTML, CSS, JavaScript, SQL, Git, and other related technologies.
|
69
|
+
Your role is to verify content of the useful tips for Ruby and Rails developers.
|
70
|
+
You need to rate the content of the tip from 1 to 10 in order to determine if it is working, useful and helpful for Ruby and Rails developers.
|
71
|
+
When 10 is the highest score, it means that the tip is working, useful and helpful for Ruby and Rails developers.
|
72
|
+
When 1 is the lowest score, it means that the tip is not working, not useful and not helpful for Ruby and Rails developers.
|
73
|
+
You need to return only the score from 1 to 10.
|
74
|
+
If file is empty, or no tip return 0.
|
75
|
+
If something is wrong with the tip return details about what is wrong and how to fix it, but keep short.
|
76
|
+
|
77
|
+
Example of response:
|
78
|
+
|
79
|
+
```json
|
80
|
+
{
|
81
|
+
"score": 10
|
82
|
+
}
|
83
|
+
```
|
84
|
+
|
85
|
+
or
|
86
|
+
|
87
|
+
```json
|
88
|
+
{
|
89
|
+
"score": 1,
|
90
|
+
"details": "The tip is not working, not useful and not helpful for Ruby and Rails developers."
|
91
|
+
}
|
92
|
+
```
|
93
|
+
|
94
|
+
Only reply in JSON format.
|
95
|
+
INSTRUCTIONS
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/lib/get/smart/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: get-smart
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Igor Kasyanchuk
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-05-
|
10
|
+
date: 2025-05-12 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: rails
|
@@ -163,6 +163,20 @@ dependencies:
|
|
163
163
|
- - ">="
|
164
164
|
- !ruby/object:Gem::Version
|
165
165
|
version: '0'
|
166
|
+
- !ruby/object:Gem::Dependency
|
167
|
+
name: faraday
|
168
|
+
requirement: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '0'
|
173
|
+
type: :development
|
174
|
+
prerelease: false
|
175
|
+
version_requirements: !ruby/object:Gem::Requirement
|
176
|
+
requirements:
|
177
|
+
- - ">="
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
version: '0'
|
166
180
|
description: Learn Ruby and Rails by examples
|
167
181
|
email:
|
168
182
|
- igorkasyanchuk@gmail.com
|
@@ -180,7 +194,6 @@ files:
|
|
180
194
|
- files/gems/acts-as-taggable-on/beginner/query_tags.md
|
181
195
|
- files/gems/acts-as-taggable-on/beginner/setup_gem.md
|
182
196
|
- files/gems/acts-as-taggable-on/expert/advanced_search_and_caching.md
|
183
|
-
- files/gems/acts-as-taggable-on/expert/dynamic_tag_contexts.md
|
184
197
|
- files/gems/acts-as-taggable-on/expert/hierarchical_tags_with_ancestry.md
|
185
198
|
- files/gems/acts-as-taggable-on/middle/caching_tag_counts.md
|
186
199
|
- files/gems/acts-as-taggable-on/middle/multiple_tag_contexts.md
|
@@ -223,7 +236,6 @@ files:
|
|
223
236
|
- files/gems/counter_culture/middle/scoped_comment_counter.md
|
224
237
|
- files/gems/devise/advanced/custom_password_strength_validator.md.md
|
225
238
|
- files/gems/devise/advanced/devise_jwt_integration.md.md
|
226
|
-
- files/gems/devise/advanced/dynamic_omniauth_providers.md.md
|
227
239
|
- files/gems/devise/advanced/multiple_user_scopes.md.md
|
228
240
|
- files/gems/devise/beginner/configure_routes.md
|
229
241
|
- files/gems/devise/beginner/customize_devise_views.md
|
@@ -473,7 +485,6 @@ files:
|
|
473
485
|
- files/gems/sidekiq/expert/sidekiq_batch_chaining.md
|
474
486
|
- files/gems/sidekiq/expert/sidekiq_dynamic_autoscaling.md
|
475
487
|
- files/gems/sidekiq/expert/sidekiq_opentelemetry_middleware.md
|
476
|
-
- files/gems/sidekiq/expert/sidekiq_retry_jitter.md
|
477
488
|
- files/gems/sidekiq/expert/sidekiq_tenant_isolation_namespace.md
|
478
489
|
- files/gems/sidekiq/middle/sidekiq_batch_grouping.md
|
479
490
|
- files/gems/sidekiq/middle/sidekiq_custom_middleware.md
|
@@ -809,7 +820,6 @@ files:
|
|
809
820
|
- files/rails/active_record_associations/expert/eager_load_override_select.md
|
810
821
|
- files/rails/active_record_associations/expert/multi_level_through_alias.md
|
811
822
|
- files/rails/active_record_associations/expert/polymorphic_counter_cache.md
|
812
|
-
- files/rails/active_record_associations/expert/recursive_self_referential_tree.md
|
813
823
|
- files/rails/active_record_associations/expert/scoped_polymorphic_association_conditions.md
|
814
824
|
- files/rails/active_record_associations/expert/sti_hierarchical_associations.md
|
815
825
|
- files/rails/active_record_associations/middle/association_extensions.md
|
@@ -893,7 +903,6 @@ files:
|
|
893
903
|
- files/rails/active_record_migrations/expert/parallel_migrations_via_rake.md
|
894
904
|
- files/rails/active_record_migrations/expert/postgresql_table_partitioning.md
|
895
905
|
- files/rails/active_record_migrations/expert/reversible_data_backfill.md
|
896
|
-
- files/rails/active_record_migrations/expert/squash_and_manage_migration_versions.md
|
897
906
|
- files/rails/active_record_migrations/middle/add_column_default_not_null.md
|
898
907
|
- files/rails/active_record_migrations/middle/add_index_options.md
|
899
908
|
- files/rails/active_record_migrations/middle/batch_data_migration.md
|
@@ -1319,7 +1328,6 @@ files:
|
|
1319
1328
|
- files/rails/forms/advanced/dynamic_nested_fields_with_cocoon.md
|
1320
1329
|
- files/rails/forms/advanced/form_object_with_reform.md
|
1321
1330
|
- files/rails/forms/advanced/multi_step_form_wizard.md
|
1322
|
-
- files/rails/forms/advanced/stimulus_reflex_real_time_validation.md
|
1323
1331
|
- files/rails/forms/beginner/checkbox_and_radio.md
|
1324
1332
|
- files/rails/forms/beginner/date_time_select.md
|
1325
1333
|
- files/rails/forms/beginner/display_error_messages.md
|
@@ -1485,7 +1493,6 @@ files:
|
|
1485
1493
|
- files/rails/middleware/middle/custom_request_logger_middleware.md
|
1486
1494
|
- files/rails/middleware/middle/middleware_insertion_points.md
|
1487
1495
|
- files/rails/middleware/middle/testing_middleware_integration.md
|
1488
|
-
- files/rails/models/advanced/advisory_locks_for_concurrency_control.md
|
1489
1496
|
- files/rails/models/advanced/bulk_upsert_with_upsert_all.md
|
1490
1497
|
- files/rails/models/advanced/composite_primary_keys_usage.md
|
1491
1498
|
- files/rails/models/advanced/custom_attribute_api_types.md
|
@@ -1601,7 +1608,6 @@ files:
|
|
1601
1608
|
- files/rails/routing/middle/route_globbing.md
|
1602
1609
|
- files/rails/routing/middle/routing_concerns.md
|
1603
1610
|
- files/rails/routing/middle/shallow_nesting.md
|
1604
|
-
- files/rails/secrets_and_credentials/advanced/credentials_rotation_workflow.md
|
1605
1611
|
- files/rails/secrets_and_credentials/advanced/environment_specific_credentials.md
|
1606
1612
|
- files/rails/secrets_and_credentials/advanced/nested_credentials_access.md
|
1607
1613
|
- files/rails/secrets_and_credentials/beginner/accessing_credentials_in_code.md
|
@@ -1744,7 +1750,6 @@ files:
|
|
1744
1750
|
- files/rails/views/expert/asset_pipeline_dynamic_paths.md
|
1745
1751
|
- files/rails/views/expert/cells_gem_decoupling.md
|
1746
1752
|
- files/rails/views/expert/custom_form_builder_dsl.md
|
1747
|
-
- files/rails/views/expert/i18n_view_precompilation.md
|
1748
1753
|
- files/rails/views/expert/mustache_template_integration.md
|
1749
1754
|
- files/rails/views/expert/nested_fragment_caching_strategies.md
|
1750
1755
|
- files/rails/views/expert/sse_in_views.md
|
@@ -1946,7 +1951,6 @@ files:
|
|
1946
1951
|
- files/ruby/compression/advanced/streaming_large_file_compression.md
|
1947
1952
|
- files/ruby/compression/beginner/compress_with_gzip.md
|
1948
1953
|
- files/ruby/compression/beginner/create_zip_archive.md
|
1949
|
-
- files/ruby/compression/expert/parallel_zstd_compression_with_ffi.md
|
1950
1954
|
- files/ruby/compression/expert/streaming_chunked_gzip_compression.md
|
1951
1955
|
- files/ruby/compression/middle/file_compression_gzip.md
|
1952
1956
|
- files/ruby/compression/middle/string_compression_deflate.md
|
@@ -1959,7 +1963,6 @@ files:
|
|
1959
1963
|
- files/ruby/concurrency_and_mutexes/beginner/shared_counter_with_mutex.md
|
1960
1964
|
- files/ruby/concurrency_and_mutexes/beginner/waiting_for_threads_join.md
|
1961
1965
|
- files/ruby/concurrency_and_mutexes/expert/fair_fifo_mutex.md
|
1962
|
-
- files/ruby/concurrency_and_mutexes/expert/hybrid_spinlock.md
|
1963
1966
|
- files/ruby/concurrency_and_mutexes/expert/lock_striping_mutex_shard.md
|
1964
1967
|
- files/ruby/concurrency_and_mutexes/expert/reentrant_mutex_monitor.md
|
1965
1968
|
- files/ruby/concurrency_and_mutexes/middle/condition_variable_usage.md
|
@@ -2039,7 +2042,6 @@ files:
|
|
2039
2042
|
- files/ruby/date_time/expert/astronomical_julian_day_conversion.md
|
2040
2043
|
- files/ruby/date_time/expert/business_calendar_refinement.md
|
2041
2044
|
- files/ruby/date_time/expert/high_res_monotonic_timing.md
|
2042
|
-
- files/ruby/date_time/expert/leap_second_wrapper.md
|
2043
2045
|
- files/ruby/date_time/expert/tzinfo_caching.md
|
2044
2046
|
- files/ruby/date_time/middle/business_day_calculation.md
|
2045
2047
|
- files/ruby/date_time/middle/calculate_durations.md
|
@@ -2144,7 +2146,6 @@ files:
|
|
2144
2146
|
- files/ruby/file_io/beginner/write_with_block.md
|
2145
2147
|
- files/ruby/file_io/expert/async_io_eventmachine.md
|
2146
2148
|
- files/ruby/file_io/expert/atomic_file_write.md
|
2147
|
-
- files/ruby/file_io/expert/descriptor_manipulation.md
|
2148
2149
|
- files/ruby/file_io/expert/memory_map_file.md
|
2149
2150
|
- files/ruby/file_io/expert/nonblocking_file_io.md
|
2150
2151
|
- files/ruby/file_io/expert/sparse_file_manipulation.md
|
@@ -2226,7 +2227,6 @@ files:
|
|
2226
2227
|
- files/ruby/irb/expert/input_preprocessor.md
|
2227
2228
|
- files/ruby/irb/expert/magic_commands_extension.md
|
2228
2229
|
- files/ruby/irb/expert/programmatic_irb_control.md
|
2229
|
-
- files/ruby/irb/expert/sandboxed_session.md
|
2230
2230
|
- files/ruby/irb/expert/threaded_debugging.md
|
2231
2231
|
- files/ruby/irb/middle/auto_require_gems.md
|
2232
2232
|
- files/ruby/irb/middle/awesome_print_output.md
|
@@ -2280,9 +2280,7 @@ files:
|
|
2280
2280
|
- files/ruby/matrix/beginner/matrix_basic_operations.md
|
2281
2281
|
- files/ruby/matrix/beginner/matrix_element_access.md
|
2282
2282
|
- files/ruby/matrix/beginner/matrix_initialization.md
|
2283
|
-
- files/ruby/matrix/expert/cblas_dgemm_acceleration.md
|
2284
2283
|
- files/ruby/matrix/expert/sparse_matrix_lazy_enumerator.md
|
2285
|
-
- files/ruby/matrix/expert/strassen_matrix_multiplication.md
|
2286
2284
|
- files/ruby/matrix/middle/matrix_basic_operations.md
|
2287
2285
|
- files/ruby/matrix/middle/matrix_enumeration_transform.md
|
2288
2286
|
- files/ruby/matrix/middle/matrix_transpose_and_diagonal.md
|
@@ -2730,17 +2728,10 @@ files:
|
|
2730
2728
|
- files/ruby/sockets/middle/socket_select_multiplex.md
|
2731
2729
|
- files/ruby/sockets/middle/tcp_client_basic.md
|
2732
2730
|
- files/ruby/sockets/middle/tcp_server_basic.md
|
2733
|
-
- files/ruby/strings/advanced/advanced_interpolation.md
|
2734
2731
|
- files/ruby/strings/advanced/binary_encoding_manipulation.md
|
2735
|
-
- files/ruby/strings/advanced/complex_escapes.md
|
2736
|
-
- files/ruby/strings/advanced/emoji_handling.md
|
2737
2732
|
- files/ruby/strings/advanced/freezing_and_symbols.md
|
2738
|
-
- files/ruby/strings/advanced/literals_stacking.md
|
2739
2733
|
- files/ruby/strings/advanced/percent_quoting_variants.md
|
2740
2734
|
- files/ruby/strings/advanced/regex_match_performance.md
|
2741
|
-
- files/ruby/strings/advanced/safe_concat.md
|
2742
|
-
- files/ruby/strings/advanced/strip_margin_heredoc.md
|
2743
|
-
- files/ruby/strings/advanced/unicode_normalization.md
|
2744
2735
|
- files/ruby/strings/beginner/common_string_methods.md
|
2745
2736
|
- files/ruby/strings/beginner/heredoc_string.md
|
2746
2737
|
- files/ruby/strings/beginner/length_and_empty.md
|
@@ -2752,42 +2743,22 @@ files:
|
|
2752
2743
|
- files/ruby/strings/beginner/string_slicing.md
|
2753
2744
|
- files/ruby/strings/beginner/substring_replacement.md
|
2754
2745
|
- files/ruby/strings/expert/advanced_named_captures.md
|
2755
|
-
- files/ruby/strings/expert/ast_pattern_strings.md
|
2756
2746
|
- files/ruby/strings/expert/binary_data_handling_string_b.md
|
2757
2747
|
- files/ruby/strings/expert/binary_parsing_with_unpack_pack.md
|
2758
|
-
- files/ruby/strings/expert/deep_dup.md
|
2759
|
-
- files/ruby/strings/expert/demo_continue.md
|
2760
|
-
- files/ruby/strings/expert/drb_string_marshalling_hash.md
|
2761
|
-
- files/ruby/strings/expert/fiber_storage_usage.md
|
2762
2748
|
- files/ruby/strings/expert/freeze_dedupe_strings.md
|
2763
|
-
- files/ruby/strings/expert/fstring_eval.md
|
2764
|
-
- files/ruby/strings/expert/functional_fstrings.md
|
2765
|
-
- files/ruby/strings/expert/gb_string_increment.md
|
2766
2749
|
- files/ruby/strings/expert/grapheme_cluster_counting.md
|
2767
2750
|
- files/ruby/strings/expert/handle_invalid_bytes_with_scrub.md
|
2768
|
-
- files/ruby/strings/expert/heredoc_inheritance.md
|
2769
2751
|
- files/ruby/strings/expert/in_memory_io_with_stringio.md
|
2770
|
-
- files/ruby/strings/expert/opengl_strings.md
|
2771
2752
|
- files/ruby/strings/expert/override_dup_with_initialize_copy.md
|
2772
|
-
- files/ruby/strings/expert/regex_named_captures.md
|
2773
|
-
- files/ruby/strings/expert/regex_performance.md
|
2774
2753
|
- files/ruby/strings/expert/reuse_string_buffers_replace.md
|
2775
|
-
- files/ruby/strings/expert/sprintf_named.md
|
2776
|
-
- files/ruby/strings/expert/stateful_sub",{.md
|
2777
|
-
- files/ruby/strings/expert/strict_encodings.md
|
2778
|
-
- files/ruby/strings/expert/string_gc_optimizations.md
|
2779
|
-
- files/ruby/strings/expert/zero_copy_substring.md
|
2780
|
-
- files/ruby/strings/middle/demo.json.md
|
2781
2754
|
- files/ruby/strings/middle/dynamic_gsub_blocks.md
|
2782
2755
|
- files/ruby/strings/middle/encoding_force_encode.md
|
2783
2756
|
- files/ruby/strings/middle/heredoc_squiggly.md
|
2784
|
-
- files/ruby/strings/middle/logging_demos.md.md
|
2785
2757
|
- files/ruby/strings/middle/mutable_string_concatenation.md
|
2786
2758
|
- files/ruby/strings/middle/nested_interpolation.md
|
2787
2759
|
- files/ruby/strings/middle/percent_string_literals.md
|
2788
2760
|
- files/ruby/strings/middle/regex_named_captures.md
|
2789
2761
|
- files/ruby/strings/middle/scrub_invalid_bytes.md
|
2790
|
-
- files/ruby/strings/middle/session_parse.md
|
2791
2762
|
- files/ruby/strings/middle/string_formatting_sprintf.md
|
2792
2763
|
- files/ruby/strings/middle/string_slicing_ranges.md
|
2793
2764
|
- files/ruby/symbols/advanced/symbol_dynamic_memoization.md
|
@@ -2802,7 +2773,6 @@ files:
|
|
2802
2773
|
- files/ruby/symbols/middle/dynamic_method_definition.md
|
2803
2774
|
- files/ruby/symbols/middle/dynamic_method_invocation.md
|
2804
2775
|
- files/ruby/symbols/middle/symbol_to_proc_enumeration.md
|
2805
|
-
- files/ruby/syntax/advanced/define_method_with_closure.md
|
2806
2776
|
- files/ruby/syntax/advanced/endless_method_definition.md
|
2807
2777
|
- files/ruby/syntax/advanced/flip_flop_operator.md
|
2808
2778
|
- files/ruby/syntax/advanced/keyword_splat_destructuring.md
|
@@ -3076,6 +3046,7 @@ files:
|
|
3076
3046
|
- lib/generators/get/smart/templates/get_smart.rb
|
3077
3047
|
- lib/get/smart.rb
|
3078
3048
|
- lib/get/smart/ai/generator.rb
|
3049
|
+
- lib/get/smart/ai/verifier.rb
|
3079
3050
|
- lib/get/smart/app_context.rb
|
3080
3051
|
- lib/get/smart/collection.rb
|
3081
3052
|
- lib/get/smart/learning_path.rb
|
@@ -1,31 +0,0 @@
|
|
1
|
-
## 🚀 Dynamic Tag Contexts with Custom Scopes
|
2
|
-
You can define and manipulate tag contexts at runtime to build more flexible tagging systems. This approach lets you add or remove contexts dynamically based on business logic, without altering your model definitions.
|
3
|
-
|
4
|
-
```ruby
|
5
|
-
# Define a base taggable model without fixed contexts
|
6
|
-
class Article < ApplicationRecord
|
7
|
-
acts_as_taggable_on :_dynamic
|
8
|
-
|
9
|
-
# Dynamically add contexts
|
10
|
-
def self.add_context(context_name)
|
11
|
-
ActsAsTaggableOn.remove_unused_tags
|
12
|
-
acts_as_taggable_on context_name
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
# Usage
|
17
|
-
Article.add_context(:seo_keywords)
|
18
|
-
article = Article.create(title: "Dynamic Tags")
|
19
|
-
article.seo_keywords_list.add("rails", "performance")
|
20
|
-
article.save
|
21
|
-
```
|
22
|
-
|
23
|
-
You can also remove contexts on the fly:
|
24
|
-
|
25
|
-
```ruby
|
26
|
-
def self.remove_context(context_name)
|
27
|
-
tag_types.delete(context_name.to_s)
|
28
|
-
end
|
29
|
-
```
|
30
|
-
|
31
|
-
This pattern is ideal for multi-tenant apps where each tenant may require custom tagging domains.
|
@@ -1,15 +0,0 @@
|
|
1
|
-
## 🔑 Dynamic OmniAuth Provider Setup
|
2
|
-
|
3
|
-
For scenarios where OAuth providers change at runtime, load provider credentials from the database into Devise on each boot. Wrapping in `Devise.setup` ensures strategies register correctly across environments.
|
4
|
-
|
5
|
-
```ruby
|
6
|
-
# config/initializers/devise.rb
|
7
|
-
Devise.setup do |config|
|
8
|
-
Provider.active.each do |provider|
|
9
|
-
config.omniauth provider.name.to_sym,
|
10
|
-
provider.app_id,
|
11
|
-
provider.app_secret
|
12
|
-
end
|
13
|
-
# ... other Devise config
|
14
|
-
end
|
15
|
-
```
|
@@ -1,31 +0,0 @@
|
|
1
|
-
## ⚡️ Exponential Backoff with Jitter for Retries
|
2
|
-
|
3
|
-
By default Sidekiq uses a linear retry interval. For high-throughput systems you can implement an exponential backoff with jitter to reduce retry storms. Create a custom retry middleware that computes `sleep` time using a power function plus a random jitter.
|
4
|
-
|
5
|
-
```ruby
|
6
|
-
# config/initializers/sidekiq_retry_jitter.rb
|
7
|
-
module Sidekiq
|
8
|
-
module Middleware
|
9
|
-
module Server
|
10
|
-
class ExponentialRetry
|
11
|
-
def call(worker, msg, queue)
|
12
|
-
yield
|
13
|
-
rescue => e
|
14
|
-
retry_count = msg['retry_count'] || 0
|
15
|
-
# exponential base (2^n) plus random jitter up to 5s
|
16
|
-
backoff = (2**retry_count) + rand(0..5)
|
17
|
-
Sidekiq.logger.info("Retrying \\#{msg['jid']} in \\\#{backoff}s (count: \\\#{retry_count})")
|
18
|
-
msg['retry'] = true
|
19
|
-
msg['retry_count'] = retry_count + 1
|
20
|
-
Sidekiq::Client.enqueue_to(queue, worker.class, *msg['args'])
|
21
|
-
sleep backoff
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
Sidekiq.configure_server do |config|
|
29
|
-
config.server_middleware.add Sidekiq::Middleware::Server::ExponentialRetry
|
30
|
-
end
|
31
|
-
```
|
@@ -1,15 +0,0 @@
|
|
1
|
-
## 🌳 Recursive Self-referential Tree Associations
|
2
|
-
|
3
|
-
Model hierarchical data using self-referential associations for trees and graphs. By coupling `has_many` and `belongs_to` with a `closure_tree` approach, you can query descendants and ancestors efficiently.
|
4
|
-
|
5
|
-
```ruby
|
6
|
-
class Category < ApplicationRecord
|
7
|
-
has_many :children, class_name: 'Category', foreign_key: 'parent_id'
|
8
|
-
belongs_to :parent, class_name: 'Category', optional: true
|
9
|
-
|
10
|
-
# get all descendants recursively
|
11
|
-
def descendants
|
12
|
-
children + children.flat_map(&:descendants)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
```
|
@@ -1,14 +0,0 @@
|
|
1
|
-
## 🔥 Squash Migrations and Manage Versioning
|
2
|
-
|
3
|
-
Over time, a flurry of small migrations can slow down `rails db:schema:load`. Periodically squash them into one file and adjust the version to keep history clean:
|
4
|
-
|
5
|
-
```bash
|
6
|
-
rails db:environment:set RAILS_ENV=production
|
7
|
-
rails db:schema:dump
|
8
|
-
mv db/schema.rb db/structure.sql # if using structure
|
9
|
-
rails db:drop db:create
|
10
|
-
rails db:schema:load
|
11
|
-
rails db:migrate:status
|
12
|
-
```
|
13
|
-
|
14
|
-
Create a new `0001_squashed_migrations.rb` that reflates the current schema and retire old files. Keep a git tag pointing to the last squashed migration for reference.
|
@@ -1,24 +0,0 @@
|
|
1
|
-
## ⚡ Real-time Validation with StimulusReflex
|
2
|
-
|
3
|
-
Integrate StimulusReflex for server-rendered, real-time form validations without full page reloads. Reflex actions trigger on input changes, validate server-side, and update only error messages.
|
4
|
-
|
5
|
-
```ruby
|
6
|
-
# app/reflexes/form_reflex.rb
|
7
|
-
class FormReflex < ApplicationReflex
|
8
|
-
def validate
|
9
|
-
element = element.dataset[:attribute]
|
10
|
-
value = element.value
|
11
|
-
@record = User.new(element => value)
|
12
|
-
@record.valid?
|
13
|
-
end
|
14
|
-
end
|
15
|
-
```
|
16
|
-
|
17
|
-
```erb
|
18
|
-
<!-- app/views/users/_form.html.erb -->
|
19
|
-
<%= form_with model: @user, data: { reflex: 'change->FormReflex#validate' } do |f| %>
|
20
|
-
<%= f.text_field :username %>
|
21
|
-
<div id="username_errors"><%= @user.errors[:username].join(', ') %></div>
|
22
|
-
<%= f.submit %>
|
23
|
-
<% end %>
|
24
|
-
```
|
@@ -1,8 +0,0 @@
|
|
1
|
-
## 🧠 Using PostgreSQL Advisory Locks in Models
|
2
|
-
|
3
|
-
Use PostgreSQL advisory locks to serialize complex operations across processes. This avoids deadlocks and race conditions without blocking unrelated transactions.
|
4
|
-
|
5
|
-
```ruby
|
6
|
-
class Report < ApplicationRecord
|
7
|
-
def generate_with_lock
|
8
|
-
lock_id =
|
@@ -1,22 +0,0 @@
|
|
1
|
-
## 🔄 Automate Credentials Rotation Workflow
|
2
|
-
|
3
|
-
Regularly rotating your master keys and re-encrypting credentials enhances security. Use a CI/CD job or Rake task to back up your old credentials, generate a new key, and re-encrypt existing secrets programmatically—without manual `rails credentials:edit`.
|
4
|
-
|
5
|
-
```bash
|
6
|
-
# scripts/rotate_credentials.sh
|
7
|
-
#!/usr/bin/env bash
|
8
|
-
cp config/credentials/production.yml.enc backups/production-$(date +%F).yml.enc
|
9
|
-
bundle exec rails credentials:edit --environment production --key-file new_production.key <<'YAML'
|
10
|
-
$(EDITOR=cat cat config/credentials/production.yml.enc)
|
11
|
-
YAML
|
12
|
-
mv new_production.key config/credentials/production.key
|
13
|
-
```
|
14
|
-
|
15
|
-
```yaml
|
16
|
-
# Add this to .gitlab-ci.yml or GitHub Actions
|
17
|
-
rotate-credentials:
|
18
|
-
script:
|
19
|
-
- bash scripts/rotate_credentials.sh
|
20
|
-
only:
|
21
|
-
- schedules
|
22
|
-
```
|
@@ -1,15 +0,0 @@
|
|
1
|
-
## 📈 Precompile Localized View Templates
|
2
|
-
Boost performance by compiling per-locale view templates during asset precompile. Use `I18n.available_locales` to generate variants.
|
3
|
-
|
4
|
-
```ruby
|
5
|
-
# config/initializers/i18n_views.rb
|
6
|
-
Rails.application.config.after_initialize do
|
7
|
-
I18n.available_locales.each do |locale|
|
8
|
-
Dir[Rails.root.join('app/views/**/*.html.erb')].each do |file|
|
9
|
-
compiled = ERB.new(File.read(file)).result(binding)
|
10
|
-
path = file.sub(/\.erb$/, ".#{locale}.html.erb")
|
11
|
-
File.write(path, compiled)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
```
|
@@ -1,77 +0,0 @@
|
|
1
|
-
## 🧩 Parallel Zstd Compression via FFI
|
2
|
-
|
3
|
-
For maximum throughput, leverage Zstandard’s high-speed C library with custom FFI bindings and Ruby thread pools. This lets you compress multiple files in parallel while still streaming each file in chunks for low memory usage.
|
4
|
-
|
5
|
-
```ruby
|
6
|
-
require 'ffi'
|
7
|
-
require 'concurrent'
|
8
|
-
|
9
|
-
module Zstd
|
10
|
-
extend FFI::Library
|
11
|
-
ffi_lib 'libzstd'
|
12
|
-
attach_function :ZSTD_createCStream, [], :pointer
|
13
|
-
attach_function :ZSTD_initCStream, [:pointer, :int], :size_t
|
14
|
-
attach_function :ZSTD_compressStream, [:pointer, :pointer, :pointer], :size_t
|
15
|
-
attach_function :ZSTD_flushStream, [:pointer, :pointer], :size_t
|
16
|
-
attach_function :ZSTD_freeCStream, [:pointer], :size_t
|
17
|
-
|
18
|
-
class InOut < FFI::Struct
|
19
|
-
layout :src, :pointer,
|
20
|
-
:srcSize, :size_t,
|
21
|
-
:dst, :pointer,
|
22
|
-
:dstCapacity, :size_t,
|
23
|
-
:dstSize, :size_t
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
POOL = Concurrent::ThreadPoolExecutor.new(
|
28
|
-
min_threads: 2,
|
29
|
-
max_threads: Concurrent.processor_count,
|
30
|
-
max_queue: 0 # unbounded
|
31
|
-
)
|
32
|
-
|
33
|
-
# Compress a single file in a background thread
|
34
|
-
def compress_zstd(input_path, output_path, level: 3, chunk_size: 16 * 1024)
|
35
|
-
POOL.post do
|
36
|
-
in_file = File.open(input_path, 'rb')
|
37
|
-
out_file = File.open(output_path, 'wb')
|
38
|
-
|
39
|
-
cstream = Zstd.ZSTD_createCStream()
|
40
|
-
raise "Init error" if Zstd.ZSTD_initCStream(cstream, level) != 0
|
41
|
-
|
42
|
-
io_struct = Zstd::InOut.new
|
43
|
-
io_struct[:dstCapacity] = Zstd.lib.ZSTD_CStreamOutSize()
|
44
|
-
io_struct[:dst] = FFI::MemoryPointer.new(:char, io_struct[:dstCapacity])
|
45
|
-
|
46
|
-
while (data = in_file.read(chunk_size))
|
47
|
-
io_struct[:src] = FFI::MemoryPointer.from_string(data)
|
48
|
-
io_struct[:srcSize] = data.bytesize
|
49
|
-
|
50
|
-
while io_struct[:srcSize] > 0
|
51
|
-
ret = Zstd.ZSTD_compressStream(cstream, io_struct, io_struct)
|
52
|
-
out_file.write(io_struct[:dst].read_string(io_struct[:dstSize]))
|
53
|
-
io_struct[:src] = io_struct[:src] + (data.bytesize - io_struct[:srcSize])
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
# Flush remaining data
|
58
|
-
while Zstd.ZSTD_flushStream(cstream, io_struct) > 0
|
59
|
-
out_file.write(io_struct[:dst].read_string(io_struct[:dstSize]))
|
60
|
-
end
|
61
|
-
|
62
|
-
Zstd.ZSTD_freeCStream(cstream)
|
63
|
-
in_file.close
|
64
|
-
out_file.close
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
# Kick off parallel compression for multiple files
|
69
|
-
['video1.mp4', 'video2.mp4', 'large.db'].each do |file|
|
70
|
-
compress_zstd(file, "#{file}.zst", level: 5)
|
71
|
-
end
|
72
|
-
|
73
|
-
POOL.shutdown
|
74
|
-
POOL.wait_for_termination
|
75
|
-
```
|
76
|
-
|
77
|
-
This pattern maximizes CPU utilization across cores and streams each file efficiently without high memory overhead.
|
@@ -1,53 +0,0 @@
|
|
1
|
-
## ⚙️ Hybrid Spinlock: Combining Spin‐then‐Block for Low Latency
|
2
|
-
|
3
|
-
For short‐critical sections, a pure `Mutex` can incur syscalls. Implement a spin‐then‐block strategy: spin for a few CPU cycles before falling back to blocking, reducing latency under low contention.
|
4
|
-
|
5
|
-
```ruby
|
6
|
-
require 'ffi'
|
7
|
-
|
8
|
-
module SpinLock
|
9
|
-
extend FFI::Library
|
10
|
-
ffi_lib FFI::Library::LIBC
|
11
|
-
attach_function :sched_yield, [], :int
|
12
|
-
end
|
13
|
-
|
14
|
-
class HybridLock
|
15
|
-
def initialize(spin_limit = 100)
|
16
|
-
@mutex = Mutex.new
|
17
|
-
@spin_limit = spin_limit
|
18
|
-
@locked = false
|
19
|
-
@lock_mutex = Mutex.new
|
20
|
-
end
|
21
|
-
|
22
|
-
def lock
|
23
|
-
@spin_limit.times do
|
24
|
-
return if try_lock
|
25
|
-
SpinLock.sched_yield
|
26
|
-
end
|
27
|
-
@mutex.lock
|
28
|
-
@locked = true
|
29
|
-
end
|
30
|
-
|
31
|
-
def unlock
|
32
|
-
if @locked
|
33
|
-
@locked = false
|
34
|
-
@mutex.unlock
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def try_lock
|
39
|
-
@lock_mutex.synchronize do
|
40
|
-
return false if @locked
|
41
|
-
@locked = true
|
42
|
-
true
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# Usage
|
48
|
-
lock = HybridLock.new(200)
|
49
|
-
threads = 20.times.map { Thread.new { lock.lock; /* work */; lock.unlock } }
|
50
|
-
threads.each(&:join)
|
51
|
-
```
|
52
|
-
|
53
|
-
Spin briefly to catch fast releases; fallback to standard `Mutex` if contention persists.
|
@@ -1,36 +0,0 @@
|
|
1
|
-
## 🎛️ Custom Leap Second Handling
|
2
|
-
|
3
|
-
Ruby’s core `Time`/`DateTime` ignores leap seconds, leading to subtle off‑by‑one-second errors in physics or telecom domains. Maintain an external leap‑second table (from IERS) and wrap conversions to adjust UTC ↔ TAI properly.
|
4
|
-
|
5
|
-
Example: lightweight leap‑second wrapper:
|
6
|
-
|
7
|
-
```ruby
|
8
|
-
require 'date'
|
9
|
-
LEAP_SECONDS = {
|
10
|
-
DateTime.new(2016,12,31,23,59,60,'+00:00') => 1,
|
11
|
-
# ... load from official table ...
|
12
|
-
}
|
13
|
-
|
14
|
-
class LeapTime
|
15
|
-
def initialize(dt)
|
16
|
-
@dt = dt
|
17
|
-
end
|
18
|
-
|
19
|
-
# Returns TAI (International Atomic Time) offset in seconds
|
20
|
-
def to_tai
|
21
|
-
offset = LEAP_SECONDS.select { |d,_| d <= @dt }.values.sum
|
22
|
-
@dt.to_time.to_i + offset
|
23
|
-
end
|
24
|
-
|
25
|
-
# Convert TAI seconds back to UTC DateTime
|
26
|
-
def self.from_tai(tai_sec)
|
27
|
-
# reverse lookup: subtract cumulative leap seconds
|
28
|
-
dt = Time.at(tai_sec).utc.to_datetime
|
29
|
-
corrections = LEAP_SECONDS.select { |d,_| d <= dt }.values.sum
|
30
|
-
(Time.at(tai_sec - corrections).utc).to_datetime
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
dt = DateTime.now.new_offset(0)
|
35
|
-
puts "TAI seconds: #{LeapTime.new(dt).to_tai}"
|
36
|
-
```
|
@@ -1,25 +0,0 @@
|
|
1
|
-
## 🔧 Manipulate File Descriptors Directly via FFI and `fcntl`
|
2
|
-
When you need to tweak low‑level flags (e.g., set `O_DIRECT` for bypassing page cache), use Ruby’s FFI to call `fcntl` on the file descriptor.
|
3
|
-
|
4
|
-
```ruby
|
5
|
-
require 'ffi'
|
6
|
-
|
7
|
-
module SysCtl
|
8
|
-
extend FFI::Library
|
9
|
-
ffi_lib FFI::Library::LIBC
|
10
|
-
FFI::TypeDefs = { int: :int }
|
11
|
-
attach_function :fcntl, [:int, :int, :int], :int
|
12
|
-
end
|
13
|
-
|
14
|
-
O_DIRECT = 0o40000
|
15
|
-
file = File.open('data.bin', 'r+')
|
16
|
-
fd = file.fileno
|
17
|
-
res = SysCtl.fcntl(fd, SysCtl::Fcntl::F_SETFL, O_DIRECT)
|
18
|
-
raise "fcntl failed" if res == -1
|
19
|
-
|
20
|
-
# Now reads and writes bypass the OS page cache (alignment restrictions apply)
|
21
|
-
file.read(4096)
|
22
|
-
file.close
|
23
|
-
```
|
24
|
-
|
25
|
-
This grants ultimate control over I/O semantics but requires careful attention to alignment and performance implications.
|
@@ -1,17 +0,0 @@
|
|
1
|
-
## 🛡️ Sandboxed IRB with Safe Levels
|
2
|
-
Run untrusted code or plugins within a restricted IRB session by leveraging Ruby's `$SAFE` levels (MRI ≤2.6) or `Sandbox` gems for modern versions.
|
3
|
-
|
4
|
-
```ruby
|
5
|
-
require 'sandbox'
|
6
|
-
sb = Sandbox.new
|
7
|
-
sb.eval('File.write("/tmp/hacked", "oops")') # blocked by sandbox
|
8
|
-
sb.eval('2 + 2') # => 4
|
9
|
-
|
10
|
-
# For MRI ≤2.6, you can also:
|
11
|
-
Thread.new do
|
12
|
-
$SAFE = 3
|
13
|
-
eval("File.read('/etc/passwd')") # raises SecurityError
|
14
|
-
end.join
|
15
|
-
```
|
16
|
-
|
17
|
-
This isolates evaluation contexts, preventing file system or system call escapes. Use it when loading third‑party IRB extensions.
|
@@ -1,52 +0,0 @@
|
|
1
|
-
## 🧪 Accelerate Matrix Operations with BLAS via Fiddle
|
2
|
-
|
3
|
-
Ruby’s `Matrix` is flexible but not optimized for large-scale numeric workloads. By binding to a native BLAS library with `Fiddle`, you can offload heavy multiplications to highly tuned C routines like `cblas_dgemm`. Below is a minimal example showing how to `require 'fiddle'`, link to `libblas`, and call `cblas_dgemm` directly.
|
4
|
-
|
5
|
-
```ruby
|
6
|
-
require 'fiddle'
|
7
|
-
require 'fiddle/import'
|
8
|
-
require 'matrix'
|
9
|
-
|
10
|
-
module BLAS
|
11
|
-
extend Fiddle::Importer
|
12
|
-
dlload 'libblas.so' # or 'libopenblas.so'
|
13
|
-
extern 'void cblas_dgemm(int, int, int, int, int, int, double, double*, int, double*, int, double, double*, int)'
|
14
|
-
|
15
|
-
CBLAS_ROW_MAJOR = 101
|
16
|
-
CBLAS_NO_TRANS = 111
|
17
|
-
end
|
18
|
-
|
19
|
-
class FastMatrix
|
20
|
-
def initialize(matrix)
|
21
|
-
@rows, @cols = matrix.row_count, matrix.column_count
|
22
|
-
@data = Fiddle::Pointer[matrix.to_a.flatten.pack('d*')]
|
23
|
-
end
|
24
|
-
|
25
|
-
def mul(other)
|
26
|
-
raise unless @cols == other.row_count
|
27
|
-
result = Fiddle::Pointer.malloc(@rows * other.column_count * Fiddle::SIZEOF_DOUBLE)
|
28
|
-
|
29
|
-
BLAS.cblas_dgemm(
|
30
|
-
BLAS::CBLAS_ROW_MAJOR,
|
31
|
-
BLAS::CBLAS_NO_TRANS, BLAS::CBLAS_NO_TRANS,
|
32
|
-
@rows, other.column_count, @cols,
|
33
|
-
1.0,
|
34
|
-
@data, @cols,
|
35
|
-
other_data = Fiddle::Pointer[other.to_a.flatten.pack('d*')], other.row_count,
|
36
|
-
0.0,
|
37
|
-
result, other.column_count
|
38
|
-
)
|
39
|
-
|
40
|
-
Matrix.rows(Array.new(@rows) do |i|
|
41
|
-
Array.new(other.column_count) do |j|
|
42
|
-
result.ptr.to_s.unpack('d*')[i * other.column_count + j]
|
43
|
-
end
|
44
|
-
end)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
# Usage:
|
49
|
-
a = FastMatrix.new(Matrix.build(500){ rand })
|
50
|
-
b = FastMatrix.new(Matrix.build(500){ rand })
|
51
|
-
c = a.mul(b) # Native BLAS performance
|
52
|
-
```
|
@@ -1,75 +0,0 @@
|
|
1
|
-
## ⚡ Implement Strassen's Algorithm for Matrix Multiplication
|
2
|
-
|
3
|
-
Strassen’s algorithm reduces the asymptotic complexity of multiplying two _n×n_ matrices from O(n³) to approximately O(n².81). For large matrices, this can yield significant speedups. Here’s a pure‑Ruby subclass of `Matrix` that pads to the next power of two, splits into quadrants, and recursively applies Strassen’s method.
|
4
|
-
|
5
|
-
```ruby
|
6
|
-
require 'matrix'
|
7
|
-
|
8
|
-
class StrassenMatrix < Matrix
|
9
|
-
def *(other)
|
10
|
-
raise ArgumentError unless self.column_count == other.row_count
|
11
|
-
n = [self.row_count, other.column_count].max
|
12
|
-
m = 1 << (Math.log2(n).ceil)
|
13
|
-
|
14
|
-
# Pad to m×m
|
15
|
-
a = pad(self, m)
|
16
|
-
b = pad(other, m)
|
17
|
-
|
18
|
-
result = strassen(a, b)
|
19
|
-
Matrix.rows(result[0...row_count].map { |r| r[0...other.column_count] })
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def pad(mat, size)
|
25
|
-
Array.new(size) do |i|
|
26
|
-
Array.new(size) { |j| (i < mat.row_count && j < mat.column_count) ? mat[i, j] : 0 }
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def strassen(a, b)
|
31
|
-
n = a.size
|
32
|
-
return [[a[0][0] * b[0][0]]] if n == 1
|
33
|
-
|
34
|
-
k = n / 2
|
35
|
-
a11, a12, a21, a22 = split(a, k)
|
36
|
-
b11, b12, b21, b22 = split(b, k)
|
37
|
-
|
38
|
-
m1 = strassen(add(a11, a22), add(b11, b22))
|
39
|
-
m2 = strassen(add(a21, a22), b11)
|
40
|
-
m3 = strassen(a11, subtract(b12, b22))
|
41
|
-
m4 = strassen(a22, subtract(b21, b11))
|
42
|
-
m5 = strassen(add(a11, a12), b22)
|
43
|
-
m6 = strassen(subtract(a21, a11), add(b11, b12))
|
44
|
-
m7 = strassen(subtract(a12, a22), add(b21, b22))
|
45
|
-
|
46
|
-
c11 = add(subtract(add(m1, m4), m5), m7)
|
47
|
-
c12 = add(m3, m5)
|
48
|
-
c21 = add(m2, m4)
|
49
|
-
c22 = add(subtract(add(m1, m3), m2), m6)
|
50
|
-
|
51
|
-
join(c11, c12, c21, c22)
|
52
|
-
end
|
53
|
-
|
54
|
-
def split(m, k)
|
55
|
-
a11 = m[0...k].map { |r| r[0...k] }
|
56
|
-
a12 = m[0...k].map { |r| r[k...m.size] }
|
57
|
-
a21 = m[k...m.size].map { |r| r[0...k] }
|
58
|
-
a22 = m[k...m.size].map { |r| r[k...m.size] }
|
59
|
-
[a11, a12, a21, a22]
|
60
|
-
end
|
61
|
-
|
62
|
-
def add(x,y); x.zip(y).map { |r1,r2| r1.zip(r2).map(&:sum) }; end
|
63
|
-
def subtract(x,y); x.zip(y).map { |r1,r2| r1.zip(r2).map { |a,b| a - b } }; end
|
64
|
-
def join(c11, c12, c21, c22)
|
65
|
-
top = c11.zip(c12).map { |l,r| l + r }
|
66
|
-
bot = c21.zip(c22).map { |l,r| l + r }
|
67
|
-
top + bot
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
# Usage:
|
72
|
-
a = StrassenMatrix.build(128){ rand }
|
73
|
-
b = StrassenMatrix.build(128){ rand }
|
74
|
-
c = a * b # ~O(n^2.81)
|
75
|
-
```
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
rotate
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
... ,
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1 +0,0 @@
|
|
1
|
-
...
|
@@ -1,17 +0,0 @@
|
|
1
|
-
## 🧮 Define Methods Dynamically with Closures
|
2
|
-
`Module#define_method` can accept a block that captures local variables, enabling you to create methods at runtime with context-bound behavior. This is ideal for DSLs or repeatable patterns.
|
3
|
-
|
4
|
-
```ruby
|
5
|
-
class EventHandler
|
6
|
-
[:create, :update, :delete].each do |action|
|
7
|
-
define_method("on_#{action}") do |&block|
|
8
|
-
instance_variable_set("@handler_#{action}", block)
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def trigger(action, *args)
|
13
|
-
handler = instance_variable_get("@handler_")
|
14
|
-
handler&.call(*args)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
```
|