我的根本问题是我正在尝试编写一个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条目传递到db。
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 - 如果你真的 想要id为nil,请使用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
答案 0 :(得分:1)
小心您的attr_acessible
:
如果你设置了一个,你必须设置所有可以通过参数设置的变量。否则,他们会受到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
答案 1 :(得分:0)
您的client_exists
代码错误,如果不存在则返回true。
此外,由于您的client_exists
和validation
重复使用相同的查询,我会稍微重写一下。
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