0

Приложение Ruby on Rails, над которым я работаю, позволяет users создавать и обмениваться agendas с другими users.Ассоциации активных записей: has_and_belongs_to_many, has_many: сквозная или полиморфная ассоциация?

Кроме того, мы должны быть в состоянии:

  • Отображать список agendas для каждого user, на его профиле
  • Показать список users, связанный с agenda, на странице
  • в повестку дня в
  • При совместном использовании повестки дня с другим пользователем определите role для этого пользователя и покажите роль этого пользователя в списке, указанном выше, выше

Я собирался пойти с has_and_belongs_to_many ассоциации между user и agenda моделей, как это:

class User < ActiveRecord::Base 
    has_and_belongs_to_many :agendas 
end 

class Agenda < ActiveRecord::Base 
    has_and_belongs_to_many :users 
end 

Но тогда я задавался ли это позволит мне получить и отобразить @user.agenda.user.role список roles на данный страницы повестки дня данного пользователя.

И я думал, что я должен, вероятно, пойти с has_many :through ассоциации вместо этого, таких как:

class User < ActiveRecord::Base 
    has_many :roles 
    has_many :agendas, through: :roles 
end 

class Role < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :agenda 
end 

class Agenda < ActiveRecord::Base 
    has_many :roles 
    has_many :users, through: :roles 
end 

И хотя я был довольно комфортно об идее user, имеющих нескольких roles (по одному для каждого agenda), я я не уверен в идее agenda, имеющей несколько roles (по одному для каждого user?).

Наконец, чтобы добавить к путанице, я прочитал о полиморфной ассоциации и думал, что это может быть жизнеспособным решением, если сделано таким образом, к примеру:

class Role < ActiveRecord::Base 
    belongs_to :definition, polymorphic: true 
end 

class User < ActiveRecord::Base 
    has_many :roles, as: :definition 
end 

class Agenda < ActiveRecord::Base 
    has_many :roles, as: :definition 
end 

ли какой-либо из перечисленных выше решений звука правых для ситуации?

UPDATE: Выполнение некоторых исследований, я наткнулся на эту статью (с 2012 года), объясняя, что has_many :through был «умнее», чем выбор has_and_belongs_to_many. В моем случае я все еще не уверен в том, что у agenda будет много roles.

ОБНОВЛЕНИЕ 2: Как было предложено в комментариях от @engineersmnkyn, способом решения этого было бы пойти с двумя таблицами соединений. Я попытался реализовать следующий код:

class User < ActiveRecord::Base 
    has_many :agendas, through: :jointable 
end 

class Agenda < ActiveRecord::Base 

end 

class Role < ActiveRecord::Base 

end 

class Jointable < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :agenda 
    has_many :agendaroles through :jointable2 
end 

class Jointable2 < ActiveRecord::Base 
    belongs_to :roles 
    belongs_to :useragenda 
end 

Я не уверен в синтаксисе. Я на правильном пути? И как мне определить модели Agenda и Role?

UPDATE 3: Что делать, если я пошел что-то вроде:

class User < ActiveRecord::Base 
     has_many :roles 
     has_many :agendas, through: :roles 
    end 

    class Role < ActiveRecord::Base 
     belongs_to :user 
     belongs_to :agenda 
    end 

    class Agenda < ActiveRecord::Base 
     has_many :roles 
     has_many :users, through: :roles 
    end 

, а затем, в файле миграции, идти с чем-то вроде:

class CreateRoles < ActiveRecord::Migration 
    def change 
    create_table :roles do |t| 
     t.belongs_to :user, index: true 
     t.belongs_to :agenda, index: true 
     t.string :privilege 
     t.timestamps 
    end 
    end 
end 

Смогу ли я позвонить @ user.agenda.privilege, чтобы получить привилегию («роль» создателя, редактора или зрителя) данного пользователя для данной повестки дня?

С другой стороны, мог бы я позвонить @ Agenda.user.privilege?

+1

Почему бы не настроить пользователя на множество планов через таблицу соединений, принадлежащую пользователю и повестке дня, и имеет много функций повестки дня через таблицу соединений, которая относится к повестке дня и ролям пользователей. Я бы написал его для вас, но сейчас я не на компьютере. – engineersmnky

+0

