Перейти к содержимому


Ads
Фотография
- - - - -

try/catch против if

ruby

  • Авторизуйтесь для ответа в теме
Сообщений в теме: 3

#1 Sergey Kalinin

Sergey Kalinin

    Ампиратор

  • Забанен
  • 3 429 сообщений

Отправлено 23.11.2015, 22:00

ребятушки, помогите пожалуйста в одном вопросе разобраться. сейчас буду дичь нести, но вы не смейтесь. итак вот проблема в общем виде, без привязки к конкретному языку/фреймворку
 
есть mvc-фреймворк. на его основе сделан блог с системой тегов. пользователь имеет возможность редактировать посты и при этом менять привязанные к посту теги, удалять посты и создавать новые посты. на уровне модели теги и посты связаны связью многие ко многим(has and belongs to many). на уровне БД табличка post связана с табличкой tags через табличку post_tags, которая состоит из двух колонк: tags(integer), posts(integer)
 
вот экшн update, который срабатывает после того как пользователь ввёл нужные изменения и отправил форму. 
 
вариант1:
def update
  if @post.update(post_params)
    add_new_tags(@post) if params[:tagnames]  # если из формы пришли новые теги, то добавляем их в табличку tags и создаём ассоциации в табличке post_tags
    destroy_tags(params['delete_tags'], @post) if params['delete_tags']     # если из формы пришёл список тегов для удаления, то удаляем соответствующие ассоциации   
    redirect_to user_post_path(current_user.id, @post.id), notice: 'posts was successfully updated.' # редирект куда-то там, в случае успешного обновления поста
  else
    render :edit # тоже типа редиректа, только в другое место
  end
end

def add_new_tags(post)
  tagnames = params[:tagnames].split(/[, \.?!]+/) # разбиваем строку по запятым и получаем набор тегов
  tagnames.each do |tagname| # цикл по тегам
    tag = Tag.find_by(title: tagname.downcase) # ищем в табличке tags существующий тег
    if tag
      # если находим уже существующий тег, то.....
      sql = "select * from 'posts_tags' where post_id = #{post.id} and tag_id = #{tag.id}"
      records_array = ActiveRecord::Base.connection.execute(sql)   # ...... проверяем есть ли ассоциация в табличке post_tags  
      tag.posts << post if records_array.count == 0   # ...............если её нет, то создаём
    else
      # если не находим существующий теги, то............
      tag = Tag.create(title: tagname.downcase)   # .............создаём его
      tag.posts << post     # .........и добавляем ассоциацию
    end
  end
end  

def destroy_tags(tags,post)
  tags.each do |tag|   # цикл по тегам
    sql = "delete from 'posts_tags' where post_id = #{post.id} and tag_id = #{tag}"
    records_array = ActiveRecord::Base.connection.execute(sql)    # удаляем ассоциацию
  end
end 

 
вариант2:
def update
  try  
    @post.update(post_params)
    add_new_tags(@post) if params[:tagnames]
    destroy_tags(params['delete_tags'], @post) if params['delete_tags']   
    redirect_to user_post_path(current_user.id, @post.id), notice: 'posts was successfully updated.'
  catch  
    logger.debug 'update post is failed'   # запись в лог
    render :edit
  end
end

def add_new_tags(post)
  tagnames = params[:tagnames].split(/[, \.?!]+/) 
  tagnames.each do |tagname|
    tag = Tag.find_by(title: tagname.downcase)
    if tag
      sql = "select * from 'posts_tags' where post_id = #{post.id} and tag_id = #{tag.id}"

      try
        records_array = ActiveRecord::Base.connection.execute(sql)     
        tag.posts << post if records_array.count == 0
      catch
        logger.debug 'query for add association posts_tags is failed'
        raise 'add_new_tags error'
      end
    else
      try
        tag = Tag.create(title: tagname.downcase)
        tag.posts << post
      catch
        logger.debug 'query for create tag and add association posts_tags is failed'
        raise 'add_new_tags error'
      end
    end
  end
end  

def destroy_tags(tags,post)
  tags.each do |tag|
    sql = "delete from 'posts_tags' where post_id = #{post.id} and tag_id = #{tag}"

    unless ActiveRecord::Base.connection.execute(sql)  
      logger.debug 'query for delete tags is failed'
      raise 'destroy_tags error'          
    end
  end
end   

 
вопрос. во втором варианте оправдана ли дополнительная сложность в виде добавленных проверок типа try/catch. от этих проверок стал ли код более защищённым от ошибок. так вообще правильно программировать?

Сообщение отредактировал Sergey Kalinin: 23.11.2015, 22:02

"Людей я люблю, но их надо п****ть"©Александр Баширов

#2 ARMICRON

ARMICRON

    Небожитель

  • Небожитель
  • PipPipPipPipPip
  • 6 618 сообщений

Отправлено 24.11.2015, 08:59

Нет смысла ловить exception и кидать его опять.



#3 Sergey Kalinin

Sergey Kalinin

    Ампиратор

  • Забанен
  • 3 429 сообщений

Отправлено 24.11.2015, 09:18

Нет смысла ловить exception и кидать его опять.

ну почему же нет? вот представь такую ситуацию:

  • пользователь решил обновить пост,
  • @post.update(post_paramsпрошло успешно(то есть контент поста обновлён),
  • а с привязкой тега к посту произошла проблема,
  • значит в общем операция была неуспешной и её нужно отменить или хотя бы просто знать, что произошёл сбой

почему бы ради такой благородной цели не поизвращаться с exception?

 

...или я не про то?


Сообщение отредактировал Sergey Kalinin: 24.11.2015, 09:55

"Людей я люблю, но их надо п****ть"©Александр Баширов

#4 Слепой

Слепой

    Житель

  • Житель
  • 223 сообщений

Отправлено 24.11.2015, 10:12

В данном случае нет никакого смысла в твоих извращениях с исключениями.
 
Тебе нужно делать так: все действия с БД (т.е. сохранение поста вместе с тегами) заворачиваются в транзакцию и try/catch. Если поймали исключение, то: логируем его, транзакцию откатываем, юзера возвращаем на страницу редактирования с сообщением "Не удалось сохранить пост". Всё. Никаких там вложенных и повторных пробросов не нужно.






Темы с аналогичным тегами ruby

Количество пользователей, читающих эту тему: 1

0 пользователей, 1 гостей, 0 скрытых пользователей