2009-04-07 2 views
7

При написании метода «create» для объекта в приложении Ruby on Rails я использовал два метода. Я хотел бы использовать один метод для более чистого и согласованного кода. Ниже перечислены два метода. Кто-нибудь знает, лучше ли кто-то другой? Если да, то почему?При создании объекта в Ruby on Rails, какой метод экономии вы предпочитаете и почему?

Метод 1:

def create1 
    # is this unsecure? should we grab user_id from the session 
    params[:venue]['user_id'] = params[:user_id] 

    begin 
    venue = Venue.create(params[:venue]) 
    @user_venues = @user.venues 
    render :partial => 'venue_select_box', :success => true, :status => :ok 
    rescue ActiveRecord::RecordInvalid 
    render :text => 'Put errors in here', :success => false, :status => :unprocessable_entity 
    end 
end 

Метод 2:

def create2 
    # is this unsecure? should we grab user_id from the session 
    params[:venue]['user_id'] = params[:user_id] 

    venue = Venue.new(params[:venue]) 
    if venue.save 
    @user_venues = @user.venues 
    render :partial => 'venue_select_box', :success => true, :status => :ok 
    else 
    render :text => 'Put errors in here', :success => false, :status => :unprocessable_entity 
    end 
end 
+0

Я думаю, вы имеете в виду «создать!» не «создавать» в методе 1. «Создать» не приведет к возникновению исключения; он просто возвращает false при ошибках проверки. –

+0

Вы правы, спасибо за указание, что вне – Tony

ответ

4
class VenuesController < ApplicationController 
    def create 
    @venue = @user.venues.create!(params[:venue]) 
    render :partial => 'venue_select_box', :success => true, :status => :ok 
    end 

    rescue_from ActiveRecord::RecordInvalid do 
    render :text => 'Put errors in here', :success => false, :status => :unprocessable_entity 
    end 
end 

Использование @user.venues таким образом гарантировать, что идентификатор пользователя всегда будет установлено соответствующим образом. Кроме того, ActiveRecord защитит поле :user_id от назначения в течение вызова #create!. Следовательно, атаки извне не смогут изменить :user_id.

В ваших тестах вы можете убедиться, что выполнение POST для: create вызывает исключение ActiveRecord :: RecordInvalid.

+0

точка хаоса, что «исключения не должны использоваться для обычных условий» является хорошим. Однако Rails решила иначе: «rescue_from ActiveRecord :: RecordInvalid» - обычная практика. –

3

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

2

Это зависит. Если вы ожидаете, что все операторы создания будут работать, используйте первое, потому что невозможность создания и сохранения является исключительной и может быть условием, из которого программа не может легко восстановить. Кроме того, если вы используете реляционную целостность (foreign_key_migrations от RedHill Consulting), это приведет к исключению нарушений внешнего ключа, поэтому вы, вероятно, захотите их поймать при создании или обновлении.

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

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

+0

Поскольку это действие для создания, вы говорите, что версия 1 хороша, если у меня есть проверка на стороне клиента, но версия 2 лучше, если я использую проверку на стороне сервера? – Tony

+0

Не совсем ... за небольшим исключением, вы всегда * хотите проверить на стороне сервера в качестве меры предосторожности (проверка на стороне клиента всегда может быть отключена злоумышленником) ... (разделение на два комментария) –

+0

Мое правило, я использую save(), когда ожидаю, что операция, скорее всего, завершится без использования ограничения DB, и create(), когда я ожидаю, что это может ... это поможет? Я также всегда реализую глобальный обработчик исключений, чтобы улавливать ошибочные ошибки. –

1

Я полностью согласен с комментарием Дона. Но я бы даже сделал еще один шаг с частью user_id и установил его как фильтр перед моделью.

Смежные вопросы