Ваша сложная обработка и проверки должны быть выполнены внутри модели.Толстый контроллер почти всегда хуже толстой модели.
Чтобы прояснить ситуацию, давайте приведем пример.
Предположим, у вас есть модель 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?
в части обзора.(Это не должно влиять на завершающую часть)