Skip to content

Conversation

@kkrasilov
Copy link
Contributor

Фамилия Имя

Красилов Консантин

Email

kkrasilov@gmail.com

Номер домашнего задания

3

Ссылка на видео с демо работы

https://youtu.be/q92DMbnwDac

Комментарии

Грустно вышло с тестами :(
Они работали просто с гемом active_record, а c sinatra-activerecord не захотели взлетать.
И не успел часть тестов сделать, где нужно было реализовать связи между таблицами.

Copy link

@hound hound bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some files could not be reviewed due to errors:

Error: We found some problems with your configuration file: [/Attribute] key ...
Error: We found some problems with your configuration file: [/Attribute] key 'Attribute:' is undefined., [/DuplicateMethodCall] key 'DuplicateMethodCall:' is undefined., [/FeatureEnvy] key 'FeatureEnvy:' is undefined., [/IrresponsibleModule] key 'IrresponsibleModule:' is undefined., [/PrimaDonnaMethod] key 'PrimaDonnaMethod:' is undefined., [/TooManyStatements] key 'TooManyStatements:' is undefined., [/app/workers] key 'app/workers:' is undefined., [/db/migrate] key 'db/migrate:' is undefined.

@@ -0,0 +1,6 @@
# frozen_string_literal: true

class UserWord < ActiveRecord::Base
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rails/ApplicationRecord: Models should subclass ApplicationRecord.

@@ -0,0 +1,10 @@
# frozen_string_literal: true

class Word < ActiveRecord::Base
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rails/ApplicationRecord: Models should subclass ApplicationRecord.

Copy link

@hound hound bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some files could not be reviewed due to errors:

Error: We found some problems with your configuration file: [/Attribute] key ...
Error: We found some problems with your configuration file: [/Attribute] key 'Attribute:' is undefined., [/DuplicateMethodCall] key 'DuplicateMethodCall:' is undefined., [/FeatureEnvy] key 'FeatureEnvy:' is undefined., [/IrresponsibleModule] key 'IrresponsibleModule:' is undefined., [/PrimaDonnaMethod] key 'PrimaDonnaMethod:' is undefined., [/TooManyStatements] key 'TooManyStatements:' is undefined., [/app/workers] key 'app/workers:' is undefined., [/db/migrate] key 'db/migrate:' is undefined.

Copy link

@hound hound bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some files could not be reviewed due to errors:

Error: We found some problems with your configuration file: [/Attribute] key ...
Error: We found some problems with your configuration file: [/Attribute] key 'Attribute:' is undefined., [/DuplicateMethodCall] key 'DuplicateMethodCall:' is undefined., [/FeatureEnvy] key 'FeatureEnvy:' is undefined., [/IrresponsibleModule] key 'IrresponsibleModule:' is undefined., [/PrimaDonnaMethod] key 'PrimaDonnaMethod:' is undefined., [/TooManyStatements] key 'TooManyStatements:' is undefined., [/app/workers] key 'app/workers:' is undefined., [/db/migrate] key 'db/migrate:' is undefined.

require 'sinatra/activerecord/rake'
require './app'

namespace :db do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не очень понятно, если честно, что ты хотел тут сказать. Выглядит как ненужный код.

Copy link
Contributor Author

@kkrasilov kkrasilov May 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Я его добавил чтобы была возможность работать с таксками гема sinatra/activerecord/rake - rake db:migrate, rake db:seed.
https://github.com/sinatra-activerecord/sinatra-activerecord#setup

request.body.rewind
data = JSON.parse(request.body.read)

chat_id = data['message']['chat']['id']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Чисто в теории у тебя тут очень легко может случиться ошибка, которую ты не обработаешь. Например chat ключа не будет в сообщении, оно вернет nil попробует взять ['id'] и получится беда.

Чтобы от такого застраховаться - пойди узнать про метод dig у хеша. И не забывай про обработку ошибок.

Copy link
Contributor Author

@kkrasilov kkrasilov May 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Как лучше обрабатывать ошибки?

Просто добавить

chat_id = data.dig('message', 'chat', 'id')
raise StandardError, 'Sorry, chat id cannot be blank' if chat_id.nil?

или обернуть все в begin -

begin
  chat_id = data.dig('message', 'chat', 'id')
  raise StandardError if chat_id.nil?
rescue
  puts 'Error - Sorry, chat id cannot be blank'
end

чтобы программа продолжала работать.

И с ошибками ActiveRecord, сделать -

def set_user
  user = User.find_or_create_by!(telegram_id: chat_id)
rescue ActiveRecord::NotNullViolation => e
  puts "Error - #{e}"
end

или просто добавить метод find_or_create_by! без rescue?

require_relative 'app/models/user'
require_relative 'app/services/telegram/conversation'

Dotenv.load
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Лайк за использование ENV переменных 👍

chat_id = data['message']['chat']['id']
message = data['message']['text']

user = User.find_or_create_by(telegram_id: chat_id)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

find_or_create_by если не создаст пользователя, вернет тебе false и будет беда. Лучше всего если не обрабатываешь ошибки в ActiveRecord использовать методы с восклицательным знаком find_or_create_by!


case message
when '/start'
user.send_max_word!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Понятно что ты тут пытался сделать какую-то машину состояний. Так как ты тоже можно, но лучше посмотреть в сторону https://github.com/aasm/aasm

end

def call
send(@user.conversation_status)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

У тебя сейчас в приложении появилась очень странная неприятность. Получается что работа твоего класса Telegram::Coversation зависит от названия статусов в модели. Так делать нельзя, хоть и может казаться что это красиво. Завтра кто-нибудь решит переименовать все статусы и будет большая беда.

Copy link
Contributor Author

@kkrasilov kkrasilov May 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Можно разбить на отдельные сервисы - Telegram::Start, Telegram::SendMaxWord, Telegram::SendSmiley?

def send_max_word
return RESPONSE[:max_word_error] unless (1..6).cover?(@message.to_i)

@user.update(max_words: @message, conversation_status: 'conversation_break')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@user.update!

@api.sendMessage(@user.telegram_id, @word.to_s)
end

def waiting_answer
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А вот это очень опасная архитектура этой фишки. Проблема заключается в том что ты с помощью крона запускаешь каждые N минут процесс. И если пользователь тебе не ответил - тупо его держишь. Это будет работать пока у тебя парочку пользователей, но когда у тебя их станет хотя бы пару десятков - твой сервис упадет.

def call
find_and_added_word_to_user
send_word
waiting_answer
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут надо было перключать пользователя в статус "ждет ответа" и просто выходить.

Copy link

@hound hound bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some files could not be reviewed due to errors:

Error: We found some problems with your configuration file: [/Attribute] key ...
Error: We found some problems with your configuration file: [/Attribute] key 'Attribute:' is undefined., [/DuplicateMethodCall] key 'DuplicateMethodCall:' is undefined., [/FeatureEnvy] key 'FeatureEnvy:' is undefined., [/IrresponsibleModule] key 'IrresponsibleModule:' is undefined., [/PrimaDonnaMethod] key 'PrimaDonnaMethod:' is undefined., [/TooManyStatements] key 'TooManyStatements:' is undefined., [/app/workers] key 'app/workers:' is undefined., [/db/migrate] key 'db/migrate:' is undefined.

gem 'sinatra'
gem 'sinatra-activerecord'
gem 'telegramAPI'
gem 'pry'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bundler/OrderedGems: Gems should be sorted in an alphabetical order within their section of the Gemfile. Gem pry should appear before telegramAPI.


Dotenv.load

WELCOME = 'Привет! Я бот, который помогает учить новые английские слова каждый день. Давай сперва определимся,' \
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/RedundantFreeze: Do not freeze immutable objects, as freezing them has no effect.

end

event :learn do
transitions from: [:waiting_max_word, :waiting_smiley, :sleeping], to: :learning
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style/SymbolArray: Use %i or %I for an array of symbols.

@@ -0,0 +1,30 @@
# frozen_string_literal: true
require 'aasm'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Layout/EmptyLineAfterMagicComment: Add an empty line after magic comments.

end

desc 'Reminder for answer to user'
task :reminder_for_answer do
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rails/RakeEnvironment: Include :environment task as a dependency for all Rake tasks.

end

desc 'Start a lesson with a user'
task :start_lesson do
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rails/RakeEnvironment: Include :environment task as a dependency for all Rake tasks.

namespace :telegram do
desc 'Start new training day'
task :start_new_training_day do
User.update_all(aasm_state: 'learning')
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rails/SkipsModelValidations: Avoid using update_all because it skips validations.


namespace :telegram do
desc 'Start new training day'
task :start_new_training_day do
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rails/RakeEnvironment: Include :environment task as a dependency for all Rake tasks.

private

def update_user!
@user.user_words.where(created_at: Date.today.all_day).count >= @user.max_words ? @user.sleep! : @user.lesson!
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rails/Date: Do not use Date.today without zone. Use Time.zone.today instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants