Ruby — хранение части кода в базе данных

    Сегодня нашел еще один способ как можно использовать «фишку» интерпретируемых языков — создавать и выполнять программный код в процессе работы программы.

    Можно положить часть кода в базу данных.

    Для чего это нужно?

    Мне встретилась такая задача — писать онлайн тесты.
    У каждого теста есть функция — по которой ответам пользователя ставится в соответствие — номер описания результата

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

    и теперь в месте, где нужно рассчитать результат теста пишем:
    eval(@test.function)

    function — это и есть ячейка в таблице БД, описывающей тесты.
    при этом код просто вставляется в это место программы и выполняется, ему даже не надо передавать в качестве параметров результаты ответов пользователя, он их и так уже видит

    Правда если внутри строки, передаваемой eval объявить локальную переменную, то внешняя программа ее не будет видеть (по крайней мере у меня не увидела, хотя в консоли все было ок), поэтому лучше пользоваться переменными экземпляра (instance variables) вида — @varname

    Подозреваю справедливую критику со стороны любителей строгого ООП. Но приводить этот пример в согласие с ООП я не буду, если есть желание — поэкспериментируйте.
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 23

      –2
      Кстати если интересно, то вот простенький пример такого куска кода, который я кладу в БД

      @hash =
      {
      1 => {1=>0, 2=>1},
      2 => {1=>1, 2=>3},
      3 => {1=>1, 2=>1},
      4 => {1=>0, 2=>3},
      5 => {1=>0, 2=>2},
      6 => {1=>0, 2=>2},
      7 => {1=>0, 2=>1},
      8 => {1=>1, 2=>3},
      9 => {1=>1, 2=>3},
      10 => {1=>1, 2=>3}
      }

      s=0
      @answers.each do |a|
      s += @hash[a.question_number][a.variant_number]
      end

      if (0..7).include?(s)
      @t_result_number = 1
      elsif (6..12).include?(s)
      @t_result_number = 2
      else
      @t_result_number = 3
      end
        +2
        Не вижу в вашем коде ничего такого, для чего стоило бы городить такой огород.
        Спокойно можно пользоваться обыкновенными реляционными БД.
        Например структура БД:
        1. Список тестов:
        — ИД
        — Название теста
        2. Вопрос:
        — ИД
        — Список_тестов_ИД
        — Вопрос
        — Дополнительные какие-то примечания
        3. Варианты ответов
        — ИД
        — Вопрос_ИД
        — Правильный (True/False)

        И вы избежите сразу кучи проблем. Например — тесты можно будет использовать не только с вашим скриптом но и с другими программами и под другими платформами. И можно будет вести статистику — в базе легко хранить кто, когда и как ответил. (что актуально, если тест в базу забили с ошибками)
          0
          Естественно все так и хранится в БД (ну почти так, чуть посложнее)

          Поясняю — тесты по психологии
          Нет там никаких «Правильный (True/False)»

          Ответы собираются в отдельной таблице (которая привязана к таблице сессий прохождения теста) и по результатам всех ответов на вопросы анализируется результат

          И функция преобразования ответов в результаты может быть для каждого теста различна!!!
          Вот что я хотел донести, но похоже не донес
          если конечно Вы прочитали пост, а не только заголовок и пару фраз из центра

          Или вы подумали что я извращенец и решил просто код в БД хранить :)
            0
            А тот код, который я привел — это и есть один из МНОГИХ возможных способов как преобразовывать
            ответы @answers в номер описания результата теста @t_result_number
              0
              И выбор был — либо заранее предугадать все возможные алгоритмы как ответы пользователя преобразовать в описание результата и жестко ограничить возможные алгоритмы — либо вынести это в БД

              например могут быть вопросы, которые похожи друг на друга и являются проверочными и задаются с целью определить достаточно ли искренен пользователь

              в общем всего сразу предусмотреть невозможно, поэтому я и выбрал такой вариант с хранением этого алгоритма в БД
                0
                Думается, что неявную логику можно и в БД хранить.
                Например можно добавить таблицу с вариантами или даже группами вариантов ответов.

                Например — если возможно несколько ответов на один вопрос или один из нескольких — то можно в таблицу «2. Вопрос» добавить поле — «количестов вариантов ответов» где
                0 — все ответы должны быть отмечены
                1..3 — должно быть отмечено от 1 до трех ответов.

                А если психология, то можно вместо или вместе с правильный ставить стоимость ответа в баллах и уже суммировать их потом.

                PS И подумайте еще о человеке кроме вас, которому надо будет писать эти же тесты на руби.
                  0
                  > А если психология, то можно вместо или вместе с правильный ставить стоимость ответа в баллах и > уже суммировать их потом.

                  Есть подозрение что этого варианта хватит для 90% возможных тестов, но на всякий случай я не стал ограничиваться таким алгоритмом

                  > PS И подумайте еще о человеке кроме вас, которому надо будет писать эти же тесты на руби.

                  Центральный момент — согласен. Пока вижу выход в том, чтобы готовые шаблоны для алгоритмов давать модератору с подробной инструкцией где и что надо заменить

                  а сами шаблоны разрабатывать самому
            0
            экспериментировал на php с хранением ВСЕГО кода в базе данных. То есть все функции, классы и прочее — это строки в бд. Вот уже 3 года как развиваю эту идею и могу сказать что в ней есть очень интересные плюсы (равно как и очевидные минусы). Если хабрасообществу будет интересно, могу подготовить серию топиков на эту тему. Думаю может получиться вполне увлекательно и ново
              0
              Я тоже занимался чем то подобным, могу сказать что есть задачи когда так удобнее :)
                0
                Интересно, особенно минусы :) В смысле, хотелось бы обоснованных выводов по сравнению: «монолитный код + скриптовый automation» _vs_ «скриптипг при помощи динамического кода»
                  0
                  MgDuke в посте ниже написал много минусов
                  интересно было бы и плюсы посмотреть хранения всего кода в БД, мне такая идея в голову приходила, но пока что-то плюсов особенных я не нашел
                    0
                    уже готовлю статью. Сегодня думаю появится на хабре
                  0
                  C#(в частности платформа .Net) хоть и не скриптовый язык, но тоже поддерживает компиляцию «на лету». Однако в проекте я решил не использовать такую «фишку», сделал упор на логику, сейчас меня всё устраивает.
                    +8
                    Идея хранить код в СУБД плоха хотя бы тем, что СУБД изначально расчитана на хранение данных. Это так сказать отделение зерён от плевел.

                    Из очевидных минусов:

                    — IDE работают с файлами
                    — исходники это файлы, в итоге с ними можно делать любые файловые операции
                    — поддержка, наверняка человек пришедший после вас на такой проект сочтёт вас идиотом
                    — производительность, в большинстве случаев скрипты \ рантаймы могут применять какие-либо оптимизации, включая кеш, а ваши BLOB'ы уж никак сюда не впишуться
                    — Распостранение, ох некрасиво таскать SQL дампы туда — сюда
                    — Безопасность, прямой код инжекшн в случае проблем
                    — Бекап, представляете, бывает так, что их не делают, и тогда любые ваши «кастомизации» on site коту под хвост если сломаеться база

                    Зачем это вообще необходимо? Данные != Код
                      +3
                      А помимо этого:

                      — Отладка отвратительна
                      — Нормальная поддержка ОПП, — не возможна
                      — Очень вероятны скрытые дефекты при работе с shared statеом
                      — Eval ВСЕГДА дефакто будет медленее обычного выполнения
                      — Версии \ бранчи \ мерджи \ итерации не возможны
                      — Runtime migration, при переходе на новый рантайм ошибки совместимости не будут выловлены вовремя

                      Если хорошо подумать, можно найти ещё минимум 10 причин, по которым этого не стоит делать.
                        +2
                        Как вы в таком случае относитесь к механизмам buisiness rules? Ну вот у меня, например (.net), они в виде DSL на основе Boo, и хранятся в БД тоже в текстовом виде.

                        Да и много где юзается скриптинг — тот же lua, например, под это заточен. Или вы против основного кода в БД?
                          0
                          На хабре недавно статья была про бизнес-логику, там отлично была аргументирована позиция «в БД храним данные, а не логику». Причем даже безотносительно всех тех проблем, что написал MgDuke.
                            0
                            Вы не на тот вопрос отвечаете, извините. И мне бы все-таки хотелось бы выслушать MgDuke
                              +1
                              К своему сожалению, я не знаком с DSL Boo, в СУБД вполне нормально хранить к примеру конфигурацию, даже в ХМL формате. Но категорически противопоказано хранить непосредственно исполняемый ход или его производные.
                              То есть к примеру, если Вам как-то удастся разместить workflow оперирующий бизнес объектами в СУБД, — это нормально, так как это всего лишь метаданные. А мета-информация, — это не код.

                              Я против хранения любого кода в СУБД, кроме возможностей предоставляемых самими СУБД.
                              SQL CLR — сколько угодно. БД — база данных, а не база кода =) Каким боком сдесь Lua я не понял.
                      0
                      Так!!!
                      Всем кто меня заминусовал.
                      Я так и не увидел ни одного нормального объяснения что не понравилось в моем подходе к решению проблемы!!!

                      Увидел много наездов на идею хранить ВЕСЬ код в БД.
                      Но мой топик был про другое, если его хоть кто-то удосужился прочитать из тех, кто ставил минусы могли бы заметить, что топик про конкретное решение конкретной задачи
                        +1
                        Написать можно много чего, и при этом будет работать. Вопрос в чисто архитектурном решении.
                        Я понимаю, когда разрушают архитектуру в пользу оптимизации и усиления безопасности или даже ради прикручивания новой фичи, но от этого надо стремиться уйти, а не наоборот. Что такое уникальное вы получили, положив код в базу данных?
                          0
                          Для меня это выглядит как простое и наглядное решение

                          Может не правильное с точки зрения архитектуры, но понятное с точки зрения здравого смысла (хотя он у каждого свой)

                          В общем это всего лишь эксперимент :) не судите строго
                        0
                        можно почитать про шаблоны проектирования и сделать нормально.

                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                        Самое читаемое