【问题标题】:Nested Form: find_or_create_by multiple fields嵌套表单:find_or_create_by 多个字段
【发布时间】:2012-02-11 10:43:09
【问题描述】:

我被困在嵌套表单和活动记录“find_or_create_by”方法的使用中。我正在尝试做的事情:

我有 3 个模型:Account、Transaction 和 Category。

class Account < ActiveRecord::Base
  has_many :transactions, :dependent => :destroy
  has_many :categories, :dependent => :destroy
end

class Category < ActiveRecord::Base
  has_many :transactions
  belongs_to :account
end

class Transaction < ActiveRecord::Base    
  belongs_to :category, :autosave => true
  belongs_to :account

  accepts_nested_attributes_for :category
end

我的表单如下所示:app/views/transactions/new.haml

= semantic_form_for @transaction do |f|
  = f.inputs do
    = f.input :account_id, :as => :hidden
    = f.input :title, :label => false
    = f.input :amount, :label => false
    = f.inputs :for => :category do |c|
      = c.input :title, :as => :string
      = c.input :account_id, :as => :hidden
  = f.buttons do
    = f.submit "Save"

我的控制器如下所示:

class TransactionsController < ApplicationController

  def new
    @transaction = Transaction.new
    @transaction.date ||= Transaction.last.date if Transaction.last
    @transaction.account= Account.find(params[:account]) if params[:account]
    @account = @last_transaction.account if @last_transaction
    @account = Account.find(params[:account]) if params[:account]
    @transaction.build_category(:account => @account)
  end

  def create
    @transaction = Transaction.new(params[:transaction])
    @account = @transaction.account
    respond_to do |format|
      if @transaction.save
         format.html {redirect_to (new_transaction_path( :account => @account ))}
      else
         format.html {redirect_to (new_transaction_path( :account => @account ))}
      end
    end
  end
end

类别控制器:

class CategoriesController < ApplicationController

  before_filter :authenticate_user!

  def new
    @category = Category.new
    @category.account = Account.find(params[:account]) if params[:account]
    @accounts = current_user.accounts
  end

  def create
    @category = Category.new(params[:category])
    respond_to do |format|
      if @category.save
        format.html {redirect_to (categories_path)}
      else
        format.html {render :action => "new"}
      end
    end
  end

  def update
    @category = Category.find(params[:id])
    respond_to do |format|
      if @category.update_attributes(params[:category])
        format.html {redirect_to (categories_path)}
      else
        format.html {render :action => "edit"}
      end
    end
  end
end

现在,我被困住了。如果还没有具有相同标题和相同 account_id 的现有类别,我只想创建一个新类别。

到目前为止,它总是会创建一个新类别,而忽略已经有一个具有相同名称和相同 account_id 的类别。我知道我应该使用这样的东西:

Category.find_or_create_by_title_and_account_id(category.title, account.id)

但是我应该在哪里使用它以及它应该看起来如何?

非常感谢您的帮助!

【问题讨论】:

  • 那么你的控制器代码在哪里?
  • 我添加了控制器代码。

标签: ruby-on-rails ruby activerecord associations nested-forms


【解决方案1】:

您可以使用Category.find_or_initialize_by_title_and_account_id(category.title, account.id),然后修改并保存(_create_ 将对象保存在同一行中)。但如果我理解正确,你需要的是validations。按照惯例,我们设计我们的应用程序来检索控制器的#create 操作中的错误(例如:“类别标题必须是唯一的”),如果有错误,我们会再次render :action =&gt; :new(使用与以前相同的形式,但使用显示错误)。我看到您正在使用 formtastic,因此默认情况下您会在表单中显示错误(我认为)。

【讨论】:

  • 感谢您的回答。但是我会把你建议的线路放在哪里?哪个控制器和哪个动作?
  • 你把它放在你的控制器里,因为这是最常用和最合适的方式。我看到你的代码有一些问题,你读过 Rails 指南吗?你的控制器中@last_transaction 的定义在哪里?
  • 你可以尝试用@transaction.category = Category.find_or_initialize_by_account_id_and_transaction_id(@account.id, @transaction.id)替换@transaction.build_category(:account =&gt; @account)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-19
  • 2020-02-21
  • 1970-01-01
相关资源
最近更新 更多