2014-04-10 18 views
5

Tôi đang cố chỉnh sửa/cập nhật bản ghi mô hình bằng simple_form, nhưng biểu mẫu sẽ không trực tiếp thay đổi trường mô hình. Thay vào đó, tôi cung cấp một vài trường check_box_tag cho biết cập nhật những trường nào cần thay đổi. Do đó, cập nhật không nhận được một tham số [: device] băm mà tôi có thể sử dụng để cập nhật các thuộc tính. Tôi đang cố gắng để tạo ra băm này, nhưng tôi nhận được ForbiddenAttributesError khi tôi phát hành @ device.update_attributes (params [: device]).ActiveModel :: ForbiddenAttributesError sử dụng update_attributes đã tạo tham số băm bản thân mình

Tôi tin rằng danh sách tham số mạnh của tôi là chính xác. Nếu tôi cho phép một trường mô hình (tên) được xử lý trong chế độ xem chỉnh sửa, tôi nhận được các tham số được mong đợi [: device] và mọi thứ hoạt động. Nếu tôi vô hiệu hóa trường đó, bởi vì tôi không muốn nó bị thay đổi, thì tôi cần phải tự tạo bản băm đó và tôi nhận được lỗi. Khi tôi nhìn vào băm tôi tạo ra, nó trông với tôi tương đương với cái băm được xem. Tôi không hiểu tại sao nó thất bại.

Môi trường là Ruby 2.0.0, Rails 4.1 trên Windows 8.1 với RubyMine 6.3.

Các hình thức là: < ... cần định dạng đúng một lần làm việc ...>

<%= simple_form_for @device do |f| %> 
     <legend><%= controller.action_name.capitalize %> Device:</legend> 
     <%= f.input :name, disabled: true %> 
     <%= check_box_tag(:is_admin, 0, @device.admin?) %> 
     <%= label_tag(:is_admin, "Make admin?") %> 
     <%= check_box_tag(:chg_pwd) %> 
     <%= label_tag(:chg_pwd, "Change password?") %> 
     <%= f.button :submit %> 
<% end %> 

Các params [: thiết bị] mà tôi nhận được khi tôi đã gửi f.input: tên, khuyết tật: false và cho phép chế độ xem tạo tham số [: device] là:

ActionController::Parameters (3 element(s)) 
"{"name"=>"D105", "password"=>"D105Dvgr", "password_confirmation"=>"D105Dvgr"}" 

Và, mọi thứ đều hoạt động.

Các params [: thiết bị] mà tôi tạo ra là:

ActionController::Parameters (3 element(s)) 
"{"name"=>"D106", "password"=>"D106VdAd", "password_confirmation"=>"D106VdAd"}" 

Và, tôi nhận Forbidden Thuộc tính Lỗi, mặc dù tôi thấy không có sự khác biệt giữa hai người.

Bản cập nhật là: < ... Mã cần refactored, một khi nó được làm việc ...>

class DevicesController < ApplicationController 
    before_filter :authenticate_device! 

... other methods removed here ... 

    def edit 
    @device = Device.find(params[:id]) 
    # my_page = render_to_string controller: 'devices', action: 'edit', layout: "application" 
    end 

    def update 
    authorize! :update, @device, :message => 'Not authorized as an administrator.' 
    @device = Device.find(params[:id]) 
    pwd_msg = "" 
    if params[:chg_pwd] 
     pwd_gen = @device.device + SecureRandom.urlsafe_base64(15).tr('lIO0=_\-', 'sxyzEUM').first(4) 
     params[:device] = {name: @device.name} if params[:device].nil? 
     params[:device][:password] = pwd_gen 
     params[:device][:password_confirmation] = pwd_gen 
     pwd_msg = ", new password is #{pwd_gen}" 
    end 
    if @device.update_attributes(params[:device]) 
     params[:is_admin] ? @device.add_role(:admin) : @device.remove_role(:admin) 
     flash[:notice] = ["Device updated" + pwd_msg] 
     redirect_to devices_path 
    else 
     @device.errors.messages.each do |key, value| 
     flash[:alert] = ["Unable to update device"] 
     @device.errors.messages.each do |key, value| 
      flash[:alert] << key.to_s.capitalize + " " + value[0] 
     end 
     end 
     redirect_to devices_path 
    end 
    end 

    private 

    def device_params 
    params.require(:device).permit(:device, :name, :email, :password, :password_confirmation, :encrypted_password, :salt, :role_ids, :is_admin, :chg_pwd) # TODO minimize when update is working 
    end 

end 

mô hình

là:

