Ошибка при создании связанных объектов в Rails - PullRequest
1 голос
/ 06 февраля 2009

У меня есть действие по созданию, которое пытается создать рейтинг и программу за один раз:

  def create
    @rating = current_user.ratings.create(params[:rating])
    @rating.create_programme(params[:programme])
    redirect_to ratings_path
  end

В этом коде рейтинг принадлежит и пользователю, и программе, и пользователю

  has_many :ratings
  has_many :programmes, :through => :ratings

и программа

  has_many :users, :through => :ratings
  has_many :ratings

Когда я вызываю вышеуказанное действие создания в RatingsController, Программа по какой-то причине не сохраняется как принадлежащая @rating. Так что, если я позвоню, например:

rating.programme.channel 

по рейтингу в представлении, он говорит мне, что программа является нулевым объектом. Тем не менее, программа была сохранена нормально - это просто ассоциация, которая не была сохранена. Я уверен, что это довольно простая вещь здесь, но я не могу понять это. Может ли кто-нибудь указать мне правильное направление?

спасибо, а

Ответы [ 4 ]

2 голосов
/ 07 февраля 2009

В ответ на ваш вопрос, чтобы помочь сделать код чище:

def create
  @rating = Rating.new(params[:rating])
  @rating.user      = curent_user
  @rating.programme = Programme.find_or_create_by_title(params[:programme])
  @rating.save

  redirect_to ratings_path
end

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

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

Наконец, вам, вероятно, не нужна @programme как отдельная переменная экземпляра, поскольку у вас будет легкий доступ к этому объекту из @rating.programme в ваших представлениях. В большинстве случаев лучше передавать как можно меньше переменных экземпляра, особенно когда объекты имеют легкодоступные прямые отношения. Это особенно актуально в этом случае, потому что вы вообще не рендерите шаблон.

0 голосов
/ 06 февраля 2009

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

Programme.ratings.create будет работать.

0 голосов
/ 07 февраля 2009

Я получил действие создания, работающее нормально со следующим. Был бы признателен, если бы кто-нибудь мог узнать, есть ли более элегантный способ заставить это работать:)

  def create
    @programme = Programme.find_or_create_by_title(params[:programme])
    @programme.save
    @rating = current_user.ratings.create!(params[:rating].merge(:programme_id => @programme.id))
    redirect_to ratings_path
  end

* 1004 Энди *

0 голосов
/ 06 февраля 2009

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

Rating.last

Возвращает рейтинг, который был только что создан. Посмотрите на user_id и programme_id на выходе и посмотрите, установлены ли они. Если они есть, то у вас есть ошибка в другом месте. Возможно, вы не смотрите на рейтинг, который вы считаете или что-то в этом роде.

...