加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby-on-rails – 使用带有accepts_nested_attributes_for的Rail

发布时间:2020-12-17 03:50:59 所属栏目:百科 来源:网络整理
导读:我正在编写一个名为Person的简单Rails模型has_many:phone_numbers,我试图以复杂的形式保存电话号码,而无需手动编写setter方法. accepts_nested_attributes_for应该做我想要的但是我无法让它工作.这是我到目前为止的代码: 移民 class CreatePeople ActiveRe
我正在编写一个名为Person的简单Rails模型has_many:phone_numbers,我试图以复杂的形式保存电话号码,而无需手动编写setter方法. accepts_nested_attributes_for应该做我想要的但是我无法让它工作.这是我到目前为止的代码:

移民

class CreatePeople < ActiveRecord::Migration
  def self.up
    create_table :people do |t|
      t.string :first_name
      t.string :last_name
      t.integer :address_id      
      t.string :email

      t.timestamps
    end
  end

  def self.down
    drop_table :people
  end
end

class CreatePhoneNumbers < ActiveRecord::Migration
  def self.up
    create_table :phone_numbers do |t|
      t.string :number,:limit => 10
      t.string :extension,:limit => 5
      t.string :description,:null => false
      t.integer :telephone_id
      t.string :telephone_type

      t.timestamps
    end
  end

  def self.down
    drop_table :phone_numbers
  end
end

楷模

class Person < ActiveRecord::Base
  has_one :address,:as => :addressable,:dependent => :destroy
  has_many :phone_numbers,:as => :telephone,:dependent => :destroy

  accepts_nested_attributes_for :phone_numbers

  attr_protected :id

  validates_presence_of :first_name,:last_name,:email
end

class PhoneNumber < ActiveRecord::Base
  attr_protected :id

  belongs_to :telephone,:polymorphic => true
end

视图

<% form_for @person,:builder => CustomFormBuilder do |f| %>
  <%= f.error_messages %>

  <%= f.text_field :first_name %>
  <%= f.text_field :last_name %>

  <% fields_for "person[address]",@person.address,:builder => CustomFormBuilder do |ff| %>  
    <%= ff.text_field :address_1 %>
    <%= ff.text_field :address_2 %>
    <%= ff.text_field :city %>
    <%= ff.text_field :state %>
    <%= ff.text_field :zip %>  
  <% end %>

  <h2>Phone Numbers</h2>
  <% @person.phone_numbers.each do |phone_number| %>
    <% fields_for "person[phone_numbers][]",phone_number,:builder => CustomFormBuilder do |ff| %>
      <%= ff.text_field :description %>
      <%= ff.text_field :number %>
      <%= ff.text_field :extension %>
    <% end %>
  <% end %>

  <%= f.text_field :email %>

  <%= f.submit 'Create' %>

<% end %>

调节器

def new
  @person = Person.new 
  @person.build_address
  @person.phone_numbers.build

  respond_to { |format| format.html }
end

def create
  @person = Person.new(params[:person])

  respond_to do |format|
    if @person.save
      flash[:notice] = "#{@person.name} was successfully created."
      format.html { redirect_to(@person) }
    else
      format.html { render :action => 'new' }
    end
  end
end

我已经验证正在创建phone_numbers =方法,但该帖子仍会导致:

PhoneNumber(#69088460) expected,got HashWithIndifferentAccess(#32603050)

RAILS_ROOT: H:/projects/test_project

C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/associations/association_proxy.rb:263:in `raise_on_type_mismatch'
C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/associations/association_collection.rb:319:in `replace'
C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/associations/association_collection.rb:319:in `each'
C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/associations/association_collection.rb:319:in `replace'
C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/associations.rb:1290:in `phone_numbers='
C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/base.rb:2740:in `send'
C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/base.rb:2740:in `attributes='
C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/base.rb:2736:in `each'
C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/base.rb:2736:in `attributes='
C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/base.rb:2434:in `initialize'
H:/projects/salesguide/app/controllers/accounts_controller.rb:46:in `new'
H:/projects/test_project/app/controllers/accounts_controller.rb:46:in `create'

我可以通过手动编写phone_numbers =方法来实现这一点,但这会导致巨大的重复工作,我更愿意学习如何做到这一点.谁能看到我做错了什么?

解决方法

您忘记将fields_for称为人员表单上的方法.否则,您实际上并未在accept_nested_attributes_for上下文中使用fields_for.迈克尔的解决方案试图欺骗Rails将提交视为正确定义的accepts_nested_attributes_for表单.

您尝试执行的操作的正确语法是:

parent_form_object.fields_for id,object_containing_values,{form_for options},&block

如果您提供符号作为id,您将发现代码看起来更简洁,更简单,包含Person模型中定义的子模型的关联名称.

此外,如果@ person.phone_numbers为空,您正在使用的每个块可能会导致问题.您可以确保至少有一组电话号码字段,其中的行与我使用的行类似

<% @phs = @person.phone_numbers.empty? ? @person.phone_numbers.build : @person.phone_numbers %>

通过所有更正,此代码将按您的要求执行.

视图

<% form_for @person,:builder => CustomFormBuilder do |f| %>
  <%= f.error_messages %>

  <%= f.text_field :first_name %>
  <%= f.text_field :last_name %>

  <% f.fields_for :address,:builder => CustomFormBuilder do |address_form| %>  
    <%= address_form.text_field :address_1 %>
    <%= address_form.text_field :address_2 %>
    <%= address_form.text_field :city %>
    <%= address_form.text_field :state %>
    <%= address_form.text_field :zip %>  
  <% end %>

  <h2>Phone Numbers</h2>
    <% @phs = @person.phone_numbers.empty? ? @person.phone_numbers.build : @person.phone_numbers %>
    <% f.fields_for :phone_numbers,@phs,:builder => CustomFormBuilder do |phone_number_form| %>
      <%= phone_number_form.text_field :description %>
      <%= phone_number_form.text_field :number %>
      <%= phone_number_form.text_field :extension %>
    <% end %>

  <%= f.text_field :email %>

  <%= f.submit 'Create' %>

<% end %>

您可能会发现查看complex-form-examples repository on github的工作示例很有用.它还附带了代码,可以从视图/表单中为:has_many关系动态添加新条目.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读