pretty_irb 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 +7 -0
- data/00-MANIFEST.md +356 -0
- data/ADVANCED_FEATURES.md +440 -0
- data/AI_HELP.md +408 -0
- data/AI_QUICK_START.md +247 -0
- data/COMPLETE.md +421 -0
- data/EXAMPLES.md +206 -0
- data/FEATURE_SHOWCASE.md +441 -0
- data/FILE_STRUCTURE.md +231 -0
- data/Gemfile +3 -0
- data/IMPLEMENTATION_COMPLETE.md +309 -0
- data/INDEX.md +708 -0
- data/INSTALL.md +250 -0
- data/LICENSE.txt +21 -0
- data/PUBLISH_TO_RUBYGEMS.md +466 -0
- data/QUICKSTART.md +70 -0
- data/QUICK_REFERENCE.md +253 -0
- data/README.md +251 -0
- data/Rakefile +6 -0
- data/SETUP.md +209 -0
- data/START_HERE.md +462 -0
- data/SUMMARY.md +372 -0
- data/WELCOME.md +300 -0
- data/WHAT_IS_NEW.md +324 -0
- data/exe/irb1 +6 -0
- data/exe/pretty_irb +6 -0
- data/lib/pretty_irb/ai_helper.rb +842 -0
- data/lib/pretty_irb/auto_corrector.rb +76 -0
- data/lib/pretty_irb/benchmarker.rb +94 -0
- data/lib/pretty_irb/cheat_sheet.rb +476 -0
- data/lib/pretty_irb/formatter.rb +66 -0
- data/lib/pretty_irb/history_manager.rb +97 -0
- data/lib/pretty_irb/shell.rb +387 -0
- data/lib/pretty_irb/snippet_manager.rb +119 -0
- data/lib/pretty_irb/variable_inspector.rb +146 -0
- data/lib/pretty_irb/version.rb +3 -0
- data/lib/pretty_irb.rb +26 -0
- metadata +200 -0
|
@@ -0,0 +1,842 @@
|
|
|
1
|
+
module PrettyIRB
|
|
2
|
+
class AIHelper
|
|
3
|
+
class << self
|
|
4
|
+
# Explain a Ruby method
|
|
5
|
+
def explain_method(method_name)
|
|
6
|
+
case method_name.downcase
|
|
7
|
+
when "map"
|
|
8
|
+
explain_map
|
|
9
|
+
when "select", "filter"
|
|
10
|
+
explain_select
|
|
11
|
+
when "each"
|
|
12
|
+
explain_each
|
|
13
|
+
when "reduce", "inject"
|
|
14
|
+
explain_reduce
|
|
15
|
+
when "find", "detect"
|
|
16
|
+
explain_find
|
|
17
|
+
when "merge"
|
|
18
|
+
explain_merge
|
|
19
|
+
when "keys", "values"
|
|
20
|
+
explain_keys_values
|
|
21
|
+
when "gsub", "sub"
|
|
22
|
+
explain_gsub
|
|
23
|
+
when "split", "join"
|
|
24
|
+
explain_split_join
|
|
25
|
+
else
|
|
26
|
+
suggest_available_methods
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Get code example for a concept
|
|
31
|
+
def get_example(concept)
|
|
32
|
+
case concept.downcase
|
|
33
|
+
when "loop", "iteration"
|
|
34
|
+
example_loops
|
|
35
|
+
when "condition", "if"
|
|
36
|
+
example_conditions
|
|
37
|
+
when "class"
|
|
38
|
+
example_class
|
|
39
|
+
when "method"
|
|
40
|
+
example_method
|
|
41
|
+
when "array"
|
|
42
|
+
example_array
|
|
43
|
+
when "hash"
|
|
44
|
+
example_hash
|
|
45
|
+
when "string"
|
|
46
|
+
example_string
|
|
47
|
+
when "error", "exception"
|
|
48
|
+
example_error_handling
|
|
49
|
+
when "block", "proc"
|
|
50
|
+
example_blocks
|
|
51
|
+
else
|
|
52
|
+
suggest_available_examples
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Debug code snippet
|
|
57
|
+
def debug_code(code_snippet)
|
|
58
|
+
analysis = {
|
|
59
|
+
potential_issues: [],
|
|
60
|
+
suggestions: [],
|
|
61
|
+
complexity: analyze_complexity(code_snippet)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# Check for common issues
|
|
65
|
+
analysis[:potential_issues] << "Missing error handling" if code_snippet.include?("begin") == false && has_risky_operations(code_snippet)
|
|
66
|
+
analysis[:potential_issues] << "Potential nil reference" if code_snippet.include?(".") && !code_snippet.include?("&.")
|
|
67
|
+
analysis[:suggestions] << "Consider using safe navigation operator (&.) for chained calls" if code_snippet.include?(".") && !code_snippet.include?("&.")
|
|
68
|
+
analysis[:suggestions] << "Add error handling with begin/rescue/end" if analysis[:potential_issues].include?("Missing error handling")
|
|
69
|
+
|
|
70
|
+
format_analysis(analysis)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Suggest best practices
|
|
74
|
+
def best_practices(topic)
|
|
75
|
+
case topic.downcase
|
|
76
|
+
when "naming"
|
|
77
|
+
naming_conventions
|
|
78
|
+
when "performance"
|
|
79
|
+
performance_tips
|
|
80
|
+
when "readability"
|
|
81
|
+
readability_tips
|
|
82
|
+
when "testing"
|
|
83
|
+
testing_tips
|
|
84
|
+
when "security"
|
|
85
|
+
security_tips
|
|
86
|
+
else
|
|
87
|
+
general_best_practices
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Quick reference
|
|
92
|
+
def quick_reference(keyword)
|
|
93
|
+
case keyword.downcase
|
|
94
|
+
when "operators"
|
|
95
|
+
operators_reference
|
|
96
|
+
when "symbols"
|
|
97
|
+
symbols_reference
|
|
98
|
+
when "variables"
|
|
99
|
+
variables_reference
|
|
100
|
+
when "methods"
|
|
101
|
+
methods_reference
|
|
102
|
+
else
|
|
103
|
+
"Available references: operators, symbols, variables, methods"
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
private
|
|
108
|
+
|
|
109
|
+
def explain_map
|
|
110
|
+
<<~EXPLANATION
|
|
111
|
+
🎯 map method: Transforms each element of an array
|
|
112
|
+
|
|
113
|
+
Syntax: array.map { |item| transformation }
|
|
114
|
+
|
|
115
|
+
Example:
|
|
116
|
+
[1, 2, 3].map { |x| x * 2 }
|
|
117
|
+
=> [2, 4, 6]
|
|
118
|
+
|
|
119
|
+
Key points:
|
|
120
|
+
• Returns a NEW array (doesn't modify original)
|
|
121
|
+
• Applies block to each element
|
|
122
|
+
• Commonly used for data transformation
|
|
123
|
+
EXPLANATION
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def explain_select
|
|
127
|
+
<<~EXPLANATION
|
|
128
|
+
🎯 select method: Filters array based on condition
|
|
129
|
+
|
|
130
|
+
Syntax: array.select { |item| condition }
|
|
131
|
+
|
|
132
|
+
Example:
|
|
133
|
+
[1, 2, 3, 4, 5].select { |x| x > 2 }
|
|
134
|
+
=> [3, 4, 5]
|
|
135
|
+
|
|
136
|
+
Key points:
|
|
137
|
+
• Returns NEW array with matching elements
|
|
138
|
+
• Returns empty array if nothing matches
|
|
139
|
+
• Use for filtering/querying data
|
|
140
|
+
EXPLANATION
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def explain_each
|
|
144
|
+
<<~EXPLANATION
|
|
145
|
+
🎯 each method: Iterates over elements (no transformation)
|
|
146
|
+
|
|
147
|
+
Syntax: array.each { |item| action }
|
|
148
|
+
|
|
149
|
+
Example:
|
|
150
|
+
[1, 2, 3].each { |x| puts x }
|
|
151
|
+
=> [1, 2, 3]
|
|
152
|
+
|
|
153
|
+
Key points:
|
|
154
|
+
• Returns ORIGINAL array (not transformed)
|
|
155
|
+
• Use for side effects (printing, saving, etc.)
|
|
156
|
+
• Better than map when you don't need new array
|
|
157
|
+
EXPLANATION
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def explain_reduce
|
|
161
|
+
<<~EXPLANATION
|
|
162
|
+
🎯 reduce method: Combines array elements into single value
|
|
163
|
+
|
|
164
|
+
Syntax: array.reduce(:+) or array.reduce { |acc, item| acc + item }
|
|
165
|
+
|
|
166
|
+
Example:
|
|
167
|
+
[1, 2, 3, 4].reduce(:+)
|
|
168
|
+
=> 10
|
|
169
|
+
|
|
170
|
+
Key points:
|
|
171
|
+
• Accumulates value across iterations
|
|
172
|
+
• Great for sum, product, or combining values
|
|
173
|
+
• Can use symbol as shorthand (:+, :*, etc.)
|
|
174
|
+
EXPLANATION
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def explain_find
|
|
178
|
+
<<~EXPLANATION
|
|
179
|
+
🎯 find method: Returns first element matching condition
|
|
180
|
+
|
|
181
|
+
Syntax: array.find { |item| condition }
|
|
182
|
+
|
|
183
|
+
Example:
|
|
184
|
+
[1, 2, 3, 4, 5].find { |x| x > 3 }
|
|
185
|
+
=> 4
|
|
186
|
+
|
|
187
|
+
Key points:
|
|
188
|
+
• Returns first match (not array!)
|
|
189
|
+
• Returns nil if no match found
|
|
190
|
+
• Stops searching after finding first match
|
|
191
|
+
EXPLANATION
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def explain_merge
|
|
195
|
+
<<~EXPLANATION
|
|
196
|
+
🎯 merge method: Combines hashes
|
|
197
|
+
|
|
198
|
+
Syntax: hash1.merge(hash2)
|
|
199
|
+
|
|
200
|
+
Example:
|
|
201
|
+
{a: 1, b: 2}.merge({b: 3, c: 4})
|
|
202
|
+
=> {a: 1, b: 3, c: 4}
|
|
203
|
+
|
|
204
|
+
Key points:
|
|
205
|
+
• Returns NEW hash (doesn't modify original)
|
|
206
|
+
• Later values override earlier ones
|
|
207
|
+
• Use merge! to modify original hash
|
|
208
|
+
EXPLANATION
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def explain_keys_values
|
|
212
|
+
<<~EXPLANATION
|
|
213
|
+
🎯 keys & values methods: Extract hash components
|
|
214
|
+
|
|
215
|
+
Syntax: hash.keys or hash.values
|
|
216
|
+
|
|
217
|
+
Example:
|
|
218
|
+
{name: "Ruby", age: 30}.keys
|
|
219
|
+
=> [:name, :age]
|
|
220
|
+
|
|
221
|
+
{name: "Ruby", age: 30}.values
|
|
222
|
+
=> ["Ruby", 30]
|
|
223
|
+
|
|
224
|
+
Key points:
|
|
225
|
+
• keys returns array of all keys
|
|
226
|
+
• values returns array of all values
|
|
227
|
+
• Order may not be guaranteed in older Ruby versions
|
|
228
|
+
EXPLANATION
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def explain_gsub
|
|
232
|
+
<<~EXPLANATION
|
|
233
|
+
🎯 gsub method: Global string substitution (replace all)
|
|
234
|
+
|
|
235
|
+
Syntax: string.gsub(pattern, replacement)
|
|
236
|
+
|
|
237
|
+
Example:
|
|
238
|
+
"hello world".gsub("l", "L")
|
|
239
|
+
=> "heLLo worLd"
|
|
240
|
+
|
|
241
|
+
Key points:
|
|
242
|
+
• Replaces ALL occurrences (use sub for first only)
|
|
243
|
+
• Pattern can be string or regex
|
|
244
|
+
• Returns new string (doesn't modify original)
|
|
245
|
+
EXPLANATION
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def explain_split_join
|
|
249
|
+
<<~EXPLANATION
|
|
250
|
+
🎯 split & join methods: String ↔ Array conversion
|
|
251
|
+
|
|
252
|
+
Syntax: string.split(delimiter) / array.join(delimiter)
|
|
253
|
+
|
|
254
|
+
Example:
|
|
255
|
+
"a,b,c".split(",")
|
|
256
|
+
=> ["a", "b", "c"]
|
|
257
|
+
|
|
258
|
+
["x", "y", "z"].join("-")
|
|
259
|
+
=> "x-y-z"
|
|
260
|
+
|
|
261
|
+
Key points:
|
|
262
|
+
• split: breaks string into array
|
|
263
|
+
• join: combines array into string
|
|
264
|
+
• Perfect inverse operations
|
|
265
|
+
EXPLANATION
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def suggest_available_methods
|
|
269
|
+
<<~AVAILABLE
|
|
270
|
+
Available method explanations:
|
|
271
|
+
🔸 map - Transform array elements
|
|
272
|
+
🔸 select - Filter array elements
|
|
273
|
+
🔸 each - Iterate without transformation
|
|
274
|
+
🔸 reduce - Combine into single value
|
|
275
|
+
🔸 find - Find first matching element
|
|
276
|
+
🔸 merge - Combine hashes
|
|
277
|
+
🔸 keys - Get hash keys
|
|
278
|
+
🔸 values - Get hash values
|
|
279
|
+
🔸 gsub - Replace all in string
|
|
280
|
+
🔸 split - String to array
|
|
281
|
+
🔸 join - Array to string
|
|
282
|
+
|
|
283
|
+
Usage: ?explain_method(name)
|
|
284
|
+
AVAILABLE
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def example_loops
|
|
288
|
+
<<~EXAMPLES
|
|
289
|
+
📚 Loop Examples:
|
|
290
|
+
|
|
291
|
+
Using each:
|
|
292
|
+
[1, 2, 3].each { |x| puts x }
|
|
293
|
+
|
|
294
|
+
Using times:
|
|
295
|
+
5.times { |i| puts "Number #{i}" }
|
|
296
|
+
|
|
297
|
+
Using while:
|
|
298
|
+
i = 0
|
|
299
|
+
while i < 5
|
|
300
|
+
puts i
|
|
301
|
+
i += 1
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
Using for:
|
|
305
|
+
for x in [1, 2, 3]
|
|
306
|
+
puts x
|
|
307
|
+
end
|
|
308
|
+
EXAMPLES
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def example_conditions
|
|
312
|
+
<<~EXAMPLES
|
|
313
|
+
📚 Conditional Examples:
|
|
314
|
+
|
|
315
|
+
If/elsif/else:
|
|
316
|
+
if age < 13
|
|
317
|
+
puts "Child"
|
|
318
|
+
elsif age < 18
|
|
319
|
+
puts "Teen"
|
|
320
|
+
else
|
|
321
|
+
puts "Adult"
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
Ternary operator:
|
|
325
|
+
age >= 18 ? "Adult" : "Minor"
|
|
326
|
+
|
|
327
|
+
Unless:
|
|
328
|
+
puts "Not admin" unless user.admin?
|
|
329
|
+
|
|
330
|
+
Case/when:
|
|
331
|
+
case day
|
|
332
|
+
when 1
|
|
333
|
+
puts "Monday"
|
|
334
|
+
when 2
|
|
335
|
+
puts "Tuesday"
|
|
336
|
+
end
|
|
337
|
+
EXAMPLES
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
def example_class
|
|
341
|
+
<<~EXAMPLES
|
|
342
|
+
📚 Class Definition Example:
|
|
343
|
+
|
|
344
|
+
class Person
|
|
345
|
+
attr_accessor :name, :age
|
|
346
|
+
|
|
347
|
+
def initialize(name, age)
|
|
348
|
+
@name = name
|
|
349
|
+
@age = age
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
def info
|
|
353
|
+
"#{@name} is #{@age} years old"
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
person = Person.new("Alice", 30)
|
|
358
|
+
puts person.info
|
|
359
|
+
EXAMPLES
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
def example_method
|
|
363
|
+
<<~EXAMPLES
|
|
364
|
+
📚 Method Definition Examples:
|
|
365
|
+
|
|
366
|
+
Simple method:
|
|
367
|
+
def greet(name)
|
|
368
|
+
"Hello, #{name}!"
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
With default parameter:
|
|
372
|
+
def greet(name = "Friend")
|
|
373
|
+
"Hello, #{name}!"
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
With multiple parameters:
|
|
377
|
+
def add(a, b)
|
|
378
|
+
a + b
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
With splat operator:
|
|
382
|
+
def sum(*numbers)
|
|
383
|
+
numbers.reduce(:+)
|
|
384
|
+
end
|
|
385
|
+
EXAMPLES
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
def example_array
|
|
389
|
+
<<~EXAMPLES
|
|
390
|
+
📚 Array Examples:
|
|
391
|
+
|
|
392
|
+
Creating arrays:
|
|
393
|
+
arr = [1, 2, 3]
|
|
394
|
+
arr = Array.new(5, 0) # [0, 0, 0, 0, 0]
|
|
395
|
+
|
|
396
|
+
Accessing elements:
|
|
397
|
+
arr[0] # First element
|
|
398
|
+
arr[-1] # Last element
|
|
399
|
+
arr[0..2] # Range
|
|
400
|
+
|
|
401
|
+
Adding elements:
|
|
402
|
+
arr << 4 # Push
|
|
403
|
+
arr.push(5, 6) # Add multiple
|
|
404
|
+
|
|
405
|
+
Removing elements:
|
|
406
|
+
arr.pop # Remove last
|
|
407
|
+
arr.shift # Remove first
|
|
408
|
+
EXAMPLES
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
def example_hash
|
|
412
|
+
<<~EXAMPLES
|
|
413
|
+
📚 Hash Examples:
|
|
414
|
+
|
|
415
|
+
Creating hashes:
|
|
416
|
+
hash = {name: "Ruby", age: 30}
|
|
417
|
+
hash = {"a" => 1, "b" => 2}
|
|
418
|
+
|
|
419
|
+
Accessing values:
|
|
420
|
+
hash[:name] # Using symbol key
|
|
421
|
+
hash["a"] # Using string key
|
|
422
|
+
|
|
423
|
+
Adding/updating:
|
|
424
|
+
hash[:city] = "New York"
|
|
425
|
+
|
|
426
|
+
Iterating:
|
|
427
|
+
hash.each { |k, v| puts "#{k}: #{v}" }
|
|
428
|
+
|
|
429
|
+
Merging:
|
|
430
|
+
hash1.merge(hash2)
|
|
431
|
+
EXAMPLES
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
def example_string
|
|
435
|
+
<<~EXAMPLES
|
|
436
|
+
📚 String Examples:
|
|
437
|
+
|
|
438
|
+
Creating strings:
|
|
439
|
+
str = "Hello"
|
|
440
|
+
str = 'Single quotes'
|
|
441
|
+
str = %q{Alternative syntax}
|
|
442
|
+
|
|
443
|
+
String interpolation:
|
|
444
|
+
name = "Ruby"
|
|
445
|
+
"Hello, #{name}!"
|
|
446
|
+
|
|
447
|
+
String methods:
|
|
448
|
+
"hello".upcase # "HELLO"
|
|
449
|
+
"HELLO".downcase # "hello"
|
|
450
|
+
"ruby".capitalize # "Ruby"
|
|
451
|
+
"hello world".length # 11
|
|
452
|
+
|
|
453
|
+
String splitting/joining:
|
|
454
|
+
"a,b,c".split(",") # ["a", "b", "c"]
|
|
455
|
+
["a", "b"].join(",") # "a,b"
|
|
456
|
+
EXAMPLES
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
def example_error_handling
|
|
460
|
+
<<~EXAMPLES
|
|
461
|
+
📚 Error Handling Examples:
|
|
462
|
+
|
|
463
|
+
Basic rescue:
|
|
464
|
+
begin
|
|
465
|
+
result = 10 / 0
|
|
466
|
+
rescue ZeroDivisionError
|
|
467
|
+
puts "Cannot divide by zero"
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
Multiple rescue clauses:
|
|
471
|
+
begin
|
|
472
|
+
risky_operation
|
|
473
|
+
rescue TypeError
|
|
474
|
+
puts "Type error"
|
|
475
|
+
rescue ArgumentError
|
|
476
|
+
puts "Wrong arguments"
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
Ensure (always runs):
|
|
480
|
+
begin
|
|
481
|
+
file = File.open("data.txt")
|
|
482
|
+
process(file)
|
|
483
|
+
ensure
|
|
484
|
+
file.close
|
|
485
|
+
end
|
|
486
|
+
EXAMPLES
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
def example_blocks
|
|
490
|
+
<<~EXAMPLES
|
|
491
|
+
📚 Block, Proc & Lambda Examples:
|
|
492
|
+
|
|
493
|
+
Block:
|
|
494
|
+
[1, 2, 3].each { |x| puts x }
|
|
495
|
+
|
|
496
|
+
Proc:
|
|
497
|
+
my_proc = Proc.new { |x| x * 2 }
|
|
498
|
+
my_proc.call(5) # => 10
|
|
499
|
+
|
|
500
|
+
Lambda:
|
|
501
|
+
my_lambda = lambda { |x| x * 2 }
|
|
502
|
+
my_lambda.call(5) # => 10
|
|
503
|
+
|
|
504
|
+
Key differences:
|
|
505
|
+
• Procs are more flexible
|
|
506
|
+
• Lambdas check argument count
|
|
507
|
+
• Both can be passed to methods
|
|
508
|
+
EXAMPLES
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
def suggest_available_examples
|
|
512
|
+
<<~AVAILABLE
|
|
513
|
+
Available code examples:
|
|
514
|
+
📖 loop - Iteration patterns
|
|
515
|
+
📖 condition - If/elsif/case statements
|
|
516
|
+
📖 class - Class definition
|
|
517
|
+
📖 method - Method definition
|
|
518
|
+
📖 array - Array operations
|
|
519
|
+
📖 hash - Hash operations
|
|
520
|
+
📖 string - String operations
|
|
521
|
+
📖 error - Error handling
|
|
522
|
+
📖 block - Blocks, procs, lambdas
|
|
523
|
+
|
|
524
|
+
Usage: ?example(topic)
|
|
525
|
+
AVAILABLE
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
def analyze_complexity(code)
|
|
529
|
+
case code.length
|
|
530
|
+
when 0..50
|
|
531
|
+
"Simple"
|
|
532
|
+
when 51..200
|
|
533
|
+
"Moderate"
|
|
534
|
+
when 201..500
|
|
535
|
+
"Complex"
|
|
536
|
+
else
|
|
537
|
+
"Very Complex"
|
|
538
|
+
end
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
def has_risky_operations(code)
|
|
542
|
+
risky_patterns = [
|
|
543
|
+
/\[\d+\]/, # Array indexing without check
|
|
544
|
+
/\.\w+\(/, # Method calls
|
|
545
|
+
/File\./, # File operations
|
|
546
|
+
/require/ # Require statements
|
|
547
|
+
]
|
|
548
|
+
risky_patterns.any? { |pattern| code.match?(pattern) }
|
|
549
|
+
end
|
|
550
|
+
|
|
551
|
+
def format_analysis(analysis)
|
|
552
|
+
output = "📊 Code Analysis:\n\n"
|
|
553
|
+
output += "Complexity: #{analysis[:complexity]}\n\n"
|
|
554
|
+
|
|
555
|
+
if analysis[:potential_issues].any?
|
|
556
|
+
output += "⚠️ Potential Issues:\n"
|
|
557
|
+
analysis[:potential_issues].each { |issue| output += " • #{issue}\n" }
|
|
558
|
+
output += "\n"
|
|
559
|
+
end
|
|
560
|
+
|
|
561
|
+
if analysis[:suggestions].any?
|
|
562
|
+
output += "💡 Suggestions:\n"
|
|
563
|
+
analysis[:suggestions].each { |suggestion| output += " • #{suggestion}\n" }
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
output
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
def naming_conventions
|
|
570
|
+
<<~TIPS
|
|
571
|
+
✨ Naming Conventions Best Practices:
|
|
572
|
+
|
|
573
|
+
Variables:
|
|
574
|
+
• Use snake_case: user_name, total_price
|
|
575
|
+
• Be descriptive: total_price instead of tp
|
|
576
|
+
• Avoid single letters (except i, j for loops)
|
|
577
|
+
|
|
578
|
+
Methods:
|
|
579
|
+
• Use snake_case: calculate_total(), user_exists?()
|
|
580
|
+
• Predicates end with ?: valid?(), empty?()
|
|
581
|
+
• Dangerous methods end with !: delete!(), save!()
|
|
582
|
+
|
|
583
|
+
Constants:
|
|
584
|
+
• Use CONSTANT_NAME (all caps)
|
|
585
|
+
• MAX_USERS, DEFAULT_TIMEOUT
|
|
586
|
+
|
|
587
|
+
Classes:
|
|
588
|
+
• Use PascalCase: User, ShoppingCart, UserProfile
|
|
589
|
+
• Nouns, not verbs
|
|
590
|
+
|
|
591
|
+
Avoid:
|
|
592
|
+
✗ Hungarian notation: strName, intAge
|
|
593
|
+
✗ Non-English: cena, utilisateur
|
|
594
|
+
✗ Misleading names: data, result, temp
|
|
595
|
+
TIPS
|
|
596
|
+
end
|
|
597
|
+
|
|
598
|
+
def performance_tips
|
|
599
|
+
<<~TIPS
|
|
600
|
+
⚡ Performance Tips:
|
|
601
|
+
|
|
602
|
+
Array Operations:
|
|
603
|
+
• Use each instead of map if you don't need results
|
|
604
|
+
• Use find instead of select if you need first match
|
|
605
|
+
• Avoid nested loops when possible
|
|
606
|
+
|
|
607
|
+
String Operations:
|
|
608
|
+
• Use String#freeze for constants
|
|
609
|
+
• Use single quotes for static strings
|
|
610
|
+
• Avoid string concatenation in loops (use array join)
|
|
611
|
+
|
|
612
|
+
Hash Operations:
|
|
613
|
+
• Use symbols for keys, not strings
|
|
614
|
+
• Consider using frozen strings for string keys
|
|
615
|
+
|
|
616
|
+
General:
|
|
617
|
+
• Avoid unnecessary object creation
|
|
618
|
+
• Cache expensive computations
|
|
619
|
+
• Use map/select/reduce instead of manual loops
|
|
620
|
+
• Consider lazy evaluation for large datasets
|
|
621
|
+
TIPS
|
|
622
|
+
end
|
|
623
|
+
|
|
624
|
+
def readability_tips
|
|
625
|
+
<<~TIPS
|
|
626
|
+
📖 Readability Tips:
|
|
627
|
+
|
|
628
|
+
Code Style:
|
|
629
|
+
• Keep methods short (under 15 lines)
|
|
630
|
+
• One responsibility per method
|
|
631
|
+
• Clear variable names
|
|
632
|
+
|
|
633
|
+
Comments:
|
|
634
|
+
• Write code that's self-documenting
|
|
635
|
+
• Comments explain WHY, not WHAT
|
|
636
|
+
• Keep comments in sync with code
|
|
637
|
+
|
|
638
|
+
Structure:
|
|
639
|
+
• Group related methods
|
|
640
|
+
• Alphabetize methods
|
|
641
|
+
• Constants at top of file
|
|
642
|
+
|
|
643
|
+
Control Flow:
|
|
644
|
+
• Use guard clauses at start of methods
|
|
645
|
+
• Prefer early return over nested if
|
|
646
|
+
• Keep nesting level low (max 3)
|
|
647
|
+
TIPS
|
|
648
|
+
end
|
|
649
|
+
|
|
650
|
+
def testing_tips
|
|
651
|
+
<<~TIPS
|
|
652
|
+
🧪 Testing Best Practices:
|
|
653
|
+
|
|
654
|
+
Test Structure:
|
|
655
|
+
• One assertion per test
|
|
656
|
+
• Test happy path and edge cases
|
|
657
|
+
• Use descriptive test names
|
|
658
|
+
|
|
659
|
+
What to Test:
|
|
660
|
+
• Public methods
|
|
661
|
+
• Edge cases: nil, empty, zero
|
|
662
|
+
• Error conditions
|
|
663
|
+
• Boundary conditions
|
|
664
|
+
|
|
665
|
+
What NOT to Test:
|
|
666
|
+
• Standard library code
|
|
667
|
+
• Third-party gems
|
|
668
|
+
• Dependencies (use mocks)
|
|
669
|
+
|
|
670
|
+
Example Structure:
|
|
671
|
+
describe "User" do
|
|
672
|
+
describe "#valid?" do
|
|
673
|
+
it "returns true for valid user" do
|
|
674
|
+
user = User.new(name: "Alice")
|
|
675
|
+
expect(user.valid?).to be true
|
|
676
|
+
end
|
|
677
|
+
end
|
|
678
|
+
end
|
|
679
|
+
TIPS
|
|
680
|
+
end
|
|
681
|
+
|
|
682
|
+
def security_tips
|
|
683
|
+
<<~TIPS
|
|
684
|
+
🔒 Security Tips:
|
|
685
|
+
|
|
686
|
+
Input Validation:
|
|
687
|
+
• Always validate user input
|
|
688
|
+
• Use whitelisting over blacklisting
|
|
689
|
+
• Sanitize strings before use
|
|
690
|
+
|
|
691
|
+
Data Protection:
|
|
692
|
+
• Never commit secrets to repo
|
|
693
|
+
• Use environment variables for config
|
|
694
|
+
• Hash passwords, don't encrypt
|
|
695
|
+
|
|
696
|
+
SQL/Database:
|
|
697
|
+
• Use parameterized queries
|
|
698
|
+
• Avoid string interpolation in queries
|
|
699
|
+
• Use ORM (ActiveRecord) when possible
|
|
700
|
+
|
|
701
|
+
Common Vulnerabilities:
|
|
702
|
+
• SQL Injection: Use parameterized queries
|
|
703
|
+
• XSS: Escape HTML output
|
|
704
|
+
• CSRF: Use CSRF tokens
|
|
705
|
+
TIPS
|
|
706
|
+
end
|
|
707
|
+
|
|
708
|
+
def general_best_practices
|
|
709
|
+
<<~PRACTICES
|
|
710
|
+
✅ General Best Practices:
|
|
711
|
+
|
|
712
|
+
Code Quality:
|
|
713
|
+
• DRY: Don't Repeat Yourself
|
|
714
|
+
• KISS: Keep It Simple, Stupid
|
|
715
|
+
• YAGNI: You Aren't Gonna Need It
|
|
716
|
+
|
|
717
|
+
Design Patterns:
|
|
718
|
+
• Use composition over inheritance
|
|
719
|
+
• Prefer small classes and modules
|
|
720
|
+
• Follow SOLID principles
|
|
721
|
+
|
|
722
|
+
Maintenance:
|
|
723
|
+
• Write tests first (TDD)
|
|
724
|
+
• Keep dependencies minimal
|
|
725
|
+
• Document complex logic
|
|
726
|
+
• Review code with teammates
|
|
727
|
+
PRACTICES
|
|
728
|
+
end
|
|
729
|
+
|
|
730
|
+
def operators_reference
|
|
731
|
+
<<~REFERENCE
|
|
732
|
+
📋 Ruby Operators Reference:
|
|
733
|
+
|
|
734
|
+
Arithmetic:
|
|
735
|
+
+ (addition)
|
|
736
|
+
- (subtraction)
|
|
737
|
+
* (multiplication)
|
|
738
|
+
/ (division)
|
|
739
|
+
% (modulo)
|
|
740
|
+
** (exponentiation)
|
|
741
|
+
|
|
742
|
+
Comparison:
|
|
743
|
+
== (equal)
|
|
744
|
+
!= (not equal)
|
|
745
|
+
< (less than)
|
|
746
|
+
> (greater than)
|
|
747
|
+
<= (less than or equal)
|
|
748
|
+
>= (greater than or equal)
|
|
749
|
+
<=> (spaceship - comparison)
|
|
750
|
+
|
|
751
|
+
Logical:
|
|
752
|
+
&& (and)
|
|
753
|
+
|| (or)
|
|
754
|
+
! (not)
|
|
755
|
+
and, or, not (lower precedence)
|
|
756
|
+
|
|
757
|
+
Bitwise:
|
|
758
|
+
& (and)
|
|
759
|
+
| (or)
|
|
760
|
+
^ (xor)
|
|
761
|
+
~ (not)
|
|
762
|
+
<< (left shift)
|
|
763
|
+
>> (right shift)
|
|
764
|
+
REFERENCE
|
|
765
|
+
end
|
|
766
|
+
|
|
767
|
+
def symbols_reference
|
|
768
|
+
<<~REFERENCE
|
|
769
|
+
📋 Symbols Reference:
|
|
770
|
+
|
|
771
|
+
Creating symbols:
|
|
772
|
+
:symbol
|
|
773
|
+
:"symbol with spaces"
|
|
774
|
+
Symbol.new(:symbol)
|
|
775
|
+
|
|
776
|
+
Characteristics:
|
|
777
|
+
• Immutable
|
|
778
|
+
• Lightweight (interned strings)
|
|
779
|
+
• Same symbol has same object_id
|
|
780
|
+
• Great for hash keys
|
|
781
|
+
|
|
782
|
+
Usage:
|
|
783
|
+
hash = {name: "Ruby", age: 30}
|
|
784
|
+
hash[:name] # => "Ruby"
|
|
785
|
+
|
|
786
|
+
Benefits:
|
|
787
|
+
• Faster than strings as keys
|
|
788
|
+
• More memory efficient
|
|
789
|
+
• Convention for hash keys
|
|
790
|
+
REFERENCE
|
|
791
|
+
end
|
|
792
|
+
|
|
793
|
+
def variables_reference
|
|
794
|
+
<<~REFERENCE
|
|
795
|
+
📋 Variable Types Reference:
|
|
796
|
+
|
|
797
|
+
Local Variables:
|
|
798
|
+
name = "Alice"
|
|
799
|
+
# Scoped to current context
|
|
800
|
+
|
|
801
|
+
Instance Variables:
|
|
802
|
+
@name = "Alice"
|
|
803
|
+
# Scoped to object instance
|
|
804
|
+
|
|
805
|
+
Class Variables:
|
|
806
|
+
@@count = 0
|
|
807
|
+
# Shared by all instances of class
|
|
808
|
+
|
|
809
|
+
Global Variables:
|
|
810
|
+
$global = "danger"
|
|
811
|
+
# Avoid! Use sparingly
|
|
812
|
+
|
|
813
|
+
Constants:
|
|
814
|
+
MAX_SIZE = 100
|
|
815
|
+
# Should not be changed
|
|
816
|
+
REFERENCE
|
|
817
|
+
end
|
|
818
|
+
|
|
819
|
+
def methods_reference
|
|
820
|
+
<<~REFERENCE
|
|
821
|
+
📋 Common Methods Reference:
|
|
822
|
+
|
|
823
|
+
String Methods:
|
|
824
|
+
upcase, downcase, capitalize, length, reverse,
|
|
825
|
+
split, gsub, include?, start_with?, end_with?
|
|
826
|
+
|
|
827
|
+
Array Methods:
|
|
828
|
+
push, pop, shift, unshift, map, select, each,
|
|
829
|
+
find, reduce, sort, reverse, join, length
|
|
830
|
+
|
|
831
|
+
Hash Methods:
|
|
832
|
+
keys, values, each, merge, delete, has_key?,
|
|
833
|
+
fetch, select, map, to_a
|
|
834
|
+
|
|
835
|
+
Numeric Methods:
|
|
836
|
+
abs, round, floor, ceil, even?, odd?, times,
|
|
837
|
+
upto, downto
|
|
838
|
+
REFERENCE
|
|
839
|
+
end
|
|
840
|
+
end
|
|
841
|
+
end
|
|
842
|
+
end
|