【发布时间】: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