【问题标题】:How to customize a form/POST in Rails?如何在 Rails 中自定义表单/POST?
【发布时间】:2011-07-09 11:18:46
【问题描述】:

大家好,这个问题困扰了我整整一周。我是 Rails 新手,所以请温柔:)

我的根本问题是我正在尝试编写一个 form_for Post,它将在输入上使用自动完成功能将帖子与客户联系起来。数据库正在寻找 client_id,而不是文本名称。 所以我尝试了一个自定义验证,它将查找文本值并将其替换为 id。 我的 Post.rb 文件有这个:

class Post < ActiveRecord::Base
    belongs_to :client
    attr_accessor :client_name
    attr_accessible :client_name
    before_validation_on_create :validate_client

    def validate_client
        self.client_id = 1 # just a test
    end

    def client_exists(passed_name)
      return Client.where(:full_name => passed_name).first.blank?
    end
end

但是当我这样做时,没有一个表单变量被传递。数据库获取除 client_id 之外的所有空白条目。我该如何完成此操作?为什么我的表单变量没有被传入?非常感谢。

编辑 1:从 posts_controller.rb 添加创建定义

def create
    @post = Post.new(params[:post])

    respond_to do |format|
      if @post.save
        format.html { 
            redirect_to(posts_url) # redirect_to(@post, :notice => 'Post was successfully created.')        
        }
        format.xml  { render :xml => @post, :status => :created, :location => @post }
        format.js
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @post.errors, :status => :unprocessable_entity }
      end
    end
  end

编辑 2:感谢@apneadiving,我更改了 attr_accesible 以包含其他属性,并将 POST 条目传递到数据库中。

attr_accessible :client_id, :time, :content, :client_name

但是当我将 validate_client 函数更改为搜索 client_id 时,

def validate_client
    passed_name = self.client_name

    if client_exists(passed_name)
        c = Client.where(:full_name => passed_name).first
        self.client_id = c.id
    else
        errors.add_to_base "Error"
    end
end

它总是给我这个错误:

为 nil 调用 id,这将 错误地是 4——如果你真的 想要 nil 的 id,使用 object_id

编辑 3:这是我的帖子表单。我无法正确获取 :client_name 的值。

<%= form_for(@post) do |f| %>
  <%= render 'common/error_messages', :object => f.object %>
  <div class="field">
      <%= f.label :content %><br />
      <%= f.text_area :content, :size => "50x6" %>
    </div>
  <div class="field">
    <div class="sub-field">
      <%= f.label :client_name %><br />
      <%= f.text_field :client_name, :size => "26" %>
    </div>
    <div class="sub-field">
      <%= f.label :date %><br />
      <%= f.text_field(:time, :class => 'date', :size => "10", :value => Date.today.strftime('%m/%d/%Y')) %>
    </div>
    <div class="sub-field">
      <%= f.label :time %><br />
      <%= f.time_select :time %>
    </div>
  </div>

  <div class="actions clear">
    <%= f.submit %>
  </div>
<% end %>

编辑 4:解决方案。我很难获得 :client_name,因为我的文本被标记得太远(我最初是将该功能私有化,然后将“私有”这个词去掉) . @apneadiving 答案的修改版本为我解决了这个问题!

class Post < ActiveRecord::Base
    belongs_to :client
    attr_accessor :client_name
    validate :validate_client

    def validate_client
        passed_name = self.client_name

        unless client = Client.find_by_full_name(passed_name).blank?
          self.client_id = Client.find_by_full_name(passed_name).id
        else
          errors.add(:client_name, "'#{passed_name}' cannot be found.")
        end
    end

end

【问题讨论】:

  • 嗨,painteddigital,当一个网络请求被发出时(例如一个 POST),处理它的代码在一个控制器中(通常由路由定义)。列出您在控制器中使用的代码以及获得此特定问题的答案可能会有所帮助。
  • 谢谢布兰登。我添加了它,虽然它很通用。通过脚手架创建。
  • 注意你的attr_accessible,如果你设置一个,你必须设置所有可以通过params设置的变量。否则,它们会受到保护,不会被批量分配
  • @apneadiving 很棒的提示!我不知道。因此,我将其他变量添加到文件中,但由于某种奇怪的原因,查找 client_id 时出错。我在上面评论过。
  • 似乎 c.id 为 nil,这意味着您的 client_exists 函数无法按预期工作。

标签: ruby-on-rails ruby-on-rails-3 validation forms post


【解决方案1】:

您的client_exists 代码错误,如果不存在则返回true。 此外,由于您的 client_existsvalidation 重复使用相同的查询,我会重写一下。

def validate_client
  passed_name = self.client_name

  existing_client = Client.where(:full_name => passed_name).first
  if existing_client
    self.client_id = existing_client.id
  else
    errors.add_to_base "Error"
  end
end

【讨论】:

    【解决方案2】:

    小心你的attr_acessible

    如果设置一个,则必须设置所有可以通过params设置的变量。否则他们会受到mass assignment 的保护

    编辑 1:

    似乎c.id 为零,这意味着您的client_exists 函数无法按预期工作。尝试以下(未测试):

    def validate_client
      unless client = Client.find_by_full_name(client_name).nil?
        client_id = client.id
      else
        errors.add_to_base "Error"
      end
    end
    

    【讨论】:

    • 您的代码看起来很棒,但是当我尝试它时,我遇到了“406 Not Acceptable”错误。所以我一直试图找出问题所在,我通过将 client_name 存储到内容字段中了解到它是空白的。这又回到了我最初的问题,即不了解如何操作 POST 数据。 :client_name 只是我为以后查找 :client_id 创建的一个 text_field。有没有一种简单的方法可以做到这一点或我应该阅读的资源?我在上面添加了我的 _post.html.erb。
    • 您好,我不太了解 pb。出于好奇,我可以看看你的schema.rb 中描述模型的部分吗?
    • 整理好了!谢谢你的帮助。我认为 406 是因为提交的信息,但实际上是由于使用 JS 处理错误并且没有 JS 响应程序。空白数据是因为我认为我不小心插入了太多标签。很奇怪。
    猜你喜欢
    • 2013-03-10
    • 1970-01-01
    • 1970-01-01
    • 2021-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-07
    • 1970-01-01
    相关资源
    最近更新 更多