【问题标题】:Rails 4 simple_form params not being saved to databaseRails 4 simple_form 参数未保存到数据库
【发布时间】:2014-08-17 07:09:31
【问题描述】:

作为 RoR 的新手,我正在创建一个允许客户在线填写大型表格的网站。该表单包含一些嵌套模型,但我的问题是客户端未在表单提交时保存到数据库中。

从我的服务器看来,params 似乎正在获取客户端信息,但是当 sql 操作启动时,它不会将任何信息插入数据库。虽然它说它提交了事务,但我在 rails 控制台中的客户端具有所有 nil 属性。

    Started POST "/clients" for 192.168.1.114 at 2014-08-16 23:40:14 -0700
Processing by ClientsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"2tPnVc7Aj5mMdd9ZnXVuFHHs3CprND6QZ8qyCxSC674=", "client"=>{"name"=>"Jon", "birthdate"=>"August 2 1990", "has_guardian"=>"0", "guardian"=>{"name"=>"", "phone_number"=>"", "relationship"=>"", "address"=>"", "birthdate"=>""}, "gender"=>"male", "relationship"=>"single", "address"=>"25 Oak Road, LA, CA, 90003", "home_phone"=>"3105636778", "home_phone_manner"=>"leave_message_with_info", "preferred_home_phone"=>"false", "confidential_home_phone"=>"false", "cell_work_phone"=>"3104556721", "cell_work_phone_manner"=>"leave_message_with_info", "preferred_cell_work_phone"=>"true", "confidential_cell_work_phone"=>"true", "email"=>"jon@gmail.com", "confidential_email"=>"true", "written_communication"=>"use_email", "family_contact"=>{"name"=>"Lily Mod", "phone_number"=>"3109776663"}, "additional_info"=>"Test", "created_at(1i)"=>"2014", "created_at(2i)"=>"8", "created_at(3i)"=>"17", "employer"=>"Polly", "occupation"=>"Sales", "prescriptions"=>"None", "medicines"=>"None", "allergies"=>"None", "conditions"=>"None"}, "commit"=>"Create Client"}
    Unpermitted parameters: has_guardian, guardian, family_contact, created_at(1i),       created_at(2i), created_at(3i)
  (0.1ms)  begin transaction
  SQL (0.4ms)  INSERT INTO "clients" ("additional_info", "created_at", "updated_at")          VALUES   (?, ?, ?)  [["additional_info", "Test"], ["created_at", Sun, 17 Aug 2014 06:40:14 UTC  +00:00], ["updated_at", Sun, 17 Aug 2014 06:40:14 UTC +00:00]]
  (0.6ms)  commit transaction
 Redirected to http://192.168.1.114:3000/
 Completed 302 Found in 59ms (ActiveRecord: 1.5ms)

当我在我的 clients#create 内部窥探时,它会在 @client 处显示所有 nil 属性,但是当我在 @client 上调用 name 之类的方法时,它会返回参数中的值。

26:   def create
27:     @client = Client.new(client_params)
=> 28: binding.pry
29:     respond_to do |format|
30:       if @client.save
31:         format.html { redirect_to root_path, notice: 'Client was successfully created.' }
32:         format.json { render controller: :static_pages, action: 'home', status: :created, location: root_path }
33:       else
34:         format.html { render action: 'new' }
35:         format.json { render json: @client.errors, status: :unprocessable_entity }
36:       end
37:     end
38:   end

