Обновление дополнительных атрибутов в отношении has_many:: through с использованием Rails - PullRequest
2 голосов
/ 14 июня 2010

Мне удалось установить отношения «многие ко многим» между следующими моделями

  • Персонажи
  • Навыки
  • PlayerSkills

У PlayerSkills сейчас есть атрибут, которого навыки обычно не имеют: уровень.

Модели выглядят примерно так (отредактировано для краткости):

class PlayerSkill < ActiveRecord::Base
  belongs_to :character
  belongs_to :skill
end

class Skill < ActiveRecord::Base
  has_many :player_skills
  has_many :characters, :through => :player_skills

  attr_accessible :name, :description
end

class Character < ActiveRecord::Base
  belongs_to :user

  has_many :player_skills
  has_many :skills, :through => :player_skills
end

Так что в моделях ничего особенного ... Контроллер также является очень простым на данный момент ... это в значительной степени стандартное действие обновления.

Форма, которую я хочу изменить, это символы # edit. Прямо сейчас он отображает серию флажков, которые добавляют / удаляют навыки персонажей. Это замечательно, но весь смысл использования has_many: through был также для отслеживания "уровня".

Вот что у меня есть:

- form_for @character do |f|
  = f.error_messages
  %p
    = f.label :name
    %br
    = f.text_field :name
  %p
    = f.label :race
    %br
    = f.text_field :race
  %p
    = f.label :char_class
    %br
    = f.text_field :char_class
  %p
    - @skills.each do |skill|
      = check_box_tag "character[skill_ids][]", skill.id, @character.skills.include?(skill)
      =h skill.name
      %br
  %p
    = f.submit

После того, как он отобразит «skill.name», мне нужно напечатать текстовое поле, которое обновляет player_skill.

Проблема, конечно, в том, что player_skill может существовать или не существовать! (В зависимости от того, отмечен ли флажок при загрузке формы!)

Из всего, что я прочитал, has_many: сквозное соединение прекрасно, потому что оно позволяет вам относиться к самим отношениям как к сущности ... но я совершенно не понимаю, как обращаться с сущностью в этой форме.

Как всегда, заранее спасибо за любую помощь, которую вы можете мне оказать!

Ответы [ 2 ]

1 голос
/ 18 июня 2010

Я до сих пор исправил проблему, которая у меня была ...

Когда я узнал о вложенных атрибутах, это было относительно просто!

Вот новая модель персонажей!

class Character < ActiveRecord::Base
  belongs_to :user

  has_many :player_skills
  has_many :skills, :through => :player_skills
  accepts_nested_attributes_for :player_skills

  def skills_pre_update(params)
    skills = Skill.find(:all, :order => 'id')
    skills = skills.map do |skill|
      skill.id
    end

    self.skill_ids = []
    self.skill_ids = skills

    self.skill_ids.each_with_index do |skill_id, index|
      self.player_skills[index].level = params[:character][:player_skills_attributes][index][:level]
    end

    self.skill_ids = params[:character][:skill_ids]
  end
end

А действие обновления для контроллера персонажа было слегка изменено:

@character.skills_pre_update(params)
params[:character].delete(:player_skills_attributes)
params[:character].delete(:skill_ids)

Причина в том, что эти две части уже обрабатываются действием pre_update, поэтому их не нужно снова обрабатывать update_attributes, который вызывается позже.

Вид был относительно прямым. флажки «многие ко многим» остаются прежними, однако я добавил новые текстовые поля!

- @skills.each_with_index do |skill,index|
  = check_box_tag "character[skill_ids][]", skill.id, @character.skills.include?(skill)
  =h skill.name
  -ps = skill.player_skills.find_by_character_id(@character) || skill.player_skills.build
  -fields_for "character[player_skills_attributes][]", ps do |psf|
    =psf.text_field(:level, :index => nil)
    =psf.hidden_field(:id, :index => nil)

По сути, причина, по которой я должен исключить skill_ids (skill_ids = []) в модели персонажей, заключается в том, что в противном случае он неправильно устанавливает порядок.

По сути, я добавляю все навыки.
Обновите уровни, используя текстовые поля.
Затем сбросьте навыки до того, что пользователь фактически проверил (что удалит все неиспользуемые навыки.)

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

В противном случае, я надеюсь, что это поможет кому-то еще ... потому что изменение дополнительных атрибутов в таблице соединений (без предоставления таблице соединений своих собственных контроллеров / представлений) было настоящей болью!

0 голосов
/ 14 июня 2010

Я не уверен насчет ответа, но вот что я думаю:

Для контроллера:

@character = Character.find(params[:id])

В представлении:

<% if @character.skills!=0 %>
    <% for skill in @character.skills %>
        <%=h skill.name %>
        <%= check_box_tag(skill.name, value = "1", checked = false, options = {...}) %>
    <% end %>
<% end %>

Надеждаэто поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...