Построение полиморфной ассоциации со стороны принадлежащей стороны - PullRequest
1 голос
/ 15 ноября 2011

Рассмотрим приложение, состоящее из разных типов пользователей, каждый из которых имеет разные профили. Во время регистрации пользователь может выбрать свой тип пользователя (например, покупатель или продавец).

class User < ActiveRecord::Base
  belongs_to :profileable, :polymorphic => true
  PROFILE_TYPES = %w[Buyer Seller]
end

class Buyer < ActiveRecord::Base
  # this is like a buyer profile
  has_one :user, :as => :profileable
end

class Seller < ActiveRecord::Base
  # this is like a seller profile
  has_one :artist, :as => :profileable
end

Массив PROFILE_TYPES используется в options_for_select в новом действии контроллера Users, позволяя пользователю выбрать его / ее тип пользователя.

просмотров / пользователей / new.html.erb

<%= form_for @user do |f| %>
  <%= label_tag "Type" %>
  <%= f.select :profileable_type, options_for_select(User::PROFILE_TYPES) %>
  <%# ... %>
<% end %>

Это правильно сохраняет атрибут profileable_type для пользователя.

Мой вопрос: как только пользователь создан, я бы хотел, чтобы его перенаправили на действие Users # show, где строится правильная профилируемая ассоциация. Форма будет отображаться динамически в зависимости от profileable_type.

Пока что я могу сделать правильную форму со следующим

просмотров / пользователей / show.html.erb

<%= render "#{@user.profileable_type.downcase}/form" %>

Однако это кажется очень неортодоксальным, и я не совсем уверен, как построить ассоциацию. Могу ли я создать ассоциацию при первоначальном создании пользователя? Или я должен создать ассоциацию в Buyers # create и Sellers # create (где указана вышеупомянутая форма)? Должен ли я моделировать данные по-другому?

UPDATE

У меня правильно работает эта функция, добавив attr_accessor :user_type к модели User.

app / models / user.rb (обновлено)

class User < ActiveRecord::Base
  # ...
  attr_accessor :user_type

  def user_type=(type)
    self.profileable = type.constantize.new
    self.profileable.save
  end
end

views / users / new.html.erb (обновлено)

<%= form_for @user do |f| %>
  <%= f.label :user_type %>
  <%= f.select :user_type, options_for_select(User::PROFILE_TYPES) %>
  <%# ... %>
<% end %>

Это создает правильный связанный объект и сохраняет profileable_type и profileable_id для пользователя. Тем не менее, это все еще кажется неловким и хакерским. Единственный способ обойти это, чтобы иметь отдельные формы для каждого типа пользователя? Это не очень СУХО, так как я не заставляю пользователя заполнять определенные атрибуты для профиля, который он / она выбирает, до тех пор, пока сам пользователь не будет создан.

1 Ответ

0 голосов
/ 15 ноября 2011
@user = @buyer.user.new(params[:user])
@user.save

Это автоматически сохранит profileable_type и id.Также

<%= render "#{@user.profileable_type.downcase}/form" %>

не является хорошей практикой.Ваша модель слишком много знает о представлении.Похоже, вы должны иметь форму покупателя и продавца, а не форму пользователя.Мне нужно больше информации, чтобы привести пример.

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