最近在帮朋友做个小网站。因为感觉Rails太好玩了。所以,就准备使用Rails来搞。但是,有时因为D瓜哥刚刚学习Rails。所以,就遇到了各种各样的诡异问题。今天就来讲解一个D瓜哥纳闷很久的问题: 如何让前台浏览页面和后台管理页面使用不同的layout(窃译为“布局”)文件?
前人的肩膀
其实这个问题在Stack Overflow上已经有人解决了,原问题及其解答:rails 3: layout for namespaced routes。
不过,解答的描述实在差强人意!所以,D瓜哥就“自己动手丰衣足食”,按照解答自己实践一下。还是特别感谢问题的提问者以及解答者!
建立Controller
相信看这篇文章的朋友,应该都知道,Controller相关的文件都放在了%Rails_Root%/app/controllers/
目录下,为了和普通的Controller区分,我们在%Rails_Root%/app/controllers/
下新建一个目录admin
,用于专门存放后台管理页面相关的Controller。
建立基本的Controller
也行大家都看过普通的Controller类的实现,都需要继承ApplicationController
,把Controller的基本功能都继承下来。为了让后台管理页面使用不同的布局文件,其实我们只需要在Controller类定义中,调用一下layout
方法即可。Rails中一个重要原则就是DRY。所以,为了减少代码重复,不在每一个后台管理相关的Controller中重复调用layout方法,我们建立一个后台的基础类。代码如下:
3 | class Admin::BaseController < ApplicationController |
4 | layout 'admin/application' |
这里需要特别说明一下的是,为了防止和其他普通的Controller重名,也为了便于识别和管理,我们将后台管理相关的Controller都放到了Admin
命名空间里。
建立登录Controller
建立完基础的Controller后,我们再来建立一个和登录相关的Controller。代码如下:
3 | class Admin::SessionsController < Admin::BaseController |
配置Routes
添加完上面的Controller后,启动服务器,打开http://localhost:3000/admin/signin,页面会报错,提示No route matches [GET] "/admin/signin"
。很明显是没有配置routes(窃译为“路由规则”)。所以,我们需要配置一下路由规则。
3 | SampleApp::Application.routes.draw do |
5 | resources :sessions , only: [ :new ] |
7 | match '/signin' , to: 'sessions#new' , via: 'get' |
我的工程命是SampleApp
,你的工程名字也行和我的不一样。所以,代码也有稍有差异。
添加模板
建立完路由规则,再刷新页面,页面报错,错误如下:
1 | Missing template layouts/admin/application with { :locale =>[ :en ], :formats =>[ :html ], :handlers =>[ :erb , :builder , :raw , :ruby , :jbuilder , :coffee ]}. |
这是提示我们确实模板文件。另外,有木有感觉admin/application
有点眼熟?我们在Admin::BaseController
类中调用layout事,传递的参数就是这个。
建立布局文件
根据上面的分析,我们需要在%Rails_Root%/app/views/layouts/admin/
目录下,新建一个名为application.html.erb
的文件。代码如下:
3 | < h1 >This is Admin pages.</ h1 > |
这里将布局文件命名为application.html.erb
,是为了和Rails生成的默认布局文件保持一致。从这里也能看出来,在Controller中调用layout方法,其实就是指名了寻找布局文件的路径,并且默认的根目录是%Rails_Root%/app/views/layouts/
。
建立视图模板文件
创建完布局文件,我们再次刷新浏览器。还是报错,提示错误信息如下:
1 | Missing template admin/sessions/ new , admin/base/ new , application/ new with { :locale =>[ :en ], :formats =>[ :html ], :handlers =>[ :erb , :builder , :raw , :ruby , :jbuilder , :coffee ]}. |
根据我们对Rails的MVC的了解,可以一样看出来,我们需要创建new.html.erb
。代码如下:
3 | This is login page.Please login. |
至此,所有的工作做完,再刷新一下页面(http://localhost:3000/admin/signin),是不是看到了我们想象的后台管理页面?
终极解决方案
解决后台管理页面创建的终极解决方案是:active_admin。据网友评论说,有了 ActiveAdmin,创建 Rails 应用的管理界面就像儿戏。你会有一个很好的仪表盘,图形化 CRUD 界面以及更多东西。非常灵活且可客制化。
刚刚开始整的时候,出了点问题。所以,D瓜哥就在Ruby China上发帖“active_admin 兼容 Rails 4 吗?”询问了一下。感谢网友的回答,让我顺利过关。
由于Rails 4刚刚推出,不知道active_admin的有没有发布可以兼容Rails 4的官方包。所以,在Gemfile
文件中声明gem包的时候,必须指定一下它的来源和分支。另外,还有声明一些依赖的gem。具体声明如下:
03 | gem 'activeadmin' , github: 'gregbell/active_admin' , branch: 'rails4' |
04 | gem 'ransack' , github: 'ernie/ransack' , branch: 'rails-4' |
05 | gem 'inherited_resources' , github: 'josevalim/inherited_resources' |
06 | gem 'formtastic' , github: 'justinfrench/formtastic' |
10 | gem 'jquery-rails' , '3.0.4' |
然后,使用如下命令更新、安装一下gem包:
相信一些朋友和我一样,对这两个命令都很好奇,也很纳闷,有啥区别呢?D瓜哥在网上找了两篇文章,希望能给这些朋友“传道授业解惑”:
- bundle update 和 bundle install平时大家用哪个?
- Why you should run bundle update
升级完gem包后,允许如下命令,生成后台页面:
1 | rails generate active_admin :install |
这个命令会创建一个初始化的管理页面,并且创建%Rails_Root%/app/admin
目录,用于存放管理相关的配置信息。
下一步,进行数据库迁移。执行如下命令:
完成数据库迁移之后,执行如下命令,启动服务器:
这时,就可以访问http://localhost:3000/admin,跳转到登录页面,登录进入后台管理页面。默认登录名和密码如下:
- User: admin@example.com
- Password: password
现在,虽然有了后台管理页面,但是我们需要管理的各种东西都没有。所以,这个必须得加进来。执行命令如下:
1 | rails generate active_admin :resource [MyModelName] |
这条命令会在%Rails_Root%/app/admin
目录下生成my_model_names.rb
,用于配置资源信息。这时,刷新一下浏览器,顶部菜单栏是不是多了个选项?
这样搞,实在是太爽太方便了!Rails真实太TM好玩了:怎一个爽字了得啊?!
自我吐槽
有两个地方需要特别声明一下:
- 代码段的第一行为文件路由;
- 有些地方需要建立一些文件夹,请各位看文章时候注意。
特别感谢
这篇文章,部分内容参考了active_admin的官方文档。特别感谢!
支持一下,
应该写个rails admin的比较
嗯,有机会试用一下,能看出门道来就写。哈哈
默认账号和密码登录不了。