提高代码复用之接口的规范,rails中参数,redirect_to小细节

发表于:,更新于:,By Sally
大纲
  1. 1. 接口
    1. 1.1. 通常,我在写接口的时候,是需要什么接口,就随手加一条接口
    2. 1.2. 于是,我们可以这么写
  2. 2. 页面渲染?刷新?
    1. 2.1. redirect_to 重定向
    2. 2.2. render 渲染
    3. 2.3. redirect_to 和 render

接口

通常,我在写接口的时候,是需要什么接口,就随手加一条接口

  • 假设:在一个后台中,存在很多个案例(什么事件的案例不重要),那在展示所有案例时,是这样做的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Interface::CasesController < ActionController::Base
# 返回所有的案例
def all_cases
all_cases = Case.all.map do |the_case|
{ :id=>the_case.id,
:name => the_case.name,
:desc => the_case.desc,
:site => the_case.site,
:layout_name => the_case.layout_name,
:total_area=> the_case.total_area,
:package_name=> the_case.package_name,
:cover=> SERVER + the_case.cover_url,
:style=> the_case.style,
:layout=> SERVER + the_case.layout.to_s,
}
end
render :json => {
:success => true,
:result => all_cases
}
end
end
  • 稍后,有存在很多分类,比如:按风格区分案例,按设计师区分案例等,这里是这样做的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Interface::CasesController < ActionController::Base
def select_cases_by_style
all_cases = Case.where("style like ?",params[:style].gsub(/"/,'')).map do |the_case|
{ :id=>the_case.id,
:name => the_case.name,
:desc => the_case.desc,
:site => the_case.site,
:layout_name => the_case.layout_name,
:total_area=> the_case.total_area,
:package_name=> the_case.package_name,
:cover=> SERVER + the_case.cover_url,
:style=> the_case.style,
:layout=> SERVER + the_case.layout_url,

}
end
render :json => {
:success => true,
:result => all_cases
}
end
end
  • 那如果还有很多个分类,就需要定义多个action去完成该相应的请求功能。但是可以看出,除了查询数据库的语句有变之外,返回的数据以及格式完全一样。这无疑产生了很多重复代码。

于是,我们可以这么写

  • 用条件来判断调用者传递过来的参数,然后执行查询操作产生相应的结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Interface::CasesController < ActionController::Base
def all_cases
case = Case
# 默认查询全部
cases = case.all
# 如果传递了 style 参数,就返回按 style 划分的集合
cases = Case.where("style like ?", params[:style] if params[:stylle].present?)
# 如果传递了 design 参数,就返回按 design 划分的集合
cases = Case.where("design like ?", params[:design] if params[:design].present?)
# 最后遍历集合,返回json
cases.map do |the_case|
{ :id=>the_case.id,
:name => the_case.name,
:desc => the_case.desc,
:site => the_case.site,
:layout_name => the_case.layout_name,
:total_area=> the_case.total_area,
:package_name=> the_case.package_name,
:cover=> SERVER + the_case.cover_url,
:style=> the_case.style,
:layout=> SERVER + the_case.layout.to_s,
}
end
render :json => {
:success => true,
:result => all_cases
}
end
end
  • 也可以这样做: 将查询语句的条件集合起来
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def all_cases
conditions = ["1=1"]
conditions << ["householders.name like '%#{params[:name]}%'"] if params[:name].present?
conditions << ["decoratingcases.address like '%#{params[:address]}%'"] if params[:address].present?
conditions << ["decoratingcases.designer_id = '#{params[:designer]}'"] if params[:designer].present? && params[:designer]!="全部设计师"
conditions << ["order_status = '#{params[:status]}'"] if params[:status].present? && params[:status] != "all"
conditions << ["( 1 = 1)"] if params[:status] == 'all'
conditions << ["(order_status is null or order_status = '')"] if params[:status] == ''
# 在where语句中,使用conditions条件;同时需要连接表查询,可以使用joins&includes
@decoratingcases = Jiangyoujia::Application.page(params[:page]||1)
.joins("left join householders on householders.id = decoratingcases.householder_id")
.where(conditions.join(" and "))
.includes(["application_remarks", "householder", "supervisor_operations"])
.order("#{order}")
end

页面渲染?刷新?

redirect_to 重定向

当程序执行到redirect_to方法时,代码就会停止执行,等待浏览器发起新的请求,这时,需要告诉浏览器下一步做什么,并返回302状态码

  • redirect_to 的写法 : 假设有一个product模型

  • 下面两种,都是可以带参数的

1
2
3
4
5
# 指定执行 index 这个action
redirect_to :action => "index", :page => params[:page]

# 或者指定执行 productions/index 该控制器下的index动作
redirect_to :controller => "productions/index", :page => params[:page]
  • 如果,不需要参数的话,可以使用下面的方法

  • 定向的路由 或者 地址

1
2
redirect_to products_path
redirect_to 'main/welcome'

render 渲染

render不会执行目标动作中的任何代码

1
render :action => 'index'

redirect_to 和 render

  • 首先使用 render

  • 该代码可能会出错,因为 product 可能会没有值,那执行 render :action => ‘index’ 时,不会执行index动作中的代码,就不会创建index页面需要的@index对象,

1
2
3
4
5
6
def show
product = Product.find(params[:id])
if product.nil?
reder :action => 'index'
end
end
  • 使用 redirect_to

  • 该代码执行起来不会有错,但是浏览器压力就会相对增大,如果 product 为nil,就会重定向到index动作,执行多起请求。

1
2
3
4
5
6
def show
product = Product.find(params[:id])
if product.nil?
redirect_to :action => 'index'
end
end
  • 最终,可以做如下折中处理
1
2
3
4
5
6
7
8
def show
product = Product.find(params[:id])
if product.nil?
@books = Book.all
flash.now[:alert] = 'sorry'
render 'index'
end
end