从父类创建一个子类,其中包含与sti的关系

时间:2015-04-24 15:26:38

标签: ruby-on-rails ruby-on-rails-3.2 subclass sti

我希望能够通过选择正确的角色创建一个继承自User的教授,并根据此角色链接并创建教授关系。 所以我做了:

User.rb

class User < ActiveRecord::Base

  attr_accessible :institution_id, :email, :password, :password_confirmation, :remember_me, :civility_id, :first_name,
                  :last_name, :login, :title, :avatar, :role_ids, :users_institutions_levels_attributes,
                  :users_institutions_topics_attributes, :encrypted_pass,
                  :professors_attributes
  belongs_to :institution
  has_many :students
  has_many :professors
  has_many :institutions_levels, through: :students
  accepts_nested_attributes_for :students, :professors
  # Roles
  has_many :roles, :through => :roles_users
  has_many :roles_users
  accepts_nested_attributes_for :roles_users, allow_destroy: true    
  has_many :levels, through: :institutions_levels

  # Validations
  #----------------------------------------
  validates :institution_id, :civility_id, :first_name, :last_name, :email, presence: true, if: 'self.class == User'
  validates_uniqueness_of :email
  validates :email, email: true
  validates :login, presence: true, format: {with: /^([a-zA-Z0-9_\.-]+)*$/}, if: 'self.class == User'
  validates_uniqueness_of :login, scope: [:institution_id]
end

Professor.rb

class Professor < User

  alias_attribute :user_id, :id

  #----- Attributes
  attr_accessible :civility_name, :level_key_names, :topic_key_names, :professor_id, :filtered_topics_attributes
  #----- Filters
  after_save :after_save_actions
  has_many :teacher_exercises
  has_and_belongs_to_many :filtered_topics
  has_many :filtered_levels, through: :filtered_topics
  accepts_nested_attributes_for :filtered_topics, allow_destroy: true
end

_form.html.erb

<%= simple_form_for(@user,  html: {class: 'form-horizontal'}) do |form| %>
  <div class="panel-body">
    <% for field in [:first_name, :last_name, :title, :email, :login, :password] -%>
      <%= form.input field %>
    <% end -%>
  </div>
  <div class="panel-heading clearfix">
    <h3 class="panel-title">
      <%= glyphicon(:user) %>
      <%= t('activerecord.models.role') %>
    </h3>
  </div>
  <%= form.association :roles,
                       collection: Role.accessible_by(Ability.new(current_user)),
                       as: :check_boxes,
                       label: t('commons.role') %>

    <%= form.simple_fields_for(:professors) do |ass| %>
      <div class="panel-heading clearfix">
        <div class="btn-toolbar pull-right">
          <%= link_to_add_association(glyph(:plus), ass, :filtered_topics) %>
        </div>
        <h3 class="panel-title">
          <%= glyphicon(:bookmark) %>
          <%= t('activerecord.models.topics') %>
        </h3>
      </div>
      <div class="fields_filtered_topics">
        <%= ass.simple_fields_for(:filtered_topics) do |form_r| %>
          <%= render(:partial => 'admin/users/form/filtered_topic', :locals => {f: form_r}) %>
        <% end %>
      </div>
    <% end %>
<% end %>

_filtered_topic.html.erb

<li class="fields list-group-item">
  <%= link_to_remove_association(glyphicon(:remove), f) %>
  <%= f.input :topic_id,
              prompt: @current_model.human_attribute_name(:topic.to_s),
              collection: FilteredTopic.accessible_by(Ability.new(current_user)),
              label_method: :topic,
              value_method: :topic_id %>
  <%= f.association :institutions_levels %>
</li>

它带来了许多问题,首先,因为professor_attributes仅用于它没有接受用户参数(登录,电子邮件等)的关系,并且它抱怨它们丢失所以我添加了一个条件,如果班级是用户,请检查验证,但这更难以改变,因为他们无论如何都不会得到保存。我想在控制器中弄乱哈希,但这似乎是一个非常糟糕的做法。

我无法找到关于如何实现我想要的东西的解释,我真的很感激一些帮助。

1 个答案:

答案 0 :(得分:0)

如果控制器是STI,则控制器无法直接创建嵌套实例。

我要解决此问题的方法是传入一个类型并在控制器上手动创建。例如在您的控制器中

if params[:main_type][:nested_type_attributes] && params[:main_type][:nested_type_attributes][:type]
  nested_type_attributes = params[:main_type].delete(:nested_type_attributes)
  klass = nested_type_attributes.delete(:type).constantize
  params[:main_type][:nested_type] = klass.new(nested_type_attributes)
end