创建基于Rails 3的纯净Ajax CRUD程序

十一 11th, 2011

Rails 3利用scaffold可以很容易地创建CRUD程序,但那是多页面的,现在很多场景需要使用Ajax在一个页面上实现CRUD。这对Rails 来说也是很简单的,下面就来创建一个符合Rails风格的Ajax CRUD程序。整个过程大概15分钟,建议先把整个代码照应敲一遍,然后再慢慢理解。

目标:

只有1个页面,CRUD全部基于Ajax在一个页面完成。使用无入侵式的Javascript风格。

平台:

适用于Rails 3.*,使用jQuery+sqlite。
Rails 3.1开始默认自带jQuery,如果是Rails 3.0.*需要手动添加jQuery。
如果想用Prototype要把那些js做相应修改。

Let’s GO:

1、创建项目

rails new AjaxCRUD
# 创建scaffold
rails g scaffold Entry name:string address:text phone:string email:string
# 建立数据库和表
rake db:create
rake db:migrate

2、修改controller

因为创建的是基于Ajax的CRUD,所以controller返回的数据要支持‘.js’格式,可以把默认的json格式删掉,其实除了index会返回网页,其它都是返回js,所以index外的html格式返回也可以删除。

respond_to do |format|
format.html
format.js
end

基于个思想,修改后的controller如下:

class EntriesController < ApplicationController
  def index
    @entries = Entry.all
    @entry = Entry.new

    respond_to do |format|
      format.html # index.html.erb
      format.js
    end
  end

  def show
    @entry = Entry.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.js
    end
  end

  def new
    @entry = Entry.new

    respond_to do |format|
      format.html # new.html.erb
      format.js
    end
  end

  def edit
    @entry = Entry.find(params[:id])

    respond_to do |format|
      format.html
      format.js
    end
  end

  def create
    @entry = Entry.new(params[:entry])

    respond_to do |format|
      if @entry.save
        format.html { redirect_to @entry, notice: 'Entry was successfully created.' }
        format.js
      else
        format.html { render action: "new" }
        format.js { render action: "new" }
      end
    end
  end

  def update
    @entry = Entry.find(params[:id])

    respond_to do |format|
      if @entry.update_attributes(params[:entry])
        format.html { redirect_to @entry, notice: 'Entry was successfully updated.' }
        format.js
      else
        format.html { render action: "edit" }
        format.js { render action: "edit" }
      end
    end
  end

  def destroy
    @entry = Entry.find(params[:id])
    @entry.destroy

    respond_to do |format|
      format.html { redirect_to entries_url }
      format.js
    end
  end
end

3、修改Views

修改index页面(app/views/entries/index.html.erb)来显示Entry表单。

<h1>Listing entries</h1>
<table id="entries">
<tbody>
<tr>
<th>Name</th>
<th>Phone</th>
<th>Email</th>
<th>Address</th>
<th></th>
<th></th>
<th></th>
</tr>
</tbody>
</table>
<h2>Entry form</h2>
<div id="form">"form" %></div>

注意:为了后面用jQuery操作DOM,table设置id=”entries”。

修改partial(app/views/entries/_form.html.erb),注意在form_for中添加remote以发送异步请求。

<%= form_for(@entry, :remote => true) do |f| %>
  <% if @entry.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@entry.errors.count, "error") %> prohibited this entry from being saved:</h2>

      <ul>
      <% @entry.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :phone %><br />
    <%= f.text_field :phone %>
  </div>
  <div class="field">
    <%= f.label :email %><br />
    <%= f.text_field :email %>
  </div>
  <div class="field">
    <%= f.label :address %><br />
    <%= f.text_area :address, :rows => 3 %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

新建Entry partial(app/views/entries/_entry.html.erb)。
为了发送AJAX请求,edit,destroy都设置remote=true。
为了区分不同的entry,调用dom_id来根据entry生成不同的id

<tr id="<%= dom_id entry %>">
  <td><%= entry.name %></td>
  <td><%= entry.phone %></td>
  <td><%= entry.email %></td>
  <td><%= simple_format entry.address %></td>
  <td><%= link_to 'Show', entry %></td>
  <td><%= link_to 'Edit', edit_entry_path(entry), :remote => true %></td>
  <td><%= link_to 'Destroy', entry, confirm: 'Are you sure?', method: :delete, :remote => true %></td>
</tr>

4、添加js.erb来响应Ajax请求

下面是关键,首先先说下操作流程:浏览器发起Ajax请求(CRUD)–>controller收到请求,并调用model更新数据–>返回js代码–>浏览器收到js代码,使用jQuery来更新index页面中的DOM对象,包括列表和表单。

新建 app/views/entries/create.js.erb 响应添加Entry的请求
1、在index页面的entry列表中添加刚才新增的entry对象。
2、清空index页面中添加entry表单中的数据。

$('<%= escape_javascript(render(:partial => @entry)) %>').appendTo('#entries').hide().fadeIn();
$("#new_entry")[0].reset();

escape_javascript(render(:partial => @entry))可以缩写成:j render @entry。

新建 app/views/entries/edit.js.erb 处理点击编辑时的请求
在index页面的新建entry的form中填充要编辑entry的数据。

$("#form > form").replaceWith("<%= j render "form" %>");

新建 app/views/entries/update.js.erb 来更新列表中的Entry对象。新建Entry并清空form

$("#<%= dom_id @entry %>").replaceWith("<%= j render @entry %>");
<% @entry = Entry.new # reset for new form %>
$(".edit_entry").replaceWith("<%= j render "form" %>")
$(".new_entry")[0].reset();

新建 app/views/entries/destroy.js.erb 来删除list中的Entry

$("#<%= dom_id @entry %>").remove();

5、设置主页

设置entries页面为主页。修改 config/routes.rb

AjaxCRUD::Application.routes.draw do
  resources :entries
  root :to => "entries#index"
end

删除静态首页文件。

rm public/index.html

6、启动程序

rails s

此时打开 http://127.0.0.1:3000
就可以使用了。

源代码托管在
https://github.com/camelsong/AjaxCRUD

英文原文地址:http://codefundas.blogspot.com/2010/12/create-ajax-based-curd-using-rails-3.html

标签: , , , ,
>>原创文章,欢迎转载。转载请注明:转载自Ruby迷,谢谢!
>>原文链接地址:创建基于Rails 3的纯净Ajax CRUD程序
  1. 老式仓库
    十二 14th, 201123:07

    好像不是半角的问题。。。我稍微改了一下就好了。
    不过这里评论贴代码格式不对。。。就不贴了。。。

  2. 老式仓库
    十二 12th, 201100:16

    这段也有问题:
    true %>

    ‘Are you sure?’, :method => :delete, :remote => true %>

    估计是粘贴的时候代码格式化错了。

  3. 老式仓库
    十二 12th, 201100:12

    博主,第3点中,修改Views的这段代码有问题吧?

    Entry form
    16
    “form” %>

    • 老宋
      十二 12th, 201119:39

      你说的问题是标点符号的全半角问题,我在chrome中没有哦,你是不是复制时自动进行了转换

      • PikachuEXE
        十二 29th, 201110:34

        原文:http://codefundas.blogspot.com/2010/12/create-ajax-based-curd-using-rails-3.html
        正确码:

        “form” %>

        • PikachuEXE
          十二 29th, 201110:35

          汗,还是贴不到,去原文处看吧