Благодаря @engineersmnky это имеет большой смысл, поскольку он фиксирует проблему повесток дня, не имеющих много ролей. Если я правильно понял, что вы предложили, код будет выглядеть примерно так: https://repl.it/tNS. Я не уверен в синтаксисе. –

ответ

1

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

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

Основные Rails правило:

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

Во-первых, используя свой пример (http://repl.it/tNS):

class User < ActiveRecord::Base 
    has_many :user_agendas 
    has_many :agendas, through: :user_agendas 
    has_many :user_agenda_roles, through: :user_agendas 
    has_many :roles, through: :user_agenda_roles 

    def agenda_roles(agenda) 
    roles.where(user_agenda_roles:{agenda:agenda}) 
    end 
end 

class Agenda < ActiveRecord::Base 
    has_many :user_agendas 
    has_many :users, through: :user_agendas 
    has_many :user_agenda_roles, through: :user_agendas 
    has_many :roles, through: :user_agenda_roles 

    def user_roles(user) 
     roles.where(user_agenda_roles:{user: user}) 
    end 
end 

class Role < ActiveRecord::Base 
    has_many :user_agenda_roles 
end 

class UserAgenda < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :agenda 
    has_many :user_agenda_roles 
    has_many :roles, through: :user_agenda_roles 
end 

class UserAgendaRoles < ActiveRecord::Base 
    belongs_to :role 
    belongs_to :user_agenda 
end 

Это использует таблицы объединения, чтобы держать связь пользователя < => Повестка дня, а затем таблицу, чтобы присоединиться к UserAgenda => Роль.

Второй вариант - использовать таблицу соединений, чтобы сохранить связь пользователя < => Повестка дня и другая таблица соединений для обработки отношений пользователя < => Повестка дня < => Роль. Эта опция будет немного больше настроена с точки зрения CRUD для таких вещей, как проверка того, является ли пользователь пользователем для этой Повестки, но обеспечивает небольшую гибкость.

class User < ActiveRecord::Base 
    has_many :user_agendas 
    has_many :agendas, through: :user_agendas 
    has_many :user_agenda_roles 
    has_many :roles, through: :user_agenda_roles 

    def agenda_roles(agenda) 
     roles.where(user_agenda_roles:{agenda: agenda}) 
    end 

end 

class Agenda < ActiveRecord::Base 
    has_many :user_agendas 
    has_many :users, through: :user_agendas 
    has_many :user_agenda_roles 
    has_many :roles, through: :user_agenda_roles 

    def user_roles(user) 
     roles.where(user_agenda_roles:{user: user}) 
    end 
end 

class Role < ActiveRecord::Base 
    has_many :user_agenda_roles 
end 

class UserAgenda < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :agenda 
end 

class UserAgendaRoles < ActiveRecord::Base 
    belongs_to :role 
    belongs_to :user 
    belongs_to :agenda 
end 

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

+0

Большое спасибо за ваше время и помощь @engineersmnky. Я собираюсь дать вам оба решения. Согласитесь с вами о ограничениях has_and_belongs_to_many, которые мешают нам работать непосредственно с этими отношениями. Один вопрос: что вы думаете о решении, которое я публикую в UPDATE 3? –

+1

@ThibaudClement Проблема, которую я вижу, заключается в том, что вам придется настраивать одни и те же роли несколько раз для каждой новой повестки дня или пользователя. Я был в предположении, что роль будет чем-то вроде владельца, редактора и т. Д., И в этом случае вам действительно понадобится только 1 ссылка на каждую роль, и это применимые разрешения, а не необходимость устанавливать их каждый раз.Если я неправильно понял, что роль роли играет в этой настройке, тогда ваше решение может работать для вас, поскольку это правильные отношения. – engineersmnky

+0

Еще раз спасибо @engineersmnky. Извините за то, что я не был точным в своем вопросе. Позвольте мне прояснить ситуацию. Было бы три различные возможные роли: 1. Владелец (лицо, создающее повестку дня в первую очередь), 2. Редактор (человек, с которым повестка дня была разделена и у кого есть право редактировать ее) и 3. Viewer (лицо, с которым повестка дня была разделена, и которая может ее видеть, но не редактировать). Поскольку это совместное приложение, у нас может быть несколько редакторов и зрителей (и даже владельцев) для каждой программы. Это имеет смысл? –