Сгенерированная строка не будет сохранена в базе данных ... но приставьте "A" в конце, и это будет - PullRequest
0 голосов
/ 26 августа 2009

В моем приложении эти «планировщики» (по сути, идеи статей) следуют заданным шаблонам, написанным в Markdown, с некоторым определенным синтаксисом здесь:

Please write your answer in the following textbox: [...]

Please write your answer in the following textarea:
...So here, on line, you should write one thing.
...Here, on line 2, you should write another.
...
...
...

По сути, [...] является текстовым вводом, а группа строк, начинающаяся с ..., является текстовой областью. Дело не в этом - просто для объяснения того, что делает этот код.

При действиях new и edit отображается стандартная форма планировщика с правильными полями на основе шаблона (для new) или текущего тела планировщика (для edit). При сохранении поля шаблона заполняются параметрами params [: fields], а полученная уценка сохраняется как тело планировщика. Надеюсь, что теперь можно следовать коду, зная этот контекст. Предоставляется только соответствующий код контроллера, и он использует make_resourceful.

class Staff::PlannersController < StaffController

  make_resourceful do
    actions :all

    before :create do
      find_planner_format
      if @planner_format
        current_object.body = fields_in_template @planner_format.body
      else
        flash[:error] = 'Planner format not found!'
        redirect_to staff_planners_path
      end
      current_object.user = @current_user
    end

    before :update do
      current_object.body = fields_in_template(current_object.body)
    end
  end

private

  def fields_in_template(template)
    fields = params[:fields] || {}
    if fields[:inline]
      template.gsub! /\[\.\.\..*\]/ do
        "[...#{fields[:inline].shift}]"
      end
    end
    if fields[:block]
      template.gsub! /^\.{3}.*(\n\.{3}.*)*$/ do
        fields[:block].shift.split("\n").collect { |line|
          "...#{line}"
        }.join("\n")
      end
    end
    current_object.body = template
  end

end

А теперь загадка: в действии update изменения в теле не сохраняются. После отладки я определил, что проблема заключается не только в current_object.save, поскольку следующий код before :update делает то, что вы ожидаете:

before :update do
  current_object.body = 'test string'
end

На самом деле, даже это дает ожидаемый результат:

before :update do
  current_object.body = fields_in_template(current_object.body) + 'a'
end

Итак, теперь вопрос: почему Rails настолько настойчив, что не сохраняет результат функции - и даже тогда, только когда он исходит от update? Дальнейшая отладка показала, что атрибут объекта установлен и даже утверждает, что успешно сохранил, но reload объект после сохранения отменяет изменения.

Сначала это выглядело так, как будто полученная строка была просто «отравленной» переменной, и перестройка строки путем добавления «а» удалила это странное состояние. Однако следующий код, который должен добавить «а» и удалить его снова, также не удалось сохранить.

before :update do
  new_body = fields_in_template(current_object.body) + 'a'
  new_body.slice! -1
  current_object.body = new_body
end

Это просто странно для меня. Что я здесь делаю не так, и что я могу сделать для дальнейшей отладки? (Или если бы вы случайно увидели мою ошибку, это тоже было бы неплохо ...)

РЕДАКТИРОВАТЬ: После проверки журналов SQL (не уверен, почему я не думал делать это раньше), кажется, что Rails, похоже, не признает новый атрибут body как фактически отличающийся, хотя проверка строки в отладчике подтверждает, что это так. Таким образом, Rails даже не запускает запрос UPDATE, если не изменено что-то еще, в этом случае body не включается.

Ответы [ 2 ]

1 голос
/ 26 августа 2009

Понял! Иногда это просто помогает сформулировать вопрос вслух ...

Дело в том, что я забыл, что при передаче current_object.body в fields_in_template оно передавалось по ссылке. Таким образом, все gsub! методы выполнялись непосредственно на current_object.body, поэтому Rails не обнаружил реальных «изменений» к тому времени, когда я установил body в то, что только что было установлено.

Решение:

def fields_in_template(template)
  template = template.dup
  # ...
end

Спасибо, что позволили мне поговорить с собой, и миссия выполнена!

0 голосов
/ 26 августа 2009

Я не программист на Ruby, но добавляет ли 'a' преобразование типа переменной в строку? Возможно, ваша переменная имеет неправильный тип без добавления 'a'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...