2014-02-27 77 views
1

在過去的2個小時裏,我對這個問題感到滿意。我有這兩個多態鏈接的類。醫生在醫生中有東西,用戶處理Web組件(電子郵件地址,設計等)。醫生是用戶。如何在兩側實例化具有多態關聯/驗證的Rails模型?

原因是有不同的用戶類別(護士,MedicalInstitutions),都需要他們自己的領域,但通過它們是用戶這一事實鏈接在一起。所以我在這種情況下選擇了多態關聯。

的問題是,我似乎無法實例兩者,因爲兩者都不會被保存。假設一個空的數據庫,我究竟如何創建它們,因爲它們需要彼此?有沒有辦法同時「保存兩個」?

class User < ActiveRecord::Base 
    rolify 
    devise :database_authenticatable, :registerable, 
     :recoverable, :rememberable, :trackable, :validatable 

    validates_presence_of :profile 

    belongs_to :profile, polymorphic: true 
end 

class Doctor < ActiveRecord::Base 
    has_one :user, as: :profile, dependent: :destroy 
    accepts_nested_attributes_for :user 

    validates_presence_of :user 

    # doctor-specific code here 

    delegate :email, :password, to: :user 
end 

class Nurse < ActiveRecord::Base 
    # has_one, accepts... same as doctor. nurse-specific code here 
end 

我也很感謝它,如果有人可以解決如何在FactoryGirl中實例化。

另:我見過this,但他們沒有驗證雙方。

+0

不完全清楚你的設置在這裏 - 試圖要求q的澄清。因此,醫生是一個用戶 - 那麼就醫生而言,它是一個護士還是醫療機構,就其代碼而言?這就是你的意思是不同的用戶類別? –

+0

@RichardJordan謝謝你的回答。是的,他們是一樣的。他們有自己的專門領域。 –

+0

@DaryllSantos所以基本上每個人都是一個用戶。唯一不同的是,他們有不同的配置文件(醫生/護士/等)? –

回答

0

您可以直接跳過驗證您的第一個記錄:

your_record.save(validate: false) 

編輯:

其實,你並不需要跳過驗證。它不工作的原因可能是因爲validates_presence_of檢查數據庫中是否存在關聯的對象。所以對於醫生,護士等(has_many方面),可以這樣做,因爲這些表不存儲user_id。但是,你應該更改用戶模型的驗證檢查:

validates :profile_id, presence: true 

這將確保PROFILE_ID屬性分配,即使配置文件(醫生,護士等)尚不存在。你必須雖然建立在正確的順序中的對象:

u = User.new 
d = Doctor.new 
u.profile = d 
u.save # it should be happy at this point because profile_id should be set 
d.save 
+0

謝謝邁克。呃,我如何確保一切都很好地驗證? –

+0

我更新了我的答案,我認爲這將解決您的問題。由於多態性可能會略微偏離,但這個想法應該是正確的。 –

0

存儲爲資源的用戶類型(護士/醫生),並有用戶控制器

class User 
    #resource will be nurse/doctor etc 
    belongs_to :resource, polymorphic: true, dependent: :destroy 
    accepts_nested_attributes_for :resource 

    #add user specific validations here 
end 

#user will be either doctor or nurse and not both 

class Doctor 
    has_one :user, as :resource 
    #add doctor specific validations 
end 

class Nurse 
    has_one :user, as :resource 
    #add nurse specific validations 
end 

現在,當u創建用戶類型的醫生/護士,你可以要求用戶選擇類型,並根據選擇呈現所選類型的嵌套形式。您可以在用戶表單中爲這兩種類型呈現嵌套表單,或者在用戶選擇類型時使用ajax添加它們。在HAML如下

示例形式。 'resource_fields'是一個html id。

= form_for @user ... 
    = #user specific fields go here 
    = #show dropdown to select type and send ajax with type to render type specific form. 
    - if @user.resource.nil? #if resource is not set 
    #resource_fields 
    - else #if resource is present 
    = render 'users/doctor_form', f: f if @user.resource.is_a? Doctor 
    = render 'users/nurse_form', f: f if @user.resource.is_a? Nurse 

控制器的方法來響應AJAX類型形式

def get_type_form 
    @user = User.new 
    @user.resource = case params[:selected_type] 
          when "Doctor" 
          Doctor.new 
          when 'Nurse' 
          Nurse.new 
          end 
end 

和get_form_type.js。HAML

:plain 
- if @user.resource.is_a? Doctor 
    $('#resource_fields').replaceWith("#{escape_javascript(render partial: 'users/doctor_form', locals: { f: nil })}"); 
- if @user.resource.is_a? Nurse 
    $('#resource_fields').replaceWith("#{escape_javascript(render partial: 'users/nurse_form', locals: { f: nil })}"); 

和部分爲doctor_form將作爲

#resource_fields 
- if f.nil? 
    = fields_for "user[resource_attributes]", @user.resource do |doctor| 
    = render 'users/doctor_fields', :doctor: doctor 
- if f 
    = f.fields_for :resource, @user.resource do |doctor| 
    = render 'users/doctor_fields', doctor: doctor 

和部分爲doctor_fields將作爲

= doctor.text_field :degree 
= doctor.text_field :specialization 

我有一個類似的功能和我使用上述方式實現。

+0

太棒了,我會檢查這一點......我注意到你刪除了委託/驗證,並移動了「accept_nested_attributes_for」這個資源。如果你不介意我問,爲什麼這比舊的代碼更好? –

+0

這將改變預期的行爲。在這個問題中,由於驗證,醫生或護士不能獨立於用戶存在。但這與刪除這些驗證實際上是一樣的,因爲現在醫生可以在沒有用戶的情況下存在。 –

+0

@MikeSlutsky我們可以在醫生和護士處添加驗證,以檢查用戶是否始終在場,並在用戶身上檢查資源是否始終存在。 –

相關問題