[1] pry(#<ClientsController>)> @client
=> #<Client id: nil, name: nil, email: nil, home_phone: nil, home_phone_manner: nil, cell_work_phone: nil, cell_work_phone_manner: nil, written_communication: nil, confidential_email: nil, additional_info: "test", birthdate: nil, gender: nil, relationship: nil, employer: nil, occupation: nil, medicines: nil, allergies: nil, conditions: nil, created_at: nil, updated_at: nil, preferred_home_phone: nil, confidential_home_phone: nil, preferred_cell_work_phone: nil, confidential_cell_work_phone: nil, prescriptions: nil, address: nil>
[2] pry(#<ClientsController>)> @client.name
=> "Jon"

我的相关客户控制器:

 def new
   @client = Client.new
 end

 def create
   @client = Client.new(client_params)

   respond_to do |format|
     if @client.save
       format.html { redirect_to root_path, notice: 'Client was successfully created.' }
       format.json { render controller: :static_pages, action: 'home', status: :created,     location: root_path }
     else
       format.html { render action: 'new' }
       format.json { render json: @client.errors, status: :unprocessable_entity }
     end
   end
 end
 def client_params
   params.require(:client).permit(:name, :email, :address, :home_phone, :home_phone_manner,
                                 :cell_work_phone, :cell_work_phone_manner,
                                 :written_communication, :confidential_email,
                                 :additional_info, :birthdate, :gender, :relationship,
                                 :prescriptions, :employer, :occupation, :medicines,
                                 :allergies, :conditions, :preferred_home_phone,
                                 :confidential_home_phone, :preferred_cell_work_phone,
                                 :confidential_cell_work_phone)
 end

我的路线文件:

  match '/contact', to: 'static_pages#contact', via: :get
  match '/about', to: 'static_pages#about', via: :get
  match '/contact', to: 'static_pages#about', via: :get

  match '/forms', to: 'clients#new', via: [:get, :post]

  resources :clients
  resources :family_contacts
  resources :guardians

我的客户模型,我意识到我还没有完成所有让关联工作的事情,但我现在只关心保存一个客户:

  class Client < ActiveRecord::Base

    has_one :guardian

    has_many :family_contacts

    accepts_nested_attributes_for :family_contacts
    accepts_nested_attributes_for :guardian

    attr_accessor :name, :email, :birthdate, :gender, :address
    attr_accessor :home_phone, :home_phone_manner, :confidential_home_phone, :preferred_home_phone
    attr_accessor :cell_work_phone, :cell_work_phone_manner, :confidential_cell_work_phone, :preferred_cell_work_phone
    attr_accessor :written_communication, :confidential_email
    attr_accessor :relationship, :employer, :occupation
    attr_accessor :prescriptions, :medicines, :allergies, :conditions

    def has_guardian?
      self.guardian.present?
    end

 end

我的表单很长,但我试图通过去掉很多样式和标签来简化它:

    <%= simple_form_for(@client, defaults: { required: false }, html: { class: 'form-inline' }) do |f| %>

    <%= f.input :name, label: "Patient's Name:", placeholder: "First & Last" %>

    <%= f.input :birthdate, label: "Birthdate:", placeholder: "January 1 2000" %>

    <%= f.input :has_guardian?, label: "Are you under the age of 18?", as: :boolean %>

      <%= f.simple_fields_for Guardian.new do |g| %>
        <%= g.input :name, label: "Name of Gaurdian", placeholder: "First & Last" %>
        <%= g.input :phone_number, label: "Phone # of Guardian", as: :tel %>
        <%= g.input :relationship, label: "Relationship to Patient" %>
        <%= g.input :address, label: "Guardian's Address" %>
      <% end %>

    <%= f.collection_radio_buttons :gender, [['male', 'Male'], ['female', 'Female']], :first, :last %>

    <%= f.collection_radio_buttons :relationship, [['single', 'Single'], ['married', 'Married'], ['widowed', 'Widowed'], ['seperated', 'Seperated'], ['domestic_relationship', 'Domestic Relationship']], :first, :last %>

    <%= f.input :address, lable: "Home Address:", placeholder: '25 Oak Road, Los Angeles, CA, 90003' %>

    <%= f.input :home_phone, label: "Home Phone #", as: :tel %>

    <%= f.collection_radio_buttons :home_phone_manner, [['leave_message_with_info', 'Leave message with detailed information.'], ['leave_message_with_callback', 'Leave message with call-back number only.']], :first, :last %>

    <%= f.collection_radio_buttons :preferred_home_phone, [[true, 'Yes'], [false, 'No']], :first, :last %>

    <%= f.collection_radio_buttons :confidential_home_phone, [[true, 'Yes'], [false, 'No']], :first, :last %>

    <%= f.input :cell_work_phone, label: "Cell/Work Phone #", as: :tel %>

    <%= f.collection_radio_buttons :cell_work_phone_manner, [['leave_message_with_info', 'Leave message with detailed information.'], ['leave_message_with_callback', 'Leave message with call-back number only.']], :first, :last %>

    <%= f.collection_radio_buttons :preferred_cell_work_phone, [[true, 'Yes'], [false, 'No']], :first, :last %>

    <%= f.collection_radio_buttons :confidential_cell_work_phone, [[true, 'Yes'], [false, 'No']], :first, :last %>

    <%= f.input :email, label: "Email:", as: :email %>

    <%= f.collection_radio_buttons :confidential_email, [[true, 'Yes'], [false, 'No']], :first, :last %>

    <%= f.collection_radio_buttons :written_communication, [['mail_home', 'Mail to my home address (above).'], ['mail_work', 'Mail to my work address.'], ['fax_to_home', 'Fax to me home phone (above).'], ['use_email', 'Email me to the above email address.']], :first, :last %>

  <%= f.simple_fields_for FamilyContact.new do |c| %>

      <%= c.input :name, label: "Name:", placeholder: "First & Last" %>

      <%= c.input :phone_number, label: "Phone #", as: :tel %>

      <%= c.input :name, label: "Name:", placeholder: "First & Last" %>

      <%= c.input :phone_number, label: "Phone #", as: :tel %>

  <% end %>

  <%= f.input :additional_info, label: "Additional Information:", as: :text %>

    <%= f.input :created_at, label: "Date", as: :date %>

    <%= f.input :employer, label: "Employer:" %>

    <%= f.input :occupation, label: "Occupation:" %>

    <%= f.input :prescriptions, label: "Current Prescription Medications:" %>

    <%= f.input :medicines, label: "Over the Counter Medications:" %>

    <%= f.input :allergies, label: "Allergies to Medications" %>

    <%= f.input :conditions, label: "Other Medical Conidtions" %>

    <%= f.input :created_at, label: "Date", as: :date %>

  <%= f.simple_fields_for Guardian.new do |g| %>
    <%= g.input :name, label: "Name of Gaurdian", placeholder: "First & Last" %>
    <%= g.input :birthdate, label: "Birthdate of Guardian", placeholder: "January 1 2000" %>
  <% end %>

  <%= f.input :name, label: "Patient's Name:", placeholder: "First & Last" %>
  <%= f.input :birthdate, label: "Birthdate:", placeholder: "January 1 2000" %>

  <%= f.submit %>

对于文件的长度感到抱歉,但我非常感谢任何帮助。谢谢

【问题讨论】:

标签: ruby-on-rails simple-form


【解决方案1】:

这是错误:

不允许的参数:has_guardian、guardian、family_contact、 created_at(1i), created_at(2i), created_at(3i)

虽然上面的错误是针对strong_params,但我认为这是我们需要解决的更深层次的问题。由于您是新手,让我详细说明这对您有什么作用...


属性

您拥有的模型中大量填充了attr_accessorattr_accessor 是一种在 Ruby / Rails 中创建“虚拟属性”的方法,因为它定义了一个 custom getter and setter method,它本质上将定义在系统上使用的“属性”

您遇到的问题是attr_accessor,用最简单的术语来说,不允许您将数据保存在数据库中。这将是您遇到的更大问题之一 - 您需要摆脱任何覆盖您的数据库属性的attr_accessors

这里演示了:

插入“客户”(“additional_info”、“created_at”、“updated_at”) 值 (?, ?, ?) [["additional_info", "Test"], ["created_at", Sun, 2014 年 8 月 17 日 06:40:14 UTC +00:00],[“updated_at”,2014 年 8 月 17 日星期日 06:40:14 UTC +00:00]]

这基本上表明只有additional_infocreated_atupdated_at 正在填充数据库。

您应该从 Client 模型中删除 attr_accessor 方法:

#app/models/client.rb
class Client < ActiveRecord::Base

    has_one :guardian

    has_many :family_contacts

    accepts_nested_attributes_for :family_contacts
    accepts_nested_attributes_for :guardian

end

未经许可

未经许可的参数问题主要是由于您在强参数散列中不允许使用这些参数。您需要在此处添加它们:

#app/controllers/clients_controller.rb
Class ClientsController < ApplicationController
   private

   def client_params
      params.require(:client).permit(..., :has_guardian, :guardian, :family_contact, :created_at(1i), :created_at(2i), :created_at(3i))
   end
end

尽管情况确实如此,但我觉得您尝试传递的属性数量存在很大问题。这并不违反惯例或任何东西,但验证每次提交的所有这些属性肯定会导致问题?

我会说它的unworkable - 你最好将它拆分成可管理的关联模型/对象,不过我会让你自己解决

【讨论】:

  • 感谢您的回答,我有一种预感,属性的数量有点多,不确定使用 attr_accessor 是否是处理所有属性的正确方法。我肯定会考虑将这些属性拆分为更多模型。再次感谢
  • @jjasonn:如果此错误解决了您的问题,请考虑将其标记为已接受的答案。这可能会帮助未来的访问者,将其排除在未答复的队列之外,并为您和 Rich 提升声誉。
猜你喜欢
  • 2018-01-15
  • 2014-08-07
  • 2016-04-28
  • 1970-01-01
  • 1970-01-01
  • 2016-11-18
  • 1970-01-01
  • 1970-01-01
  • 2016-01-15
相关资源
最近更新 更多