2013-12-20 9 views
0

Итак, если у меня есть таблица many_to_many с только идентификаторами в ней, и я хочу ссылаться на нее в другой модели, как бы я это сделал?Ruby on Rails - Ссылка на отношения many_to_many

Так что в модели, которая называется Rating, я хочу сказать, что она связана с обоими вещами в ассоциации, в данном случае с курсом и учебником. Таким образом, рейтинг определяется учебником и курсом. Должен ли я добавить два атрибута id в Rating, которые ссылаются на оба? Должен ли я добавлять идентификатор в many_to_many, а затем иметь атрибут ID в таблице рейтинга? Или есть что-то еще, что я могу сделать?

UPDATE:

Так вот мой ERD до сих пор. Вы можете игнорировать вещи со студентами и профессорами. ERD С правой стороны стол, который я сделал в соответствии с @RichPeck. Я смущен тем, как создавать записи. Например, я создаю курс.

course = Course.new(params)

Я тогда сделать это, чтобы сделать учебник.

textbook = course.textbooks.build(params)

Теперь, когда я course.textbooks, он перечисляет учебник я только что сделал, но когда я textbook.courses я получаю пустой список. Кроме того, после сохранения их и выхода из оболочки, а затем повторного открытия, обе команды reutnr пустым списком. Теперь это потому, что таблица соединений, CourseTextboks, пуста. Почему рельсы не добавляют туда запись? Нужно ли мне что-то делать?

Вот соответствующие файлы:

CreateCourseTextbooksMigration

class CreateCourseTextbooks < ActiveRecord::Migration 
    def change 
    create_table :course_textbooks do |t| 
     t.references :course, index: true 
     t.references :textbook, index: true 

     t.timestamps 
    end 
    end 
end 

CreateTextbookMigration

class CreateTextbooks < ActiveRecord::Migration 
    def change 
    create_table :textbooks do |t| 
     t.string :title 
     t.string :authors 
     t.string :edition 
     t.float :price 
     t.string :isbn 
     t.text :description 
     t.string :image_url 
     t.date :published 

     t.timestamps 
    end 
    end 
end 

CreateCourseMigration

class CreateCourses < ActiveRecord::Migration 
    def change 
    create_table :courses do |t| 
     t.string :title 
     t.string :letters 
     t.integer :number 

     t.timestamps 
    end 
    end 
end 

И мод ELS:

курс

class Course < ActiveRecord::Base 
    has_many :student_courses 
    has_many :students, through: :student_courses 

    has_many :professor_courses 
    has_many :professors, through: :professor_courses 

    has_many :textbook_courses 
    has_many :textbooks, through: :textbook_courses 

    validates_presence_of :title, :letters, :number 
end 

Учебник

class Textbook < ActiveRecord::Base 
    has_many :textbook_courses 
    has_many :courses, through: :textbook_courses 
end 

CourseTextbook

class CourseTextbook < ActiveRecord::Base 
    belongs_to :course 
    belongs_to :textbook 

    has_many :rating_course_textbooks, :class_name => "RatingCourseTextbook" 
    has_many :ratings, :through => :rating_course_textbooks 

    validates_presence_of :course 
end 

Можете ли вы помочь мне, ребята?

UPDATE2:

Я понял это после того, как примерно через полчаса поиска и обращать больше внимания на SQL сгенерированного при создании объектов .. Так что, когда вы делаете course.build он просто возвращает объект и как-то ссылки это, но не через таблицу соединений. Я узнал, что вы должны сохранить курс НЕ нового профессора или просто использовать create.

Это то, что происходит

>>> course = Course.create(params) 
    # INSERT into courses table 
>>> professor = course.build(params) 

>>> professor.save 
    # INSERT into professors table 
>>> course.professors 
    # [Professor {id:1, blah}] 
>>> professor.courses 
    # [] 

И это то, что теперь работает

>>> course = Course.create(params) 
    # INSERT into courses table 
>>> professor = course.build(params) 

>>> course.save 
    # INSERT into professors table 
    # INSERT into professor_courses table 
>>> course.professors 
    # [Professor {id:1, blah}] 
>>> professor.courses 
    # [Course {id:1, blah}] 

яй! Теперь просто чтобы увидеть, если все это работает с другими моими моделями, как RatingsCourseTextbooks

Update3 Таким образом, после возни на некоторое время, я обнаружил, что я делал это слишком сложно. В рейтинге может быть только один CourseTextbook, поэтому мне не нужна другая таблица соединений. Я просто добавил идентификатор CourseTextbook для рейтинга.

