嵌套表单:find_or_create_by 多个字段

发布于 2025-01-05 06:57:26 字数 2896 浏览 5 评论 0原文

我陷入了嵌套表单和活动记录“find_or_create_by”方法的使用中间。我想做的事情:

我有 3 个模型:帐户、交易和类别。

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)

但是我应该在哪里使用它以及它应该是什么样子?

我真的很感谢你的帮助!

I'm stuck in the middle of a nested form and usage of active records "find_or_create_by" method.. What I'm trying to do:

I have 3 models: Account, Transaction and 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

My form looks like this: 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"

My controllers look like this:

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

Categories Controller:

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

Now, I'm stuck. I only want to create a new category, if there isn't already an existing category with the same title AND same account_id.

By now, it always creates a new category, ignoring that there is already a category with the same name and the same account_id. I know that I should use something like this:

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

But where should I use it and how should it look exactly?

I really appreciate your help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

尴尬癌患者 2025-01-12 06:57:26

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

You can use Category.find_or_initialize_by_title_and_account_id(category.title, account.id), then modify it and save (_create_ saves the object in the same line). But if I understand correctly, what you need here are validations. By convention, we design our apps to retrieve errors (like: "Category title must be unique") in #create actions of your controllers and if there are errors, we render :action => :new again (with the same form as previously, but with errors shown). I see that you're using formtastic, so you've got errors display in forms by default (I think).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文