【问题标题】:Rails: Virtual attributes and form valuesRails:虚拟属性和表单值
【发布时间】:2009-06-21 01:51:40
【问题描述】:

我有一个带有虚拟属性的模型书,用于从书本表单创建一个编辑器。 代码如下:

class Book < ActiveRecord::Base
  has_many :book_under_tags
  has_many :tags, :through => :book_under_tags
  has_one  :editorial
  has_many :written_by
  has_many :authors, :through => :written_by

  def editorial_string
   self.editorial.name unless editorial.nil?
   ""
  end
  def editorial_string=(input)
    self.editorial = Editorial.find_or_create_by_name(input)
  end
end

还有新的形式:

<% form_for(@book,
            :html => { :multipart => true }) do |f| %>
  <%= f.error_messages %>

...
  <p>
    <%= f.label :editorial_string , "Editorial: " %><br />
    <%= f.text_field :editorial_string, :size => 30  %> <span class="eg">Ej. Sudamericana</span>
  </p>
 ...

这样,当表单数据没有通过验证时,当重新显示表单时,我丢失了在编辑字段中提交的数据,并且还创建了一个新的编辑器。我该如何解决这两个问题?我是 ruby​​ 的新手,我找不到解决方案。

更新我的控制器:

  def create
    @book = Book.new(params[:book])
    respond_to do |format|
      if @book.save
        flash[:notice] = 'Book was successfully created.'
        format.html { redirect_to(@book) }
        format.xml  { render :xml => @book, :status => :created, :location => @book }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @book.errors, :status => :unprocessable_entity }
      end
    end
  end

【问题讨论】:

    标签: ruby-on-rails activerecord attributes virtual


    【解决方案1】:

    我相信它的原因是您的 Book#editorial_string 方法将始终返回“”。可以简化为:

      def editorial_string
       editorial ? editorial.name : ""
      end
    

    根据评论更新:

    听起来你想做嵌套表单。 (请参阅accepts_nested_attributes_for in api docs)注意这是 Rails 2.3 中的新功能。

    所以如果你更新你的 Book 类

    class Book < ActiveRecord::Base
      accepts_nested_attributes_for  :editorial
      ...
    end
    

    (您现在也可以删除 editorial_string=, editorial_string 方法)

    并将您的表单更新为以下内容

    ...
    <% f.fields_for :editorial do |editorial_form| %>
      <%= editorial_form.label :name, 'Editorial:' %>
      <%= editorial_form.text_field :name %>
    <% end %>
    ...
    

    【讨论】:

    • 谢谢。但是,我再次遇到的问题是,由于验证错误,当表单重新显示时,我丢失了字段编辑的值。而且我不知道如何防止在书未通过验证时创建社论。
    • 感谢您的回复,我使用的是ubuntu aptitude工具安装的rails 2.1.0-6,所以我没有那个功能。我认为我将更改表单并禁止在 Book 表单中创建 Editors。
    【解决方案2】:

    第一个问题是

    def editorial_string
      self.editorial.name unless editorial.nil?
      ""
    end
    

    将始终返回 "",因为那是最后一行。

    def editorial_string
      return self.editorial.name if editorial
      ""
    end
    

    会解决这个问题。至于为什么验证不通过,我不知道,你在控制器中做什么?您遇到了哪些验证错误?

    【讨论】:

    • 感谢您的修复。但是我有同样的问题:我在编辑表单中丢失了表单中插入的值。在控制器中我有: def create @book = Book.new(params[:book]) respond_to do |format| if @book.save flash[:notice] = '书已成功创建。' format.html { redirect_to(@book) } else format.html { render :action => "new" } end end end
    • 您能否查看您的开发服务器日志并粘贴您的参数。从那里我会尝试用这些参数在脚本/控制台创建一本新书,看看你是否能找到任何看起来不合适的东西(或修复它)。
    • 这里:参数:{"commit"=>"Cear", "authenticity_token"=>"1e0b41988b8c3908a52ce5422e0852a76afbf1a4", "action"=>"create", "author_string"=>"", "controller "=>"books", "book"=>{"uploaded_picture"=>"", "title"=>"", "isbn"=>"00", "published"=>"", "pages"= >"100", "description"=>"", "edittorial_string"=>"AAAAAAAA"}}
    • 好的,所以打开脚本/控制台,将这些参数分配给一个变量,然后尝试在控制台上创建一本书。你所拥有的应该起作用。
    • 是的。这样可行。但我的问题是,如果我在提交的数据中遇到验证错误(例如 ISBN 没有验证),当重新显示表单显示错误时,我丢失了编辑字段的值(该字段的提交值)。我认为@rnicholson 的回答是正确的,我需要accepts_nested_attributes_for,但我还没有那个版本的rails :(。
    【解决方案3】:

    看看这个播客http://railscasts.com/episodes/167-more-on-virtual-attributes。我认为你应该从 editorial_string=(input) 移动你的 find_or_create 保存后回调的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-29
      • 2012-07-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多