New ERD

Спасибо за вашу поддержку

ответ

2

Я предполагаю, что вы новичок в Rails, поэтому я объясню, как это будет работать для вас здесь:


ActiveRecord Associations

Одной из основных особенностей Rails' является ActiveRecord association

ActiveRecord поддерживает схему реляционных баз данных, позволяя ссылаться на разные «связанные» модели из одного запроса. Это, как вы можете позвонить @user.images и т.д.

ActiveRecord сидит выше уровня базы данных, и ссылается на вашей модели с использованием has_many, belongs_to и т.д. ссылок. Если вы хотите сослаться на свои родственные модели, вы должны будете использовать эти, как это:

#app/models/user.rb 
Class User < ActiveRecord::Base 
    has_many :images 
end 

#app/models/image.rb 
Class Image < ActiveRecord::Base 
    belongs_to :user 
end 

Ваш код

Кажется, вы используете has-and-belongs-to-many

Как уже упоминалось Sachin Singh, вам, скорее всего, будет лучше всего использовать polymorphic relationship с этими моделями: Polymorphic Association

Это позволяет вам ссылаться на отношения нескольких моделей: Rails/ActiveRecord заполняет полиморфные поля с именем модели & id.Вот как ваши модели могут выглядеть:

Class Rating < ActiveRecord::Base 
    belongs_to :rateable, :polymorphic => true 
end 

Class Course < ActiveRecord::Base 
    has_many :ratings, :as => :rateable 
end 

Class Textbook < ActiveRecord::Base 
    has_many :ratings, :as => :rateable 
end 

Update

Если вы хотите иметь конкретные учебники для некоторых курсов, и имеют рейтинги этих учебников, вы, вероятно, лучше всего использовать has_many :through

Это может быть совершенно не по себе, но я установил таблицы courses и textbooks как таблицы верхнего уровня, а затем textbook_courses как aj ойн-модель. Я бы затем textbook_course_ratings в другом присоединиться к модели, чтобы дать необходимые рейтинги за учебник

Цель будет @course.textbooks.ratings

Class Course < ActiveRecord::Base 
    has_many :textbook_courses 
    has_many :textbooks, :through => :textbook_courses 
end 

Class Textbook < ActiveRecord::Base 
    has_many :textbook_courses 
    has_many :courses, :through :textbook_courses 
end 

Class TextbookCourse < ActiveRecord::Base 
    belongs_to :textbook 
    belongs_to :course 

    has_many :textbook_course_ratings, :class_name => "TextbookCourseRating" 
    has_many :ratings, :through => :textbook_course_ratings 
end 

Class TextbookCourseRating < ActiveRecord::Base 
    belongs_to :textbook_course 
    belongs_to :rating 
end 

Class Rating < ActiveRecord::Base 
    has_many :textbook_course_ratings, :class_name => "TextbookCourseRating" 
    has_many :textbooks, :through => :textbook_ratings 
end 

Я никогда не делал такие глубокие has_many :through отношений, прежде чем ; но он должен работать

Там несколько важных вещей, чтобы отметить:

  1. Вы должны изменить свои объединения таблиц включить primary key (идентификатор) - HABTM они не нужны, но НМТ делает
  2. Вы будете иметь много accepts_nested_attributes_for сделать :)

Ваши объединения таблиц для этого будет выглядеть следующим образом:

textbook_courses 
id | course_id | textbook_id | created_at | updated_at 

textbook_courses_ratings 
id | textbook_course_id | rating_id | created_at | updated_at 
+0

лучшее объяснение. –

+0

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

+0

Вы можете использовать 'has_many: through' за то, что вы опубликовали - позвольте мне написать его вам! –

0

если, Курс и TextBook имеет много оценок, то в таблице рейтингов должна быть полиморфным.

class Rating < AcrtiveRecord::Base  
    belongs_to :ratable, polymorphic: true  
end 

class Course < ActiveRecord::Base 
    has_many :ratings, as: :ratable 
end 

class TextBook < ActiveRecord::Base 
    has_many :ratings, as: :ratable 
end 

рейтинги таблица будет иметь два столбца с именем ratable_type и ratable_id

ratable_type: он будет держать имя класса курс или учебник.

ratable_id: он будет содержать идентификатор ассоциированного abject.

+0

Это не то, что чтение относится к курсу или учебнику. Это одновременно. Таким образом, могут быть разные оценки для одного и того же учебника в другом курсе – adamk33n3r

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