如何拦截nested_attributes以进行进一步处理?
tl;dr:是否可以从嵌套模型中拦截发布的值以进行进一步处理?我已经尝试了所有我能想到的方法来访问嵌套属性以用于 before_save
回调,但这可能只是我想象力的局限性的证明。
我正在编写一个图书馆应用程序,其中书籍可以有许多作者,反之亦然。该位与 has_many_through
和 accepts_nested_attributes_for
配合得很好。该应用程序可以很好地保存所有书籍和作者信息。除了...我似乎无法在 Author 或 Book 模型上编写有效的 before_save
来检查我们尝试创建的 Author 是否存在。这是我已经拥有的:
class Book < ActiveRecord::Base
has_many :authorships
has_many :authors, :through => :authorships
accepts_nested_attributes_for :authors, :authorships
end
class Author < ActiveRecord::Base
has_many :authorships
has_many :books, :through => :authorships
before_save :determine_distinct_author
def determine_distinct_author
Author.find_or_create_by_author_last( @author )
end
end
## books_controller.rb ##
def new
@book = Book.new
@book.authors.build
respond_to do |format|
format.html
format.xml { render :xml => @book }
end
end
def create
@book = Book.new(params[:book])
@author = @book.authors #I know this line is wrong. This is the problem (I think.)
# more here, obviously, but nothing out of ordinary
end
当我发布表单时,开发日志会传递以下内容:
Parameters: {"commit"=>"Create Book",\
"authenticity_token"=>"/K4/xATm7eGq/fOmrQHKyYQSKxL9zlVM8aqZrSbLNC4=",\
"utf8"=>"✓", "book"{"title"=>"Test", "ISBN"=>"", "genre_id"=>"1", "notes"=>"", \
"authors_attributes"=>{"0"{"author_last"=>"McKinney", "author_first"=>"Jack"}}, \
"publisher"=>"", "pages"=>"", "language_id"=>"1", "location_id"=>"1"}}
所以......数据就在那里。但我如何才能处理它呢?当我发布数据时,日志如下:
Author Load (0.4ms) SELECT `authors`.* FROM `authors` WHERE\
`authors`.`author_last` IS NULL LIMIT 1
我已经做了相当多的搜索,看看嵌套属性上有什么,我在表单方面看到了很多,但关于如何访问的内容却很少。资产一旦提交。
任何关于为什么有效的解决方案确实有效的解释也将不胜感激。谢谢。
tl;dr: Is it possible to intercept posted values from a nested model for further processing? I've tried everything I can think of to access the nested attributes to use for a before_save
callback, but that may be only a testament to the limits of my imagination.
I'm writing a library application, where books can have many authors and vice versa. That bit is working just fine with a has_many_through
and accepts_nested_attributes_for
. The app saves all the book and author information just fine. Except... I can't seem to write a working before_save
on either the Author or Book model to check if the Author that we're trying to create exists. Here's what I already have:
class Book < ActiveRecord::Base
has_many :authorships
has_many :authors, :through => :authorships
accepts_nested_attributes_for :authors, :authorships
end
class Author < ActiveRecord::Base
has_many :authorships
has_many :books, :through => :authorships
before_save :determine_distinct_author
def determine_distinct_author
Author.find_or_create_by_author_last( @author )
end
end
## books_controller.rb ##
def new
@book = Book.new
@book.authors.build
respond_to do |format|
format.html
format.xml { render :xml => @book }
end
end
def create
@book = Book.new(params[:book])
@author = @book.authors #I know this line is wrong. This is the problem (I think.)
# more here, obviously, but nothing out of ordinary
end
When I post the form, the dev log passes on this:
Parameters: {"commit"=>"Create Book",\
"authenticity_token"=>"/K4/xATm7eGq/fOmrQHKyYQSKxL9zlVM8aqZrSbLNC4=",\
"utf8"=>"✓", "book"{"title"=>"Test", "ISBN"=>"", "genre_id"=>"1", "notes"=>"", \
"authors_attributes"=>{"0"{"author_last"=>"McKinney", "author_first"=>"Jack"}}, \
"publisher"=>"", "pages"=>"", "language_id"=>"1", "location_id"=>"1"}}
So... the data's there. But how do I get to it to process it? When I post the data, here's that log:
Author Load (0.4ms) SELECT `authors`.* FROM `authors` WHERE\
`authors`.`author_last` IS NULL LIMIT 1
I've done a fair bit of searching around to see what there is out there on nested attributes, and I see a lot on the form side, but not much on how to get to the assets once they're submitted.
Any explanation of why the solution which works does actually work would also be appreciated. Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先,这一行将
一组作者分配给@author,但在您的 before_save 中,您似乎期望单个作者模型。其次,@author 变量的作用域为控制器,并且在模型的作用域中将为空。
删除该行并在您的 Book 类中尝试此操作(未测试):
First, this line
assigns an array of authors to @author, but in your before_save you seem to be expecting a single author model. Secondly, the @author variable is scoped to the controller and will be empty in your model's scope.
Remove that line and try this in your Book class (not tested):
1) 嵌套属性是一个数组,应该作为数组来访问。从一个模型到下一个模型的提交仍然是一个很大的问题。
2)accepts_nested_attributes_for可能不会有太大帮助,毫无疑问,从现在到整个系统完全发挥作用之前,必须进行大量自定义处理。也许现在最好放弃它并继续前进。
在这个方向上:看起来 Ryan Bates 最近在 jQuery TokenInput 插件上做了一些工作这将处理作者的许多自动完成功能。更多关于更大的问题(并且有点难找到)是 follow 他发布了关于处理新条目的插件的一些问题。
1) The nested attributes is an array, and should be accessed as an array. Getting the submission from the one model to the next still presents quite a problem.
2)
accepts_nested_attributes_for
is probably not going to help out a whole lot, and there will undoubtedly be a lot of custom processing which will have to happen between now and when the whole system is fully functional. Probably best to ditch it now and move on.In that direction: It looks like Ryan Bates has done a recent bit on the jQuery TokenInput plugin which will take care of a lot of the autocomplete feature on the author. More to the larger problem (and a bit harder to find), is a follow up that he posted to some issues with the plugin on working with new entries.
我不太确定你想要完成什么,但在你的 Author 内部你有一个 before_save 回调,这显然给出了错误。
对我来说,您似乎正在寻找具有给定名称的作者,然后想使用它?这是正确的吗?
使用嵌套表单,您将始终创建一个新作者,除非您想使用选择框之类的东西,然后选择一个作者 ID(它是书籍的一部分,因此不是嵌套的),而不是作者详细信息。
在用户体验方面,我会提供选择现有作者(使用自动完成字段)或创建新作者(使用嵌套字段选项——无需
before_save
回调)的选项。I am not quite sure what you are trying to accomplish, but inside your
Author
you have abefore_save
callback, and that is obviously giving the error.To me it seems you are looking for an author with the given name, and then want to use that? Is that correct?
Using a nested form, you will always create a new author, unless you want to use something like a select-box, and then select an author-id (which is part of the book, so not nested), instead of the authors details.
UX-wise, i would offer the option to either select an existing author (use an autocomplete field), or create a new one (using the nested fields option --without your
before_save
callback).