可以使用auto complete插件来实现
这里还通过一个实例来说明:
说明:环境 rails 2.0.2, mysql, winxp
--有两个模型类:
Author:
#Class
class Author < ActiveRecord::Base
has_many :articles
end
#Migration
class CreateAuthors < ActiveRecord::Migration
def self.up
create_table :authors do |t|
t.column :name, :string
end
end
def self.down
drop_table :authors
end
end
class Author < ActiveRecord::Base
has_many :articles
end
#Migration
class CreateAuthors < ActiveRecord::Migration
def self.up
create_table :authors do |t|
t.column :name, :string
end
end
def self.down
drop_table :authors
end
end
Article:
#Class
class Article < ActiveRecord::Base
belongs_to :author
end
#Migration
class CreateArticles < ActiveRecord::Migration
def self.up
create_table :articles do |t|
t.column :author_id, :integer
t.column :content, :text
end
def self.down
drop_table :articles
end
end
class Article < ActiveRecord::Base
belongs_to :author
end
#Migration
class CreateArticles < ActiveRecord::Migration
def self.up
create_table :articles do |t|
t.column :author_id, :integer
t.column :content, :text
end
def self.down
drop_table :articles
end
end
对artilces资源的edit模板:
<h1>Edit</h1>
<%form_for(:article, :url=>article_path(@article), :html=>{:method=>:put}) do |f| %>
<p>
<label>Content:</label>
<%=f.text_field :content %>
</p>
<p>
<label>Author: </label>
<%=f.collection_select :author_id, Author.find(:all), :id, :name %>
</p>
<%= submit_tag "submit" %>
<%end%>
<%form_for(:article, :url=>article_path(@article), :html=>{:method=>:put}) do |f| %>
<p>
<label>Content:</label>
<%=f.text_field :content %>
</p>
<p>
<label>Author: </label>
<%=f.collection_select :author_id, Author.find(:all), :id, :name %>
</p>
<%= submit_tag "submit" %>
<%end%>
这里使用了选择框:
---这里我们希望做点改变,将author这个选择框变成一个输入框,输入的内容在authors表中做模糊查询,得到的结果在下面列出来。或者可以输入原本authors中不存在的数据,保存之后会添加到authors表中。
修改edit模板:
<h1>Edit</h1>
<%form_for(:article, :url=>article_path(@article), :html=>{:method=>:put}) do |f| %>
<p>
<label>Content:</label>
<%=f.text_field :content %>
</p>
<p>
<label>Author: </label>
<%=f.text_field :author_name %>
</p>
<%= submit_tag "submit" %>
<%end%>
<%form_for(:article, :url=>article_path(@article), :html=>{:method=>:put}) do |f| %>
<p>
<label>Content:</label>
<%=f.text_field :content %>
</p>
<p>
<label>Author: </label>
<%=f.text_field :author_name %>
</p>
<%= submit_tag "submit" %>
<%end%>
这里的author_name在articles表中并没有定义,所以在Article类中定义一个虚拟属性:
class Article < ActiveRecord::Base
belongs_to :author
#读方法,如果author存在的话,那么author.name值就是author_name
def author_name
author.name if author
end
#写方法,首先在authors表中查找name字段匹配的数据,存在,那么跟arti#cle.author发生关联,查找不到,那么创建新的author对象。
def author_name=(name)
self.author=Author.find_or_create_by_name(name) unless name.blank?
end
end
belongs_to :author
#读方法,如果author存在的话,那么author.name值就是author_name
def author_name
author.name if author
end
#写方法,首先在authors表中查找name字段匹配的数据,存在,那么跟arti#cle.author发生关联,查找不到,那么创建新的author对象。
def author_name=(name)
self.author=Author.find_or_create_by_name(name) unless name.blank?
end
end
现在就可以实现输入保存的功能了,但是还没有做自动完成的功能
下面安装auto complete插件
>ruby script/plugin install auto_complete
因为auto complete功能需要使用ajax,所以在layout/application视图中应该声明
<%= javascript_include_tag :defaults %>
那么如何通过ajax来让author输入框将name字段列出来呢?
应该是这样,在author输入框中的内容传到controller中,执行一个类似于这样的查询:
@authors = Author.find(:all, :conditions=>["name LIKE ?", "%#{params[search]}%"])
得到的这个@authors实例变量显示在author输入框下面
好了,来看看怎么实现这个功能:
在authors资源中,index这个action中的代码:
class AuthorsController < ApplicationController
def index
@authors=Author.find (:all, :conditions=>["name like ?", "%#{params[:search]}%"], :include=>[:articles])
end
end
def index
@authors=Author.find (:all, :conditions=>["name like ?", "%#{params[:search]}%"], :include=>[:articles])
end
end
我们希望能将输入文本框中的字符通过ajax方式,将其放到params[:search]中,然后在author输入框下面有一个下拉框一样的东西,显示的是@authors变量的name字段。
将edit.erb的内容修改如下:
<h1>Edit the Article</h1>
<%form_for(:article, :url=>article_path(@article), :html=>{:method=>:put}) do |f| %>
<p>
<label>Content:</label>
<%=f.text_field :content %>
</p>
<p>
<label>Author: </label>
<%= text_field_with_auto_complete :article, :author_name, {},{:url=>formatted_authors_path(:js),
:method=>:get, :with=>"'search='+element.value" }%>
</p>
<%= submit_tag "submit" %>
<%end%>
<%form_for(:article, :url=>article_path(@article), :html=>{:method=>:put}) do |f| %>
<p>
<label>Content:</label>
<%=f.text_field :content %>
</p>
<p>
<label>Author: </label>
<%= text_field_with_auto_complete :article, :author_name, {},{:url=>formatted_authors_path(:js),
:method=>:get, :with=>"'search='+element.value" }%>
</p>
<%= submit_tag "submit" %>
<%end%>
效果图如下:
值得注意的是这里表出来的一行
<%= text_field_with_auto_complete :article, :author_name, {},{:url=>formatted_authors_path(:js),
:method=>:get, :with=>"'search='+element.value" }%>
:method=>:get, :with=>"'search='+element.value" }%>
text_field_with_auto_complete是因为装了auto_complete插件之后可以使用这个tag
后面跟的参数第一个article是类名,第二个author_name是属性名,第三个{}里面可以写text_field的size属性等,第四个说明auto_complete显示内容,get方法,给params[:search]参数赋值。
OK..在rails1.2上自带有auto_complete这个helper,具体内容可以baidu或者google。。
本文转自 fsjoy1983 51CTO博客,原文链接:http://blog.51cto.com/fsjoy/108526,如需转载请自行联系原作者