嵌套表单:find_or_create_by 多个字段
我陷入了嵌套表单和活动记录“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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以使用
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, werender :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).