08 October 2014

缘起


觉得以前写的后台不太好用,想要修改,未征得前辈的同意。于是百度了一下,看有没有什么好用Ruby的后台管理的模板之类的,结果找到了两个gem包: web-app-theme和rails_admin

rails_admin有一个Dome, 而web-app-theme没有demo,看来,如果要使用的话,需要去仔细的阅读官方的文档。

rails_admin的Dome的地址为https://github.com/bbenezech/dummy_app/,由于年代久远,加之世界变化飞快,很多demo中的很多的gem包的都已经更新到Rails 4或者Ruby 2.0以上了。为了确保以后整合的方便,特地将Gem包之流的版本向前调整了,调整的gem版本如下:

gem 'rails'
gem 'rails_admin', '~> 0.4.9'
gem 'cancan'  # 授权管理
gem 'devise'  # 权限系统
gem 'paperclip'   # 文件上传
gem 'mini_magick'
gem 'carrierwave' # 文件上传
gem 'dragonfly', '0.9.12'

精确的版本控制是很重要的,版本的不兼容会导致很多的问题,而且莫名其妙。比如dragonfly 0.9和 1.0之间的不兼容,导致自己安装和启动服务器不能成功。

此外,原先的gem包的安装在工作使用的tophold的gemset中,导致安装了一大堆的不同版本的Rails,相当的混乱。使用rvm gemset empty tophold将gemset清空掉了,然后在重新使用bundle install安装web项目所需的gem; 新建一个新的gemset: cpanel。并尝试在项目中添加.ruby-gemset.ruby-version,仔细想想,这样也挺方便的,不必时时都用默认的。

成功运行Demo之后,界面还挺漂亮的,效果也挺不错的,没有出现全面刷新的情况。查看了一下代码,傻眼了,除了Models中有些内容,其他的地方都没什么内容,难道,具体的内容都封装到了rails_amdin中。但是,如何使用过去版本的rails_admin,从哪里下手,一脸迷茫,先从项目的Readme开始。

RailsAdmin


RailsAdmin是一个Rails engine,其提供易于使用的接口操作数据。

特性

RailsAdmin具有很多的特性,其中一些列出如下:

  • 可对任何数据进行CRUD操作
  • Custon定制化方法
  • 自动的表单验证
  • 搜索以及过滤
  • 可将数据导出为CSV/JSON/XML
  • 验证通过Devise或其他
  • 授权通过Cancan
  • 用户动作历史通过PaperTrail
  • 支持的ORMs: ActiveRecord以及Mongoid

安装

  • bundle gem包
  • 运行rails g rails_admin:install
  • 需要时,为路由提供一个命令空间
  • 启动服务器,rails s,并在admin/下管理数据。

配置

配置文件在config/initializers/rails_admin,为了开始需要对启动Devise、Cancan以及Papertrail有所了解。

Rails_admin的wiki文档: https://github.com/sferik/rails_admin/wiki

Cancan


CanCan是Ruby的授权库,其限制了给定的用户可以访问的资源。所有的权限都定义在Ability这个类中,并且不需要在控制器,视图以及数据库查询中重复。

安装

Rails 3中,通过在Gemfile中添加,并运行bundle命令安装cancan

gem “cancan”

开始

CanCan需要一个可在控制器中访问的current_user方法。首先,设置权限(通过Authlogic或者Devise)。如果想要特别的定制的话,参考改变默认行为

注意: 权限和授权是不同的,因此,存在Devise这样的身份验证的权限库,以及cancan这样的授权库。不过,授权本身依赖权限的控制。

1. 定义Abilities

用户权限定义在Ability类中,CanCan 1.5提供一个Rails 3的生成器,可以用来创建该类。

如果使用的Rails 2.3的版本,需要在models目录下添加新类ability.rb,并加上如下的内容:

class Ability
  include CanCan::Ability

  def initialize(user)
  end
end

更多细节参定义Abilities

**2.检查Abilities以及Authorization **

当前的用户权限可通过在视图和控制器中使用can?cannot?方法检查。

<% if can? :update, @article %>
  <%= link_to "Edit", edit_article_path(@article) %>
<% end %>

更多信息参考Checking Abilities

如果用户不具有操作某个给定工作的权限,authorize!方法将会抛出异常。

def show
  @article = Article.find(params[:id])
  authorize! :read, @article
end

为每个动作设定如上的anagram是繁琐的,所以load_and_authorize_resource方法为所有RESTful的资源路由器的控制器自动设置权限方法。其使用before过滤器在实例变量中加载资源并对每个方法完成授权。

class ArticlesController < ApplicationController
  load_and_authorize_resource

  def show
    # @article is already loaded and authorized
  end
end

更多信息参考授权控制器动作

3. Handle Unauthorized Access

如果用户授权失败,就会抛出CanCan::AccessDenied异常。必须要捕获该行为,并在ApplicationController中修改其行为。

class ApplicationController < ActionController::Base
  rescue_from CanCan::AccessDenied do |exception|
    redirect_to root_url, :alert => exception.message
  end
end

更多信息参考异常处理

4. Lock It Down

如果想要对应用中每一个动作确保授权都能启动,可以同在ApplicationController中添加check_authorization

class ApplicationController < ActionController::Base
  check_authorization
end

This will raise an exception if authorization is not performed in an action. If you want to skip this add skip_authorization_check to a controller subclass. See Ensure Authorization for more information.

