2013-04-10 37 views
111

Tôi mới tham gia ROR nhưng đã quyết định tôi cũng có thể tìm hiểu về 4. Điều này có thể hoặc không có ý kiến ​​hay. Tôi đang cố gắng để tạo ra một hình thức bằng cách sử dụng thuộc tính lồng nhau và tôi đang đấu tranh.Rails 4 Các thuộc tính lồng nhau Các tham số chưa được đính kèm

Tôi đã xem xét đường ray này http://railscasts.com/episodes/196-nested-model-form-part-1 và tôi đang cố gắng tạo lại một tình huống tương tự trên của riêng tôi.

Tôi có một đối tượng Bill có nhiều đối tượng Do. Đối tượng Do cũng thuộc về một số Person. Tôi muốn một hình thức mà tôi có thể tạo ra Bill và các con của nó Dues tất cả trong một trang.

Các trường phù hợp được hiển thị trên trang (mặc dù chưa có trình đơn thả xuống cho Người) và gửi thành công. Tuy nhiên, không ai trong số các dues trẻ em được lưu vào cơ sở dữ liệu và lỗi được ném trong nhật ký máy chủ:

Unpermitted parameters: dues_attributes

Có sự một số loại thay đổi trong Rails 4, hay tôi chỉ còn thiếu một cái gì đó hoàn toàn.

Ngay trước khi lỗi, nhật ký hiển thị này:

Started POST "/bills" for 127.0.0.1 at 2013-04-10 00:16:37 -0700 
Processing by BillsController#create as HTML<br> 
Parameters: {"utf8"=>"✓", 
"authenticity_token"=>"ipxBOLOjx68fwvfmsMG3FecV/q/hPqUHsluBCPN2BeU=", 
"bill"=>{"company"=>"Comcast", "month"=>"April ", 
"year"=>"2013", "dues_attributes"=>{ 
"0"=>{"amount"=>"30", "person_id"=>"1"}, 
"1"=>{"amount"=>"30", "person_id"=>"2"}, 
"2"=>{"amount"=>"30", "person_id"=>"3"}}}, "commit"=>"Create Bill"} 



mã có liên quan được liệt kê dưới đây

due.rb

class Due < ActiveRecord::Base 
    belongs_to :person 
    belongs_to :bill 
end 


bill.rb

class Bill < ActiveRecord::Base 
    has_many :dues, :dependent => :destroy 
    accepts_nested_attributes_for :dues, :allow_destroy => true 
end 


bills_controller.rb

# GET /bills/new 
    def new 
     @bill = Bill.new 
     3.times { @bill.dues.build } 
    end 


hóa đơn/_form.html.erb

<%= form_for(@bill) do |f| %> 
    <div class="field"> 
     <%= f.label :company %><br /> 
     <%= f.text_field :company %> 
    </div> 
    <div class="field"> 
     <%= f.label :month %><br /> 
     <%= f.text_field :month %> 
    </div> 
    <div class="field"> 
     <%= f.label :year %><br /> 
     <%= f.number_field :year %> 
    </div> 
    <div class="actions"> 
     <%= f.submit %> 
    </div> 
    <%= f.fields_for :dues do |builder| %> 
     <%= render 'due_fields', :f => builder %> 
    <% end %> 
    <% end %> 


hóa đơn /_due_fields.html.erb

<div> 
    <%= f.label :amount, "Amount" %>   
    <%= f.text_field :amount %> 
    <br> 
    <%= f.label :person_id, "Renter" %> 
    <%= f.text_field :person_id %> 
</div> 

UPDATE để bills_controller.rb: này hoạt động!

def bill_params 
    params.require(:bill).permit(:company, :month, :year, 
           dues_attributes: [:amount, 
                :person_id]) 
end 
+4

Fix trên định dạng: params.require (: hóa đơn).giấy phép (: công ty,: tháng,: năm,: dues_attributes => [: số tiền,: person_id]) –

Trả lời

163

Có vẻ có sự thay đổi trong việc xử lý bảo vệ thuộc tính và bây giờ bạn phải lập danh sách trắng params trong bộ điều khiển (thay vì attr_accessible trong mô hình) vì cựu strong_parameters ngọc tùy chọn trở thành một phần của Rails Core.

này nên tìm một cái gì đó như thế này:

class PeopleController < ActionController::Base 
    def create 
    Person.create(person_params) 
    end 

private 
    def person_params 
    params.require(:person).permit(:name, :age) 
    end 
end 

Vì vậy params.require(:model).permit(:fields) sẽ được sử dụng

và cho lồng nhau thuộc tính giống như

