从belongs_to方面构建多态关联

时间:2011-11-15 02:52:54

标签: ruby-on-rails

考虑一个由各种用户类型组成的应用程序,每个用户类型都有不同的配置文件。在注册期间,允许用户选择他/她的用户类型(即买方或卖方)。

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,允许用户选择他/她的用户类型。

视图/用户/ 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 action,其中构建了正确的可分析关联。将根据profileable_type动态呈现表单。

到目前为止,我能够使用以下

呈现正确的表单

视图/用户/ show.html.erb

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

然而,这似乎非常不正统,我不太确定如何建立联系。我可以在最初创建用户时创建关联吗?或者我应该在买家#create和卖家#create(上面的表格点)中创建关联?我应该以不同方式对数据建模吗?

更新

通过向用户模型添加attr_accessor :user_type,我可以正常运行。

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保存在用户上。然而,这似乎仍然是尴尬和hackish。围绕这个的唯一方法是为每种用户类型分别创建表单吗?这不是很干,因为我没有强迫用户填写他/她选择的配置文件的特定属性,直到创建用户本身。

1 个答案:

答案 0 :(得分:0)

@user = @buyer.user.new(params[:user])
@user.save

这将自动保存profileable_type和id。还

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

不是好习惯。你的模型对视图了解得太多了。看起来您应该有买家和卖家表格,而不是用户表格。我需要更多信息来举例。