Я пытаюсь сделать приложение для студентов, чтобы публиковать проекты. Когда они создают публикацию, они могут добавлять своих товарищей по команде. У каждого студента есть идентификатор пользователя, и я хочу, чтобы студент, создающий проект, мог выбирать другие идентификаторы из той же организации, что и их товарищи по команде. Ассоциации моделей:
пользователь
has_and belongs_to_many :projects
проект
has_and belongs_to_many :users
У меня есть модель проекта с:
:user_id (integer)
:team_mates (integer)
В форме моих проектов я хочу, чтобы студент (создающий проект) выбирал другие идентификаторы (из списка студентов, принадлежащих к одной организации) в качестве товарищей по команде. Мой первый вопрос: должен ли атрибут товарищей по команде быть целым числом (поскольку может быть более одного товарища по команде, и в этом случае может ли этот атрибут содержать массив?
Моя следующая проблема: я не знаю, как это сделать. Если я добавлю строку выбора в форму своего проекта, чтобы добавить user_ids, где user.organisation соответствует текущему идентификатору пользователя, тогда учащийся, создающий проект, должен увидеть список возможных вариантов.
Затем на странице показа моих проектов я хочу отобразить каждого ученика в команде.
Может ли кто-нибудь помочь с тем, как подойти к этому? Я потерялся и застрял в поисках примеров подобных проблем.
ОБНОВИТЬ
Я нашел эту статью: http://collectiveidea.com/blog/archives/2015/07/30/bi-directional-and-self-referential-associations-in-rails/
Хотя я в замешательстве. Я не знаю, следует ли мне присоединяться к проектам с пользователями (через таблицу соединений, которую я назвал «команды»), или мне следует объединять пользователей с пользователями через таблицу соединений, называемую «команды».
Если я присоединяю пользователей к проектам, для меня имеет смысл, что пользователь, создающий проект, может выбирать других пользователей в качестве товарищей по команде проекта. Однако неверно утверждать, что в каждом проекте много команд (что и показано в этом примере). Я не уверен в изменении has_many на has_one, так как в статье далее объясняется, как has_many через соединение.
Если я присоединяю пользователей к пользователям, то пользователь со многими проектами может иметь разные команды для каждого проекта. Так что это было бы не правильно.
Взяв статью за пример, я попробовал:
создать модель команд:
class CreateTeams < ActiveRecord::Migration
def change
create_table :teams do |t|
t.references :project, index: true, foreign_key: true
t.references :team_mate, index: true
t.timestamps null: false
end
add_foreign_key :teams, :projects, column: :team_mate_id
add_index :teams, [:project_id, :team_mate_id], unique: true
end
end
Команда.рб
belongs_to :project
belongs_to :team_mate, class_name: "Profile"
Контроллер команд (я разберусь с этим позже — пока он прокомментирован, так как у меня еще нет раздела сватовства):
class TeamsController < ApplicationController
before_action :resync_matches, only: :index
def index
# several orders of magnitude faster
@team_mates = current_user.team_mates
.page(params[:page])
end
private
def resync_matches
# only resync if we have to
if current_user.teams_outdated?
new_matches = MatchMaker.matches_for(current_user)
current_user.team_mates.replace(new_matches)
end
end
end
проект.rb
has_one :team
has_many :team_mates, through: :teams, dependent: :destroy
Я изменил это, чтобы у проектов была одна команда, а не много.
Я смущен этим и не уверен, как это запустить. В форме моих проектов я хочу предложить пользователям (которые создают проекты) выбирать профили других пользователей, которые являются товарищами по команде. Я потерялся в этот момент.
Я попытался сделать Teams Helper:
module TeamsHelper
def team_mate_options
s = ''
Profile.in_same_organisation.each do |profile|
s << "<option value='#{profile.id}'>#{profile.user.full_name}</option>"
end
s.html_safe
end
end
В своем profile.rb я попытался сделать область, чтобы получить профили, которые принадлежат к той же организации, что и создатель проекта (хотя я не уверен, что это правильно):
scope :in_same_organisation, -> (organisation_id) { where(organisation_id: organisation_id) }
Затем в форме моих проектов я попытался добавить опцию выбора:
<div class="form-group">
<%= label_tag 'team_mates', 'Choose team mates' %>
<%= select_tag 'team_mates', team_mate_options, multiple: true, class: 'form-control chosen-it' %>
</div>
ПРЕДЛОЖЕНИЕ ВИШАЛА
Приняв предложение Вишала, я реализовал предложенную структуру. У меня проблема с формой проектов. Моя полная установка:
Модели Организация
has_many :profiles
Профиль
has_many :projects
belongs_to :organisation
has_many :teams, foreign_key: "team_mate_id"
has_many :team_projects, through: :teams, source: :project
Проект
belongs_to :profile
has_many :teams
has_many :team_mates, through: :teams
Команда
belongs_to :project
belongs_to :team_mate, class_name: "Profile"
В моей таблице команд есть:
create_table "teams", force: :cascade do |t|
t.integer "project_id"
t.integer "team_mate_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Затем в моей форме проекта у меня есть:
<%= f.label :team_mates, :label => "Add a team member" %>
<%= f.collection_select(:team_mate_id, Profile.all, :id, :team_mate_select, {prompt: "Select the team member"}, {:required => true}) %>
В моей модели профиля у меня есть:
def team_mate_select
self.user.formal_name
end
Моя структура такова, что профили принадлежат пользователям. В пользователе у меня есть метод, называемый формальным именем, который добавляет заголовок к имени пользователя.
Когда я сохраняю это и пробую, я получаю сообщение об ошибке:
undefined method `team_mate_id' for #<Project:0x007fa08ed3d8e0>
(выделение строки выбора коллекции в форме проекта)
Мои проекты/form.html.erb имеют:
<%= simple_form_for(@project) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :title, :label => "Title", autofocus: true %>
<%= f.input :description, :as => :text, :label => "Describe your project", :input_html => {:rows => 10} %>
<%= f.input :remark, :as => :text, :label => "Is there an interesting fact or statistic that's relevant to this research?", :input_html => {:rows => 5}, :placeholder => "In fact, ...(insert a fact which shows why this research might be interesting or relevant)" %>
<%= f.input :hero_image, :label => "Add an image" %>
<%= f.label :team_mates, :label => "Add a team member" %>
<%= f.collection_select(:team_id, Profile.all, :id, :team_mate_select, {prompt: "Select the team member"}, {:required => true}) %>
<div class="form-actions" style="margin-top:50px">
<%= f.button :submit, "Create", :class => 'formsubmit' %>
</div>
<% end %>
project
иteam
будет связь. Если для каждогоproject
имеется ровно один столбецteam
, то вы просто добавляете столбецteam_id
в свою модельproject
, а также отношениеbelongs_to
. Отношение междуuser
иteam
аналогично отношению междуuser
иproject
, которое у вас уже есть. Ага, может быть, вашprojects
ведет себя в этом отношении какteams
? Тогда вам вообще не нужна была бы модельteam
. 11.03.2016