params.require(:person).permit(:name, :age, pets_attributes: [:id, :name, :category]) 

Một số chi tiết có thể được tìm thấy trong Ruby edge API docsstrong_parameters on github hoặc here

+1

Tôi đã thay đổi Bảng điều khiển của mình thành như sau: 'def bill_params params.require (: bill) .permit (: công ty,: tháng,: năm,: dues_attributes [: số tiền,: person_id]) end' Tôi hiện đang gặp phải lỗi này: ** không chuyển đổi biểu tượng ẩn thành số nguyên ** – jcanipar

+2

Vâng, nó giúp đặt đại tràng vào đúng nơi ... Đây chính xác là những gì cần phải làm. Cảm ơn @ thorsten-muller! – jcanipar

+81

KHÔNG QUÊN ID! 'pets_attributes: [: id,: name,: category]' Nếu không, khi bạn chỉnh sửa, mỗi thú cưng sẽ được tạo lại. – Arcolye

18

Từ tài liệu

To whitelist an entire hash of parameters, the permit! method can be used 

params.require(:log_entry).permit! 

Thuộc tính lồng nhau có dạng băm. Trong ứng dụng của tôi, tôi có một mô hình Question.rb chấp nhận các thuộc tính lồng nhau cho một mô hình Answer.rb (trong đó người dùng tạo ra các lựa chọn câu trả lời cho một câu hỏi mà anh ta tạo ra). Trong question_controller, tôi làm điều này

def question_params 

     params.require(:question).permit! 

    end 

Mọi thứ trong băm câu hỏi đều được phép, kể cả thuộc tính câu trả lời lồng nhau. Điều này cũng hoạt động nếu các thuộc tính lồng nhau ở dạng một mảng. Có nói rằng, tôi tự hỏi nếu có một mối quan tâm an ninh với phương pháp này bởi vì nó về cơ bản cho phép bất cứ điều gì bên trong băm mà không chỉ định chính xác nó là gì, mà có vẻ trái với mục đích của các thông số mạnh mẽ.

+0

Tuyệt vời, tôi không thể cho phép tham số một cách rõ ràng, điều này tiết kiệm cho tôi một số giờ. –

+2

Vâng, sử dụng .permit! thường được xem là mối quan tâm về bảo mật tiềm năng. Bạn chỉ thực sự muốn sử dụng nó nếu người dùng là một quản trị viên, nhưng ngay cả sau đó tôi sẽ cảnh giác với việc sử dụng nó. – 8bithero

+6

Thuộc tính lồng nhau của tôi cũng nằm trong một mảng. Có phải '.permit! 'Là lựa chọn duy nhất không? Tôi không thể làm cho nó hoạt động ngay cả với tất cả các thuộc tính của mô hình được phép vì nó chokes trên mảng. –

16

hoặc bạn chỉ có thể sử dụng

def question_params 

    params.require(:question).permit(team_ids: []) 

end 
+0

cảm ơn, tôi có thể cho phép các tham số chấp nhận mảng ngay bây giờ –

10

Trên thực tế có một cách để chỉ trắng-list tất cả các thông số lồng nhau.

params.require(:widget).permit(:name, :description).tap do |whitelisted| 
    whitelisted[:position] = params[:widget][:position] 
    whitelisted[:properties] = params[:widget][:properties] 
end 

Phương pháp này có lợi thế hơn các giải pháp khác. Nó cho phép cho phép tham số lồng sâu.

Trong khi các giải pháp khác như:

params.require(:person).permit(:name, :age, pets_attributes: [:id, :name, :category]) 

Đừng.


Nguồn:

https://github.com/rails/rails/issues/9454#issuecomment-14167664

3

Hôm nay tôi tình cờ gặp vấn đề này cùng, trong khi làm việc trên đường ray 4, tôi đã có thể để có được nó làm việc bằng cách cơ cấu lại fields_for tôi như:

<%= f.select :tag_ids, Tag.all.collect {|t| [t.name, t.id]}, {}, :multiple => true %> 

Sau đó, trong bộ điều khiển của tôi, tôi có thông số mạnh mẽ của tôi là:

private 
def post_params 
    params.require(:post).permit(:id, :title, :content, :publish, tag_ids: []) 
end 

Tất cả các công trình!

+0

hi cảm ơn bạn @KingsleyIjomah - điều gì sẽ xảy ra nếu bạn muốn danh sách trắng các thuộc tính cụ thể của trẻ em? – BKSpurgeon

1

Nếu bạn sử dụng một lĩnh vực JSONB, bạn phải chuyển nó sang JSON với .to_json (ROR)

Các vấn đề liên quan