设置该方法后,如果某个方法没有执行授权,就会抛出异常。如果想要在某个子类中跳过检查,可以在类中添加skip_authorization_check。更多信息,参考Ensure Authorization

CanCan的Wiki文档: https://github.com/ryanb/cancan/wiki

web-app-theme


Web App Theme是一个Rails生成器,可以用来快速生成管理后台面板。其灵感来源Lighthouse, Basecamp, RadiantCMS以及其他,该个gem包可以称为开发一个完整的web应用程序布局的起点。

安装

Rails(版本>= 3.1.0)

该版本的Rails,所有的样式都存放在gems包的assets路径中,并且不需要拷贝到应用程序中,除非你想要定制样式(使用web_app_theme:assets生成器)。There only css file generated when you run the theme generator is the web_app_theme.css that includes the theme of your choice. Add to your gemfile:

gem ‘web-app-theme’, ‘~> 0.8.0’

使用

主题生成器

不带任何参数使用时,会在application.html.erb中生成带有默认主题的布局。

rails g web_app_theme:theme

可以在第一个参数中指定生成的布局的名字:

rails g web_app_theme:theme admin # it will generate a layout called `admin.html.erb`

如果想要使用另外的主题取代默认的,可以使用--theme选项:

rails g web_app_theme:theme admin --theme="drastic-dark"

可以通过--engine=name选项,指定模板引擎,引擎可以是erb或haml。

rails g web_app_theme:theme --engine=haml # 需要在Gemfile中指定haml

If you want to generate the stylesheets of a specific theme without changing the previously generated layout you can pass the –no-layout option:

如果想要生成特定主题的样式表,但又不想改变之前生成的布局,可以设置--no-layout选项:

rails g web_app_theme:theme --theme=bec --no-layout

想要指定在头部使用的文本,可以使用--app-name选项:

rails g web_app_theme:theme --app-name="My New Application"

如果想要用来生成用来登录和登出的页面,需要使用值为sign的–type选项。如果没指定,默认值是administration

rails g web_app_theme:theme sign --layout-type=sign

资源生成器(Assets Generator)

Used to copy a theme of your choice from the gem to your application, without parameters it will copy the ‘default’ theme

用来从gem包中拷贝所选择的主题,并将其放到应用程序中。不带任何参数时,则使用default主题。

rails g web_app_theme:assets --theme=red

上面的命令将拷贝主题文件到app/assets/stylesheets/web-app-theme路径中,同样也会将图片拷贝到app/assets/images/web-app-theme路径中。

Themed Generator

Start creating your controllers manually or with a scaffold, and then use the themed generator to overwrite the previously generated views.

手动创建控制器,或者使用scaffold创建控制器。然后,使用themed生成器覆盖先前生成的视图。比如,有一个使用model复数名的控制器,覆盖先前生成的视图命令如下:

rails g web_app_theme:themed posts # 模型为Post,控制器为PostsController
rails g web_app_theme:themed admin/gallery_pictures # 模型为GalleryPicture,控制器名为Admin::GalleryPicturesController

Use the –layout option specifying the previously generated layout to add a link to the controller you are working on:

使用--layout选项指定先前生成的布局,并添加链接到控制器中,命令如下:

rails g web_app_theme:themed posts --layout=admin # 添加`Posts`链接到导航中

如果控制器使用和模型不同的名字,则地址个参数指定控制器路径,第二个参数指定模型名:

rails g web_app_theme:themed items post
rails g web_app_theme:themed admin/items post

如果使用will_paginate作为分页,则需要使用--will-paginate选项:

rails g web_app_theme:themed items post --will-paginate

可以通过--engine=name选项,指定模板引擎,引擎可以是erb或haml。

rails g web_app_theme:themed posts --engine=haml

如果在routes.rb设置了类似map.resource :dashboard这样的路由,可以使用--type=text来生成text视图:

rails g web_app_theme:themed dashboards --themed-type=text

If you want to show form error messages inside the generated forms, use the following code inside your environment.rb

如果想要在生成的表单内显示错误信息,可以在environment.rb中使用如下的代码:

ActionView::Base.field_error_proc = Proc.new do |html_tag, instance| 
  if html_tag =~ /<label/
    %|<div class="fieldWithErrors">#{html_tag} <span class="error">#{[instance.error_message].join(', ')}</span></div>|.html_safe
  else
    html_tag
  end
end

如果想要带有翻译页,可以在类似config/locales/en_us.ymllocale.yml文件中创建响应的键。

en_us:
  web-app-theme: 
    save: Save
    cancel: Cancel
    list: List
    edit: Edit
    new: New
    show: Show
    delete: Delete
    confirm: Are you sure?
    created_at: Created at
    all: All

ActiveAdmin

又发现了一个新的后台管理的gem包 - ActiveAdmin。一些收集如下:

总结

上面的写的虽然乱七八糟的,但是,一段时间后在看这些的介绍,确实又收获了不少。

后记


折腾新的gem包需要时间,这些时间这样做值不值,应该有更加重要的事情才对。我去引入haml到项目中如何,然后,就是将

原本是新的后台,结果变成了新的后台模板语言,总有些乱其八糟的感觉。不管怎么样,算是迈出了第一步,erb写的确实恶心。

一个月过后,看了xdite关于视图部分的整理,找到了个方法,将js放到body的最下面。网页加载的速度确实变快了,后台的速度稍微有点起色了,优化的第一步算是完成了。




傲娇的使用Disqus