2014-05-24 56 views
1

我已經構建了相當複雜的表單,它創建了一個處方,其中包含許多實現。我用這句法鑑於:Rails 4無法以嵌套形式訪問哈希(未定義方法`[]'爲零:NilClass)

- provide(:title, 'Create prescription') 
%h1 Add medicines to prescription 
.row 
    .span6.offset3 
    = form_for @prescription do |f| 
     = render 'shared/error_prescription_messages' 
     %p 
     = f.hidden_field :patient_id, :value => params[:patient_id] 
     = f.hidden_field :user_id, :value => current_user.id 
     = f.fields_for :relations do |builder| 
     = render 'child_form', :f => builder 
     %p= f.submit "Submit" 

chlid_form很簡單:

- it=f.options[:child_index].to_i 
- n= it.to_s 

%h2 
    = "Medicine ##{it+1}" 

= f.hidden_field :medicine_id, :id => "my_medicine_id#{it}" 
- if params[:prescription].nil? || params[:prescription][:relations_attributes][n.to_sym][:medicine_name].nil? 
    = f.autocomplete_field :medicine_name, autocomplete_medicine_name_relations_path, :id_element => "#my_medicine_id#{it}" 
- else 
    = f.autocomplete_field :medicine_name, autocomplete_medicine_name_relations_path, :id_element => "#my_medicine_id#{it}", :value => params[:prescription][:relations_attributes][n.to_sym][:medicine_name] 

= f.label :amount, "Amount of medicine boxes" 
= f.number_field :amount, :value => 1 

= f.label :daily 
= f.number_field :daily, :value => 1 

= f.label :period_in_days, "Duration of treatment (in days)" 
= f.number_field :period_in_days, :value => 1 

所以你可以看到我使用f.options[:child_index]讓孩子的指標(0,1,2 .. )因爲我用這種特殊的形式生成多個項目。然後我把它變it併成功地用它在:id_element => "#my_medicine_id#{it}"這工作完全正常(創建my_medicine_id0,my_medicine_id1 ....)雖然沒有在這一行工作:

:value => params[:prescription][:relations_attributes][n.to_sym][:medicine_name]

其中n只是n=it.to_s

我雖然在控制器中有些錯誤,但如果我將此行更改爲任何 :value => params[:prescription][:relations_attributes]**[:'0']**[:medicine_name]或0到4之間的任何其他整數,一切都很好,但我需要在這一行中進行動態更改。所以我得到了證明,它工作,因爲它在這裏生成整數罰款"#my_medicine_id#{it}",但不會在哈希工作!當我從PARAMS打印整個哈希我得到這個:

{"patient_id"=>"7", "user_id"=>"1", "relations_attributes"=>{"0"=>{"medicine_id"=>"13490", "medicine_name"=>"Locacid 500 mcg/g (0,05%) (1 tuba 30 g)", "amount"=>"0", "daily"=>"1", "period_in_days"=>"1"}, "1"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}, "2"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}, "3"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}, "4"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}}}

所以要得到我需要它是很明顯, params[:prescription][:relations_attributes][SOME_KIND_OF_INETEGER][:medicine_name]應該工作的值,但不會。

控制器代碼:

class PrescriptionsController < ApplicationController 
before_action :signed_in_user 
before_action :doctor_user,  only: [:new, :create] 
before_action :pharmacist_user, only: [:update] 

def new 
    @prescription =Prescription.new 
    5.times { @prescription.relations.build } 
end 

def create 
    @prescription = Prescription.new(new_prescription_params) 
    if @prescription.save 
     flash[:success] = "Prescription created." 
     redirect_to @prescription 
else 
    5.times { @prescription.relations.build } 
     render 'new', :prescription => params[:prescription] 
    end 
end 

def show 
    @prescription = Prescription.find(params[:id]) 
    @medicines = @prescription.medicines.paginate(page: params[:page], :per_page => 10) 
end 

def update 
    @prescription = Prescription.find(params[:id]) 
    @patient = Patient.find(params[:patient_id]) 

    if !prescription_expired?(@prescription) 
     @prescription.realized = 1 
     if @prescription.save 
      flash[:success] = "Prescription realized." 
      redirect_to @patient 
     else 
      redirect_to root_url 
     end 
    else 
      flash[:notice] = "Can't realize, prescription expired." 
      redirect_to @patient 
    end 
end 

private 

    def new_prescription_params 
     params.require(:prescription). 
     permit(:patient_id, :user_id, relations_attributes: [:medicine_id, :medicine_name, :amount, :daily, :period_in_days]) 
    end 

    def doctor_user 
     redirect_to(root_url) unless current_user.function == "doctor" 
    end 

    def pharmacist_user 
     redirect_to(root_url) unless current_user.function == "pharmacist" 
    end 

    def prescription_expired?(presc) 
     presc.created_at < 1.month.ago 
    end 

    def signed_in_user 
     unless signed_in? 
      store_location 
      flash[:notice] = "Please log in." 
      redirect_to login_url 
     end 
    end 

我江郎才盡了,所以我問你們,如果有人可以提供幫助。謝謝。

+1

這似乎不是通過rails的方式來做到這一點。爲什麼要將表單元素與模型綁定,然後重寫此屬性值?這應該在控制器中完成。請用控制器代碼更新您的問題,以便我們清理它。 – BroiSatse

+1

我不知道你爲什麼要做'[n.to_sym]'...我會認爲'[n]'會起作用,不是嗎?它不是散列轉儲中的符號。 – SteveTurczyn

+0

不要寫任何個人信息。閱讀聲稱自己感到沮喪的人是令人沮喪的。這與這個問題無關。通常,初學者會寫出類似「奇怪/奇怪的行爲」的字眼,但在大多數情況下,語言/框架沒有什麼奇怪或奇怪的,最有可能的是那些聲稱這很奇怪的人的想法。 – sawa

回答

2

在您的視圖中使用params毫無意義,因爲您已將這些分配給您的模型。另外當你渲染你的新動作時,這些參數並不存在,因爲還沒有任何東西被髮送到服務器。只需從輸入中刪除所有values即可。

你的部分應該是這樣的:

- it=f.options[:child_index].to_i 
- n= it.to_s 

%h2 
    = "Medicine ##{it+1}" 

= f.hidden_field :medicine_id, :id => "my_medicine_id#{it}" 
= f.autocomplete_field :medicine_name, autocomplete_medicine_name_relations_path 

= f.label :amount, "Amount of medicine boxes" 
= f.number_field :amount 

= f.label :daily 
= f.number_field :daily 

= f.label :period_in_days, "Duration of treatment (in days)" 
= f.number_field :period_in_days 

如果你希望你的字段有默認值,你的數據庫中設置的默認值。

+1

@Herwish - 默認值是一個明確的模型,而不是控制器,並且絕對不是視圖。 TBH,我從來沒有發現任何價值參數的使用。正如我在答案中提到的那樣,在數據庫列上設置一個默認值或者在模型中添加'after_initialize'鉤子。 – BroiSatse

+1

而不是'@prescription = Prescription.new'做'@prescription = patient.find(parms [:patient_id])。prescriptions.build' – BroiSatse

+1

@Herwish - 在那裏擺脫'values'。做@prescription = patient.find(parms [:patient_id])。prescriptions.build(user_id:current_user)' – BroiSatse

相關問題