Реализация обзора перед сохранением - контроллер или модель? - PullRequest
1 голос
/ 28 января 2011

Есть ли способ сделать "сохранение" в существующей записи вместо использования update_attributes?

Половина значений, которые я сохраняю, рассчитывается из пользовательских данных и поэтому не присутствует в хэше params,Кроме того, может быть несколько циклов просмотра пользователем, что означает, что: id выпадает из хэша params (я сохраняю его в хэше сессий).

Мне кажется, что концептуально проще "сохранить" вфинальная версия @post.В итоге я сохранил окончательную версию @post в хеше атрибутов, затем вернулся в базу данных, чтобы получить исходную запись, а затем выполнил update_attributes.Надеюсь, что 2-й поиск записи кэшируется?На самом деле, теперь легко сгенерировать список изменений в данном редактировании, поэтому, возможно, я останусь с этим, если это сработает, но это кажется неловким.

Что такое «путь Rails»?Я здесь новенький и хочу вписаться.

<form is submitted>
@post = Post.new(params[:post])
<lots of calculations and validity checking>
finalattrhash = @post.attributes
@post = nil
@post = post.find(session[:postid])

respond_to do |format|
  if @post.update_attributes(finalattrhash)
    session[:postid] = nil
    format.html { redirect_to(@post, :notice => 'post was successfully updated.') }
  else ... end
end

Ответы [ 2 ]

1 голос
/ 28 января 2011

Что такое "путь рельсов"? я новый здесь и хочу вписаться в

Нет, все должно быть наоборот. Спросите: «Как Rails может упростить мою жизнь, помочь мне написать хороший, поддерживаемый код и повысить ценность бизнеса моего клиента»

Распространенной ошибкой является попытка заставить ваши бизнес-требования соответствовать коду, показанному в примерах, или всегда спрашивать о «лучших практиках». Или другими словами: спросите, что ваша платформа может сделать для вас, а не то, что вы можете сделать для своей платформы!

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

В частности, имейте в виду, что вам не нужно ограничивать себя встроенными методами save и update_attributes. Вы вызвали два действия: Просмотр и Завершение. Поэтому добавьте их в свою модель:

class Post << AR::Base
  def review
    # do the validations, calculations, etc for the review step
  end
  def finalize
    # do whatever you need for the finalize step
    save # save the model instance
  end
end

Вам также не нужно принимать стандартные имена действий RESTful. Нужно действие под названием «обзор»? Назовите это так:

resources :posts do
  member do
    post 'review' # maps to PostsController#review
  end
end

BDD / TDD - хороший способ избавиться от этих методов и помочь вам удовлетворить ваши конкретные требования. Это также помогает обеспечить хорошее разделение задач, поскольку вы в конечном итоге тестируете методы изолированно, что помогает в написании поддерживаемого кода.

1 голос
/ 28 января 2011

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

Чтобы прояснить ситуацию, давайте приведем пример.

Предположим, у вас есть модель Post.У вас есть title и content, хранящиеся в базе данных.И предположим, что вы не хотите, чтобы использование непосредственно вводило эти поля, но другие четыре поля: trip_name, trip_date ,ited и with_who.(Конечно, это не очень «реальный случай»: D)

class Post < ActiveRecord::Base
  # DB fields: title:string, content:text
  attr_accessor :trip_name, :trip_date, :visited, :with_who
  attr_protected :title, :content # This line could be ignored, but to only protected these two fields from mass assignment.

  before_save :complex_handles

  validates :title, :presence => true, :uniqueness => true
  validates :content, :presence => true

  private

  def complex_handles
    @title = @trip_name + " " + @trip_date
    @content = @visited + " " + @with_who
  end

end

Таким образом, ваша форма выдаст вам следующий хеш:

params[:post] = {
  :trip_name => "some trip",
  :trip_date => "2010-01-29",
  :visited => "Hong Kong",
  :with_who => "with my GF"
}

Это должна быть обычная простая форма иКонтроллер также будет простейшей формой:

respond_to do |format|
  if @post.update_attributes(params[:post])
    format.html { redirect_to(@post, :notice => 'post was successfully updated.') }
  else
    ...
  end
end

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

===== ОБНОВЛЕНО =====

Если мое понимание верно, я думаю, у вас есть форма сдве кнопки (одна review и одна finalize).И для проверки вы просто обновляете поля, не сохраняя в базе данных.

Так что было бы проще присвоить двум кнопкам отправки другой атрибут name.И в вашем контроллере:

respond_to do |format|
  if (params[:action] == "finalize" && @post.update_attributes(params[:post]))
    || (params[:action] == "review" && @post.attributes = params[:post] && @post.valid?)
    format.html { redirect_to(@post, :notice => 'post was successfully updated.') }
  else
    ...
  end
end

Эта часть кажется немного хитрой.Поскольку params [: action] может принимать одно значение за один раз, так что вы не испортите проверку.

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

Однако вам нужно немного обновить код модели Post:

# Before, I have used:
before_save :complex_handles

# Now, I change to:
before_validation :complex_handles

, чтобы обработкабудет сделано, прежде чем вы позвоните @post.valid? в части обзора.(Это не должно влиять на завершающую часть)

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