下面的代码显示了Rails 4,cocoon gem和simple_form的以下设置。基本上,我在数据库中有很多客户端,我想通过选择下拉列表(通过电子邮件选择)将现有客户与发票相关联。当我通过电子邮件选择现有客户端时,会发生创建具有相同电子邮件的新客户端。此新客户端不与任何用户关联。为什么会这样?
编辑:我想我可能已经设置好了,以便客户端每http://requiremind.com/differences-between-has-one-and-belongs-to-in-ruby-on-rails/只能有一张发票,但仍应允许更新客户端子对象。
模型设置
class Invoice<的ActiveRecord ::基
belongs_to :user
has_one :client
has_many :invoice_items, dependent: :destroy
accepts_nested_attributes_for :invoice_items, allow_destroy: true
accepts_nested_attributes_for :client
end
class Client < ActiveRecord::Base
belongs_to :user
belongs_to :invoice
end
class User < ActiveRecord::Base
has_many :clients, dependent: :destroy
has_many :invoices, dependent: :destroy
end
_形成部分以通过编辑/更新
进行调用= simple_form_for [current_user, @invoice], html: { class: 'form-horizontal' } do |f|
- if @invoice.errors.any?
#error_explanation
%h2= "#{pluralize(@invoice.errors.count, "error")} prohibited this invoice from being saved:"
%ul
- @invoice.errors.full_messages.each do |msg|
%li= msg
.form-group
= f.label :paid, "Paid?"
= f.input_field :paid
%br/
%h3 Client
/ = f.simple_fields_for :client, Client.new do |client|
= f.simple_fields_for :client, Client.new do |client|
= client.select :email, Client.all.map { |c| [c.email, c.email, { class: c.user.id }] }, include_blank: true
= link_to "New Client", new_user_client_path(current_user)
%h3 Invoice Items
= f.simple_fields_for :invoice_items do |invoice_item|
= render 'invoice_item_fields', :f => invoice_item
.links.form-group
= link_to_add_association 'Add Invoice Item', f, :invoice_items, class: 'btn btn-primary'
.actions
= f.submit 'Submit'
发票控制器:
class InvoicesController < ApplicationController
respond_to :json
before_action :set_invoice, only: [:show, :edit, :update, :destroy]
before_action :get_invoice_client, only: [:create, :update]
before_filter :authenticate_user!
# GET /invoices
# GET /invoices.json
def index
@invoices = current_user.invoices
end
# GET /invoices/1
# GET /invoices/1.json
def show
end
# GET /invoices/new
def new
@invoice = current_user.invoices.build
@invoice.client = @invoice.build_client
@invoice_items = @invoice.invoice_items.build
end
# GET /invoices/1/edit
def edit
end
# POST /invoices
# POST /invoices.json
def create
@invoice = current_user.invoices.build(invoice_params)
@invoice.client = @invoice_client
respond_to do |format|
if @invoice.save
format.html { redirect_to [current_user,@invoice], notice: 'Invoice was successfully created.' }
format.json { render action: 'show', status: :created, location: @invoice }
else
format.html { render action: 'new' }
format.json { render json: @invoice.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /invoices/1
# PATCH/PUT /invoices/1.json
def update
@invoice.client = @invoice_client
binding.pry
respond_to do |format|
if @invoice.update(invoice_params)
format.html { redirect_to [current_user, @invoice], notice: 'Invoice was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: @invoice.errors, status: :unprocessable_entity }
end
end
end
# DELETE /invoices/1
# DELETE /invoices/1.json
def destroy
@invoice.destroy
respond_to do |format|
format.html { redirect_to user_invoices_url(current_user) }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_invoice
@invoice = current_user.invoices.find(params[:id])
@invoice_items = @invoice.invoice_items
end
# Never trust parameters from the scary internet, only allow the white list through.
def invoice_params
params.require(:invoice).permit(:paid, :date_sent, :user_id, client_attributes: [:id, :email, :firstname, :lastname, :home_phone, :mobile_phone],
invoice_items_attributes: [:id, :description, :line_total, :unit_cost, :quantity, :item, :invoice_id, :_destroy])
end
def get_invoice_client
@invoice_client = Client.find_by_email(params[:invoice][:client_attributes][:email]) || nil
end
end
答案 0 :(得分:1)
尝试更改此行
= f.simple_fields_for :client, Client.new do |client|
到
= f.simple_fields_for :client, @invoice.client do |client|
答案 1 :(得分:0)
我不确定我理解客户端和用户之间的关系,但是如果您有一个现有的客户端表。 。
Class Client
has_one :user
Class User
belongs_to :client, :dependent => :destroy
has_many :invoices, :dependent => :destroy
has_many :invoice_items, :through => :invoices
Class Invoice
belongs_to :user
has_many :invoice_items, :dependent => :destroy
Class Invoice_item
belongs_to :Invoice
您可以将客户端和用户表合并到一个表中,因为两者之间存在一对一关联,但您可以将其保留为上述。
如果您的主要表单是@client,那么
= simple_form_for @client do |f|
... f.client fields ...
= f.simple_fields_for @user do |u|
... u.user fields ...
= f.simple_fields_for @invoices do |i|
... i.invoice fields ...
= f.simple_fields_for @invoice_items do |t|
... t.invoice_item fields ...
由于您使用的是Haml,因此缩进至关重要。如果将simple_field_for输出提取为单独的部分,则读取和管理将更加容易。我把它们排除在外,这样你就可以看到你的“嵌套”模型之间的关系了。
希望有所帮助。