vault backup: 2026-06-03 14:09:18
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
---
|
||||
status: processing
|
||||
type: knowledge
|
||||
tags:
|
||||
- programming
|
||||
- ruby
|
||||
created: 2026-05-17
|
||||
updated: 2026-05-26
|
||||
title: Ruby - массивы
|
||||
source:
|
||||
- "[[Ruby - массивы]]"
|
||||
- "[[Итераторы для обработки массивов Ruby]]"
|
||||
---
|
||||
|
||||
# Ruby — массивы
|
||||
|
||||
Массив в Ruby — экземпляр класса `Array`. Поскольку массивы являются объектами со своими методами, работа со списками данных упрощается.
|
||||
|
||||
Связанные темы: [[Ruby - основы языка]]
|
||||
|
||||
## Создание массива
|
||||
|
||||
```ruby
|
||||
a1 = [1, 2, 3] # литерал
|
||||
a2 = %w{word1 word2} # массив строк без кавычек
|
||||
a3 = ['start', nil, 5, [1, 2]] # разнотипные элементы, вложенный массив
|
||||
|
||||
a4 = Array.new # пустой массив
|
||||
a5 = Array.new(3) # [nil, nil, nil]
|
||||
a6 = Array.new(5, "Test") # ["Test", "Test", ...]
|
||||
a7 = Array.new(5) { |i| i * i } # [0, 1, 4, 9, 16]
|
||||
a8 = Array.[](1, 'a', /^A/) # через метод класса
|
||||
```
|
||||
|
||||
Ruby поддерживает многомерные массивы с элементами разной размерности.
|
||||
|
||||
## Индексация
|
||||
|
||||
```ruby
|
||||
a[0] # первый элемент
|
||||
a[-1] # последний элемент
|
||||
a[-2] # предпоследний
|
||||
```
|
||||
|
||||
### Размер
|
||||
|
||||
```ruby
|
||||
a.size # количество элементов
|
||||
a.length # синоним size
|
||||
```
|
||||
|
||||
## Поиск элементов
|
||||
|
||||
```ruby
|
||||
a.include?(obj) # => true / false
|
||||
a.index(obj) # индекс первого вхождения или nil
|
||||
```
|
||||
|
||||
## Добавление элементов
|
||||
|
||||
```ruby
|
||||
a << 4 # в конец
|
||||
a += [5] # объединение
|
||||
a.push(6) # в конец (синоним: append)
|
||||
a.unshift(0) # в начало (сдвигает остальные вправо)
|
||||
a.insert(2, x) # вставить перед элементом с индексом 2
|
||||
```
|
||||
|
||||
## Удаление элементов
|
||||
|
||||
```ruby
|
||||
a.delete(obj) # удалить все вхождения obj
|
||||
a.delete_at(index) # удалить по индексу
|
||||
a.delete_if { |x| block } # удалить все, подходящие под условие
|
||||
a.shift # удалить и вернуть первый элемент
|
||||
a.pop # удалить и вернуть последний элемент
|
||||
```
|
||||
|
||||
## Срезы
|
||||
|
||||
```ruby
|
||||
a[1..3] # диапазон индексов
|
||||
a[1, 3] # начиная с индекса 1, длиной 3
|
||||
a.values_at(0, 2, 4) # элементы по перечисленным индексам или диапазонам
|
||||
a.first(n) # первые n элементов
|
||||
a.last(n) # последние n элементов
|
||||
```
|
||||
|
||||
## Полезные методы
|
||||
|
||||
```ruby
|
||||
a.flatten # развернуть многомерный массив в одномерный
|
||||
a.flatten! # то же, но изменяет сам массив
|
||||
|
||||
a.sample # случайный элемент
|
||||
a.sample(n) # n случайных элементов
|
||||
|
||||
a.select { |x| block } # массив элементов, для которых block == true
|
||||
```
|
||||
|
||||
## Итераторы
|
||||
|
||||
`each` перебирает элементы массива:
|
||||
|
||||
```ruby
|
||||
ary.each { |item| block }
|
||||
```
|
||||
|
||||
Пример:
|
||||
|
||||
```ruby
|
||||
arr.each do |x|
|
||||
if x > 0 && x % 5 == 0
|
||||
arr_out << x
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
`each_index` перебирает индексы:
|
||||
|
||||
```ruby
|
||||
ary.each_index { |index| block }
|
||||
```
|
||||
|
||||
Похожий проход по индексам:
|
||||
|
||||
```ruby
|
||||
(0...arr.size).each do |i|
|
||||
if arr[i] > 0 && arr[i] % 5 == 0
|
||||
arr_out << arr[i]
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
### Поиск минимума, максимума и индексов
|
||||
|
||||
Императивный вариант:
|
||||
|
||||
```ruby
|
||||
a = gets.chomp.split.map { |i| i.to_i }
|
||||
p a
|
||||
|
||||
max = min = a[0]
|
||||
maxi = mini = 0
|
||||
|
||||
for i in 1...a.size
|
||||
if a[i] > max
|
||||
max = a[i]
|
||||
maxi = i
|
||||
end
|
||||
|
||||
if a[i] < min
|
||||
min = a[i]
|
||||
mini = i
|
||||
end
|
||||
end
|
||||
|
||||
puts "Максимальное число: #{max}, индекс: #{maxi}"
|
||||
puts "Минимальное число: #{min}, индекс: #{mini}"
|
||||
```
|
||||
|
||||
Через методы массива:
|
||||
|
||||
```ruby
|
||||
a = gets.chomp.split.map { |i| i.to_i }
|
||||
p a
|
||||
|
||||
max = a.max
|
||||
min = a.min
|
||||
maxi = a.index(max)
|
||||
mini = a.index(min)
|
||||
```
|
||||
@@ -0,0 +1,293 @@
|
||||
---
|
||||
status: processing
|
||||
type: knowledge
|
||||
tags:
|
||||
- programming
|
||||
- ruby
|
||||
created: 2026-05-17
|
||||
updated: 2026-05-26
|
||||
title: Ruby - основы языка
|
||||
source:
|
||||
- "[[Ruby - основы языка]]"
|
||||
- "[[Знания Ruby]]"
|
||||
---
|
||||
|
||||
# Ruby — основы языка
|
||||
|
||||
Ruby — объектно-ориентированный язык, но допускает процедурный стиль написания кода. Всё является объектом, включая числа и булевы значения.
|
||||
|
||||
Связанные темы: [[Ruby On Rails]]
|
||||
|
||||
## Синтаксис
|
||||
|
||||
- Знак препинания в конце строки не нужен
|
||||
- Отступы не несут синтаксического смысла (в отличие от Python)
|
||||
- Несколько команд в одной строке разделяются через `;`
|
||||
|
||||
```ruby
|
||||
puts "Hello World!"
|
||||
puts 42; puts "next line"
|
||||
```
|
||||
|
||||
## Комментарии
|
||||
|
||||
```ruby
|
||||
# однострочный комментарий
|
||||
|
||||
=begin
|
||||
многострочный
|
||||
комментарий
|
||||
=end
|
||||
```
|
||||
|
||||
## Типы данных
|
||||
|
||||
```ruby
|
||||
"Hello".class # => String
|
||||
true.class # => TrueClass
|
||||
5.class # => Integer
|
||||
6.4.class # => Float
|
||||
nil.class # => NilClass
|
||||
```
|
||||
|
||||
### Именование
|
||||
|
||||
- Переменные — с маленькой буквы: `my_var`
|
||||
- Классы — с большой буквы: `MyClass`
|
||||
- Ключевые слова языка использовать нельзя
|
||||
|
||||
### Преобразование типов
|
||||
|
||||
**Явное:**
|
||||
|
||||
| Метод | Что делает |
|
||||
|--------|-----------------------------------------|
|
||||
| `to_i` | к целому числу (дробная часть отсекается) |
|
||||
| `to_f` | к вещественному числу |
|
||||
| `to_s` | к строке |
|
||||
|
||||
**Неявное:** при математических операциях `Integer + Float` → `Float`.
|
||||
|
||||
## Значения по умолчанию
|
||||
|
||||
Для присваивания значения по умолчанию часто используют `||=`:
|
||||
|
||||
```ruby
|
||||
a ||= 'что-то'
|
||||
# то же самое, что:
|
||||
a = a || 'что-то'
|
||||
```
|
||||
|
||||
Это работает из-за того, что в Ruby только `nil` и `false` считаются falsey. Все остальные значения, включая `0`, пустую строку и пустой массив, в условиях считаются truthy.
|
||||
|
||||
Ограничение: `||=` не подходит, если `false` — допустимое сохранённое значение.
|
||||
|
||||
## Предикаты
|
||||
|
||||
В Ruby проверки часто оформляют методами-предикатами с `?` на конце:
|
||||
|
||||
```ruby
|
||||
0.zero? # => true
|
||||
1.zero? # => false
|
||||
2.positive? # => true
|
||||
|
||||
8.even? # => true
|
||||
8.odd? # => false
|
||||
|
||||
''.empty? # => true
|
||||
'wow'.empty? # => false
|
||||
|
||||
something.nil?
|
||||
items.any?
|
||||
items.empty?
|
||||
```
|
||||
|
||||
## Управляющие конструкции
|
||||
|
||||
```ruby
|
||||
# if без ветвления
|
||||
if a > 0
|
||||
action
|
||||
end
|
||||
|
||||
# if-elsif-else
|
||||
if a > 0
|
||||
...
|
||||
elsif a == 0
|
||||
...
|
||||
else
|
||||
...
|
||||
end
|
||||
|
||||
# unless — выполнится, если условие ложно
|
||||
unless a > 0
|
||||
action
|
||||
end
|
||||
|
||||
# case
|
||||
case a
|
||||
when 1 then puts "один"
|
||||
when 2 then puts "два"
|
||||
else puts "другое"
|
||||
end
|
||||
```
|
||||
|
||||
### Альтернативные условия
|
||||
|
||||
Тернарный оператор — короткая форма `if/else`, когда нужно выбрать одно из двух значений:
|
||||
|
||||
```ruby
|
||||
condition ? value_if_true : value_if_false
|
||||
```
|
||||
|
||||
Пример:
|
||||
|
||||
```ruby
|
||||
age = 20
|
||||
status = age >= 18 ? 'adult' : 'minor'
|
||||
# => "adult"
|
||||
```
|
||||
|
||||
Обычный `if/else` для того же случая:
|
||||
|
||||
```ruby
|
||||
status =
|
||||
if age >= 18
|
||||
'adult'
|
||||
else
|
||||
'minor'
|
||||
end
|
||||
```
|
||||
|
||||
Тернарный оператор удобен, когда обе ветки короткие и возвращают простые значения:
|
||||
|
||||
```ruby
|
||||
message = user.nil? ? 'Гость' : user.name
|
||||
price = discount ? base_price * 0.9 : base_price
|
||||
```
|
||||
|
||||
Если логика занимает несколько строк, лучше использовать обычный `if/else`. Вложенные тернарные операторы тоже лучше не писать: они быстро становятся нечитаемыми.
|
||||
|
||||
Плохой вариант:
|
||||
|
||||
```ruby
|
||||
result = a > 0 ? 'positive' : a < 0 ? 'negative' : 'zero'
|
||||
```
|
||||
|
||||
Постфиксный `if` используют для коротких выражений:
|
||||
|
||||
```ruby
|
||||
do_something if num.zero?
|
||||
```
|
||||
|
||||
`unless` выполняет блок, если условие ложно:
|
||||
|
||||
```ruby
|
||||
unless something.zero?
|
||||
do_something
|
||||
end
|
||||
```
|
||||
|
||||
Сложные условия внутри `unless` лучше не писать: `unless a && b` читается хуже явного `if`.
|
||||
|
||||
## Логические операторы
|
||||
|
||||
```ruby
|
||||
true && false # => false
|
||||
false || true # => true
|
||||
!true # => false
|
||||
```
|
||||
|
||||
Сравнение с логическими значениями строгое:
|
||||
|
||||
```ruby
|
||||
true == 1 # => false
|
||||
false == nil # => false
|
||||
```
|
||||
|
||||
Логические операторы возвращают не обязательно `true` или `false`, а последнее вычисленное значение:
|
||||
|
||||
```ruby
|
||||
0 && 'one' # => "one"
|
||||
nil && false # => nil
|
||||
```
|
||||
|
||||
## Оператор `<=>`
|
||||
|
||||
`<=>` называют spaceship-оператором. Он возвращает `-1`, `0` или `1` и часто используется при сортировке:
|
||||
|
||||
```ruby
|
||||
1 <=> 1 # => 0
|
||||
2 <=> 1 # => 1
|
||||
1 <=> 2 # => -1
|
||||
```
|
||||
|
||||
## Строки
|
||||
|
||||
Конкатенация:
|
||||
|
||||
```ruby
|
||||
name = 'H' + 'e' + 'x' + 'l' + 'e' + 't'
|
||||
name = 'H' 'e' 'x' 'l' 'e' 't'
|
||||
```
|
||||
|
||||
Интерполяция работает только в двойных кавычках:
|
||||
|
||||
```ruby
|
||||
greeting = "hello #{name}"
|
||||
line_feed = "one line\nanother one"
|
||||
```
|
||||
|
||||
Полезные методы:
|
||||
|
||||
```ruby
|
||||
name = 'ruby'
|
||||
name.upcase # => "RUBY"
|
||||
name.include?('ru')
|
||||
name.capitalize # => "Ruby"
|
||||
name.length # => 4
|
||||
```
|
||||
|
||||
Срезы:
|
||||
|
||||
```ruby
|
||||
name = 'ruby'
|
||||
name[1] # => "u"
|
||||
name[-1] # => "y"
|
||||
name[0, 2] # => "ru"
|
||||
name[0..-2] # => "rub"
|
||||
name[-4..] # => "ruby"
|
||||
name[/ru/] # => "ru"
|
||||
```
|
||||
|
||||
Пример маскирования номера карты:
|
||||
|
||||
```ruby
|
||||
def prepare_card_for_display(num)
|
||||
"**#{num[-4..]}"
|
||||
end
|
||||
```
|
||||
|
||||
## Циклы
|
||||
|
||||
| Оператор | Назначение |
|
||||
|----------|-----------|
|
||||
| `loop` | бесконечный цикл; выход через `break` |
|
||||
| `while` | цикл с условием выполнения |
|
||||
| `until` | цикл, пока условие ложно |
|
||||
| `for` | итератор по перечислимому объекту |
|
||||
| `next` | пропустить текущий шаг |
|
||||
| `redo` | повторить текущий шаг заново |
|
||||
|
||||
**Диапазоны в `for`:**
|
||||
|
||||
```ruby
|
||||
for i in 1..5 # от 1 до 5 включительно
|
||||
for i in 1...5 # от 1 до 4 (5 не входит)
|
||||
```
|
||||
|
||||
**Деление с остатком:**
|
||||
|
||||
```ruby
|
||||
x, r = x.divmod(n)
|
||||
```
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
---
|
||||
status: seed
|
||||
type: guide
|
||||
tags:
|
||||
- programming
|
||||
- ruby-on-rails
|
||||
- api
|
||||
created: 2026-05-25
|
||||
updated: 2026-05-25
|
||||
title: API импорт в Rails через runner
|
||||
source: "[[Работа с API для проекта Attendance Mephi]]"
|
||||
---
|
||||
|
||||
# API импорт в Rails через runner
|
||||
|
||||
Памятка по ручному запуску импортов в [[Ruby On Rails]]-проекте Attendance Mephi для [[НИР]].
|
||||
|
||||
## Контекст
|
||||
|
||||
Импорт запускается через `bin/rails runner`:
|
||||
|
||||
```sh
|
||||
/home/ada/.local/bin/mise exec ruby -- bin/rails runner '...'
|
||||
```
|
||||
|
||||
Актуальный семестр берется из `Term.actual`. Для старта `2026-02-07` код семестра: `20252`.
|
||||
|
||||
## Credentials
|
||||
|
||||
```yaml
|
||||
api:
|
||||
home_mephi:
|
||||
host:
|
||||
code:
|
||||
token:
|
||||
students_mephi:
|
||||
host:
|
||||
username:
|
||||
password:
|
||||
```
|
||||
|
||||
См. также: [[Rails credentials edit не открывает редактор]].
|
||||
|
||||
## Endpoints
|
||||
|
||||
```text
|
||||
GET {home_mephi.host}/study_groups.json?term_code=20252&code=...&token=...
|
||||
GET {home_mephi.host}/tutors.json?term_code=20252&code=...&token=...
|
||||
GET {students_mephi.host}/get_list_by_group_name?group=...&term=20252
|
||||
GET {home_mephi.host}/tutors/{staff_id}/schedules.json?term_code=20252&date=YYYY-MM-DD&code=...&token=...
|
||||
```
|
||||
|
||||
`students_mephi` использует Basic Auth: `username/password`.
|
||||
|
||||
## Ручная загрузка
|
||||
|
||||
```sh
|
||||
/home/ada/.local/bin/mise exec ruby -- bin/rails runner 'ImportGroupsService.execute'
|
||||
/home/ada/.local/bin/mise exec ruby -- bin/rails runner 'ImportTutorsService.execute'
|
||||
/home/ada/.local/bin/mise exec ruby -- bin/rails runner 'ImportStudentsService.execute'
|
||||
/home/ada/.local/bin/mise exec ruby -- bin/rails runner 'term = Term.actual; ImportDisciplineService.execute(nil, term)'
|
||||
```
|
||||
|
||||
Расписание на сегодня:
|
||||
|
||||
```sh
|
||||
/home/ada/.local/bin/mise exec ruby -- bin/rails runner 'term = Term.actual; ImportScheduleService.execute(Date.today, term)'
|
||||
```
|
||||
|
||||
Расписание за весь семестр до сегодня:
|
||||
|
||||
```sh
|
||||
/home/ada/.local/bin/mise exec ruby -- bin/rails runner 'term = Term.actual; finish = [term.get_finish_date, Date.today].min; (term.start_date..finish).each { |date| ImportScheduleService.execute(date, term) unless date.wday == 0 }'
|
||||
```
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
---
|
||||
status: seed
|
||||
type: guide
|
||||
tags:
|
||||
- programming
|
||||
- ruby-on-rails
|
||||
- deploy
|
||||
created: 2026-05-29
|
||||
updated: 2026-05-29
|
||||
title: Capistrano deploy через systemd
|
||||
source: "[[Команды для деплоя с помощью Capistrano]]"
|
||||
---
|
||||
|
||||
# Capistrano deploy через systemd
|
||||
|
||||
Заметка про выдачу минимальных `sudo`-прав для деплоя Rails-приложения через Capistrano, когда сервисы управляются через `systemd`.
|
||||
|
||||
## Sudoers
|
||||
|
||||
В `/etc/sudoers` задаётся alias для команд, которые Capistrano может выполнять без пароля:
|
||||
|
||||
```sudoers
|
||||
Cmnd_Alias PUMA_CONTROL = /usr/bin/mv /tmp/navigation_backend_puma_production.service /etc/systemd/system/, /usr/bin/mv /tmp/navigation_backend_puma_production.socket /etc/systemd/system/, /bin/systemctl daemon-reload, /bin/systemctl enable navigation_backend_puma_production, /bin/systemctl start navigation_backend_puma_production, /bin/systemctl stop navigation_backend_puma_production, /bin/systemctl restart navigation_backend_puma_production, /bin/systemctl enable navigation_backend_puma_production.socket, /bin/systemctl restart navigation_backend_sidekiq_production.service, /bin/systemctl restart navigation_backend_solid_queue_production.service, /bin/systemctl restart solid_queue
|
||||
deploy ALL = NOPASSWD: PUMA_CONTROL
|
||||
```
|
||||
|
||||
Где:
|
||||
- `deploy` — пользователь, от имени которого выполняется деплой;
|
||||
- `navigation_backend` — имя приложения в service/socket unit-файлах.
|
||||
|
||||
## Команды деплоя
|
||||
|
||||
```bash
|
||||
cap production puma:install
|
||||
cap production deploy
|
||||
```
|
||||
|
||||
`puma:install` кладёт `systemd` unit-файлы, после чего `deploy` перезапускает Puma и фоновые сервисы без интерактивного ввода пароля.
|
||||
|
||||
## Связанные заметки
|
||||
- [[Ruby On Rails]]
|
||||
- [[Sidekiq - основа работы]]
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
---
|
||||
status: seed
|
||||
type: guide
|
||||
tags:
|
||||
- programming
|
||||
- ruby-on-rails
|
||||
- debug
|
||||
created: 2026-05-20
|
||||
updated: 2026-05-20
|
||||
title: Rails credentials edit не открывает редактор
|
||||
source: "[[99 System/Archive/Rails credentials edit не открывает редактор|Rails credentials edit не открывает редактор]]"
|
||||
---
|
||||
|
||||
# Rails credentials edit не открывает редактор
|
||||
|
||||
Заметка фиксирует кейс, когда `bin/rails credentials:edit` в [[Ruby On Rails]] завершается без открытия редактора и без явной ошибки.
|
||||
|
||||
## Симптом
|
||||
|
||||
Команда:
|
||||
|
||||
```bash
|
||||
bin/rails credentials:edit
|
||||
```
|
||||
|
||||
сразу печатает:
|
||||
|
||||
```text
|
||||
File encrypted and saved.
|
||||
```
|
||||
|
||||
При этом редактор не открывается, а credentials фактически не меняются.
|
||||
|
||||
## Причина
|
||||
|
||||
Rails 7.x выбирает редактор через helper `rails/command/helpers/editor.rb` и берёт `$VISUAL` приоритетнее `$EDITOR`.
|
||||
|
||||
Если переменная окружения `$VISUAL` установлена, например в `zed` или `code`, значение `$EDITOR` игнорируется. Если указанный в `$VISUAL` редактор не найден или не может быть запущен, системный вызов завершается с ошибкой, но Rails может молча продолжить выполнение и сохранить файл без изменений.
|
||||
|
||||
Связанный контекст: [[Environment Variables]] и [[Command Path]].
|
||||
|
||||
## Решение
|
||||
|
||||
На один запуск явно сбросить `$VISUAL` и задать рабочий редактор:
|
||||
|
||||
```bash
|
||||
VISUAL="" EDITOR="nano" bin/rails credentials:edit
|
||||
```
|
||||
|
||||
Можно заменить `nano` на любой редактор, который доступен в текущем окружении.
|
||||
|
||||
## Диагностика
|
||||
|
||||
Проверить, не установлен ли `$VISUAL`:
|
||||
|
||||
```bash
|
||||
echo "VISUAL='$VISUAL'"
|
||||
```
|
||||
|
||||
Проверить, находится ли редактор в `PATH`:
|
||||
|
||||
```bash
|
||||
which nano
|
||||
```
|
||||
|
||||
Если используется GUI-редактор вроде `code` или `zed`, отдельно проверить, что его CLI-команда доступна из той же shell-сессии, где запускается Rails.
|
||||
|
||||
## Практический вывод
|
||||
|
||||
Для `credentials:edit` важен не только `$EDITOR`, но и `$VISUAL`. Если Rails ведёт себя так, будто файл был сохранён без редактирования, сначала проверить переменные окружения редактора и доступность команды редактора через `PATH`.
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
---
|
||||
status: processing
|
||||
type: moc
|
||||
tags:
|
||||
- programming
|
||||
- ruby-on-rails
|
||||
created: 2025-12-17
|
||||
updated: 2026-05-29
|
||||
title: Ruby On Rails
|
||||
---
|
||||
|
||||
# Ruby On Rails
|
||||
|
||||
%% Begin Waypoint %%
|
||||
- [[Active Storage]]
|
||||
- [[API импорт в Rails через runner]]
|
||||
- [[Capistrano deploy через systemd]]
|
||||
- [[Rails credentials edit не открывает редактор]]
|
||||
- [[Sidekiq - основа работы]]
|
||||
|
||||
%% End Waypoint %%
|
||||
Reference in New Issue
Block a user