Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails multiple Has_one relationship to same model

I am working on a Rails application and currently I have 2 models - Subjects and Lessons. A Subject has 3 different types of lessons - Lecture, Tutorial and Laboratory. I modelled such that there are 3 has_one to the Lesson model.

Right now, I am trying to create a nested form for subjects and lessons but the lecture, tutorial and laboratory being saved was always the first form that was rendered. i.e. I have 3 nested forms separately for Lecture, Tutorial and Laboratory but the Lecture, Tutorial and Laboratory that was saved was always the one that was first built. In my codes the lecture was first built so the attributes for tutorial and laboratory would follow the one that I have filled in for my lecture.

I am not sure where I have went wrong or even if having multiple has_one relationship works in this case so any advice would be appreciated.

The related codes are as follows:

The subject model

class Subject < ActiveRecord::Base

  has_one :lecture, :class_name => "Lesson"
  has_one :laboratory,:class_name => "Lesson"
  has_one :tutorial, :class_name => "Lesson"

  accepts_nested_attributes_for :lecture
  accepts_nested_attributes_for :laboratory
  accepts_nested_attributes_for :tutorial 

end

The lesson model

class Lesson < ActiveRecord::Base
  belongs_to :subject
end

The Subject and lesson nested form

<%= form_for(@subject_list) do |f| %>
  <div class="field">
    <%= f.label :subject_code %><br />
    <%= f.text_field :subject_code %>
  </div>
  <div>
    <%= f.fields_for :lecture do |lecture| %>
      <%= render "lecture_fields", :f => lecture %>
    <% end %>
  </div>
  <div>
    <%= f.fields_for :tutorial do |tutorial| %>
      <%= render "tutorial_fields", :f => tutorial %>
    <% end %>
  </div>
  <div>
    <%= f.fields_for :laboratory do |laboratory| %>
      <%= render "laboratory_fields", :f => laboratory %>
    <% end %>
  </div>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

The new action in the subject controller

    def new
    @subject = Subject.new

    lecture = @subject.build_lecture
    laboratory = @subject.build_laboratory
    tutorial = @subject.build_tutorial

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @subject }
    end
  end

I would appreciate if someone could help me out in identifying where I have went wrong. If in the case that I should not be creating such multiple relationships, I would like to have some advice on how could I actually render out 3 forms with a default field indicating the lesson type.

like image 486
Butter Beer Avatar asked Jan 19 '13 13:01

Butter Beer


1 Answers

I'm not really sure if that works, but my advise is to use AR inheritance

class Lesson < ActiveRecord::Base
end

class LectureLesson < Lesson
  belongs_to :subject
end

class LaboratyLesson < Lesson
  belongs_to :subject
end

class TutorialLesson < Lesson
  belongs_to :subject
end

class Subject
  has_one :lecture_lesson
  has_one :laboratory_lesson
  has_one :tutorial_lesson

  accepts_nested_attributes_for :lecture_lesson
  accepts_nested_attributes_for :laboratory_lesson
  accepts_nested_attributes_for :tutorial_lesson
end

Migration

class LessonsAndSubjects < ActiveRecord::Migration
  def up
    remove_column :subjects, :lesson_id

    add_column :subjects, :lecture_lesson_id, :integer
    add_column :subjects, :laboratory_lesson_id, :integer
    add_column :subjects, :tutorial_lesson_id, :integer

    add_column :lessons, :type, :string

    add_index :subjects, :lecture_lesson_id
    add_index :subjects, :laboratory_lesson_id
    add_index :subjects, :tutorial_lesson_id
  end

  def down
    remove_column :subjects, :lecture_lesson_id
    remove_column :subjects, :laboratory_lesson_id
    remove_column :subjects, :tutorial_lesson_id

    remove_column :lessons, :type

    add_column :subjects, :lesson_id, :integer
  end
end

it makes more sense and it may be fix you issue with nested attributes

like image 117
rorra Avatar answered Sep 20 '22 03:09

rorra