class Device < ActiveRecord::Base 

    rolify 
    devise :database_authenticatable, :rememberable, :trackable, :validatable 

    validates :device, 
      presence: true, 
      length: {minimum: 4 }, 
      uniqueness: {case_sensitive: false } 
    validates :name, 
      presence: true 

    def remember_me 
    true unless self.admin? 
    end 

    def admin 
    self.add_role :admin 
    end 

    def not_admin 
    self.remove_role :admin 
    end 

    def admin? 
    self.has_role? :admin 
    end 
    def device? 
    self.has_role? :device 
    end 
    def vip? 
    self.has_role? :vip 
    end 

    def login=(login) 
    @login = login 
    end 
    def login 
    @login || self.device || self.email 
    end 

    def self.find_first_by_auth_conditions(warden_conditions) 
    conditions = warden_conditions.dup 
    if login = conditions.delete(:login) # Note one equal sign. Strange but true. 
     where(conditions).where(["lower(device) = :value OR lower(email) = :value", { :value => login.downcase }]).first 
    else 
     where(conditions).first 
    end 
    end 

end 

THÔNG TIN MỚI: Tôi lơ là cung cấp thông tin Tôi có trong ApplicationController. sửa chữa này từ Anton Trapp xử lý các thông số mạnh mẽ đối với đá quý mà chưa được đầy đủ Rails 4 tương thích:

before_filter do 
    resource = controller_name.singularize.to_sym 
    method = "#{resource}_params" 
    params[resource] &&= send(method) if respond_to?(method, true) 
    end 

Tôi đã tìm thấy rằng việc sử dụng các giải pháp đề xuất của:

@device.update_attributes(device_params) 

không hoạt động nếu một mô hình trường được cập nhật. Kết quả là "param not found: device". Nó hoạt động nếu không có trường mô hình nào được cập nhật. Vì vậy, toàn bộ vấn đề đặt ra câu hỏi về những gì thực sự sai.

Trả lời

1

Việc sửa chữa là để thêm các lĩnh vực như attr_accessor với mô hình, nhưng không phải cơ sở dữ liệu, để nó có thể được sử dụng đúng trong biểu mẫu.

attr_accessor :is_admin, :chg_pwd 

Và sau đó sửa đổi nhằm mục đích:

<%= simple_form_for @device do |f| %> 
    <legend><%= controller.action_name.capitalize %> Device:</legend> 
    <%= f.input :name, disabled: true %> 
    <%= f.input :is_admin, as: :boolean, checked_value: true, unchecked_value: false %> 
    <%= f.input :chg_pwd, as: :boolean, checked_value: true, unchecked_value: false %> 
    <%= f.button :submit %> 
<% end %> 

Sau đó, do các mã ứng dụng điều khiển từ Anton Trapp:

before_filter do 
    resource = controller_name.singularize.to_sym 
    method = "#{resource}_params" 
    params[resource] &&= send(method) if respond_to?(method, true) 
    end 

tôi đã có thể cập nhật các trường trong điều khiển thiết bị như sau:

@device.update_attributes(params[:device]) 
3

Trong DevicesController#update hành động, thay đổi

@device.update_attributes(params[:device]) 

Để

@device.update_attributes(device_params) 

Như bạn đang sử dụng Rails 4.1, bạn cần phải lập danh sách trắng các thuộc tính mà bạn muốn được chèn/cập nhật trong cơ sở dữ liệu.Như bạn thông qua các thuộc tính trực tiếp đến update_attributes phương pháp không cho phép chúng bạn nhận ActiveModel::ForbiddenAttributesError

CẬP NHẬT

Để giải quyết param not found: device:

def device_params 
    if params[:device] 
     params.require(:device).permit(:device, :name, :email, :password, :password_confirmation, :encrypted_password, :salt, :role_ids, :is_admin, :chg_pwd) # TODO minimize when update is working 
    end 
    end 
+0

Được rồi, thay đổi này có ý nghĩa tổng thể và hoạt động. Tôi vẫn tự hỏi, mặc dù, tại sao nó làm việc theo cách nó là khi một lĩnh vực mô hình đã được tham gia? Bạn có biết rằng? Cảm ơn ... –

+0

'tại sao nó làm việc theo cách nó là khi một lĩnh vực mô hình đã được tham gia?' Có nghĩa là? Trường mô hình nào? Bạn có nghĩa là mã này làm việc trong mọi trường hợp? –

+0

Trong chế độ xem chỉnh sửa, nếu tôi sử dụng "f.input: name, disabled: false", thì thông số [: device] được gửi đến hành động cập nhật với thông số [: davice] [: name] được đặt. Trong trường hợp đó, hành động cập nhật hoạt động như tôi đã làm. Nếu, thay vào đó, tôi sử dụng "f.input: name, disabled: true", để trường name không thể thay đổi, hơn params [: device] là nil. Để update_attributes, tôi đã xây dựng params [: device] như được hiển thị. Cả hai băm đều tương đương nhau. Nhưng, tôi đã nhận được ForbiddenAttributeError trên băm tôi đã xây dựng mặc dù cái mà khung nhìn sửa được xây dựng cho tôi làm việc bằng cách sử dụng @ device.update_attributes (params [: device]). –

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