Gem DSL for defining before_filters's dependencies like rake tasks

mvj3 · 2013年07月13日 · 最后由 mvj3 回复于 2013年07月16日 · 3770 次阅读

Rails before_filters don't take it far enough. What stepstepstep allows you to do is define before_filters's dependecies in the same way you do with rake tasks.


Stick this in your Gemfile.

gem 'stepstepstep'


Include the DSL && Defining steps

class FooController < ApplicationController
  include Stepstepstep

  step :two => [:one_point_three, :one_point_seven] do
    @a << 2
  step :one_point_three => :one do
    @a << 1.3
  step :one do
    @a = [1]
  step :one_point_seven => :one_point_three, :only => :index do
    @a << 1.7

  def index
    render :inline => @a.inspect # => [1, 1.3, 1.7, 2].inspect

  def another
    render :inline => @a.inspect # => [1, 1.3, 2].inspect

Why does stepstepstep.gem exists?

A few months ago, I was writing a single page application about learning mobile development technology at This page contains lessons, a video, classes, teachers, students, reference material, question-to-answers, exams, chat messages, and their current all learning statuses and dependencies. In brief, there are fifteen steps to load this page, including privileges to judge, fourteen illegal redirect_to , etc. So I need to write a step dependencies management tool, like rake tasks.

At first, I thought maybe I could define several procs in a single before_filter, but the execution context is really complicated. Then one day, I found action_jackson.gem, which was written by Blake Taylor two years ago. The core implementation of this gem is to define each action as a method, and at last call a class method register_filters to register all these methods as before_filter independently. Of course, they're ordered by the earlier declarations. This implementation is not elegant, but the idea is really awesome, it doesn't break Rails's rules.

Then I got a deep understanding of the Rails controllers filters's implementation mechanism. Maybe skip_before_filter helped. In each step, I insert it first, extract all the inserted steps by skip_before_filter, then sort them by TSort(a topological sorting algorithm provided by Ruby standard library), and at last append them again to before_filters. It works, and all rspecs are passed.

I renamed it from action_jackson to stepstepstep, because the DSL is only a step class method, which handles all the details. Most of the implementations were rewritten, and I added rspecs . Thanks Blake Taylor :)


-__- 工作流似的...

#1 楼 @luikore

_.keys(eoe) // ["domain_to_urls", "domain", "app", "uid", "uname", "uhash", "avatar", "homeUrl", "appUrl", "app_item", "app_item_id", "visitor_list_pattern", "fp", "jsfun_user_avatar_url", "is_uid_a_teacher", "utils", "faye_port", "learn_summary_data", "is_local", "current_user", "is_uid_uhash_valid", "course", "all_classes", "teachers", "is_a_teacher", "current_class", "is_current_class_time_end", "period_id", "students", "is_a_student", "lessons", "lesson_id_to_seqs", "current_issue", "is_current_issue_finished", "current_lesson_time_racings", "class_channel", "lesson_channel", "lesson", "uid_to_unames", "section_with_exam", "online_uids", "user", "issue", "spend_seconds", "is_not_finished_issue", "lesson_to_spend_time", "lessons_seq_in_students", "lesson_to_questions_count", "lesson_to_answers_count", "learn_id_to_exam_count", "students_in_summary_unfinished", "students_in_summary_finished_sort", "seq_in_class", "learn_summary", "feedback", "is_debug", "faye"]
_.keys(eoe).length // 59
_.reject(eoe, function(s) { return _.isFunction(s); }).length // 49

在 Chrome 控制台可以看到的有 49 个变量数据输出,如何管理是个大问题,里面还包括读写和前后依赖,目前我想到的解决办法是分到不同的流程里面。


#3 楼 @hooopo 。。。话说你们都是如何处理这样有很多数据和流程依赖的单页应用?

mvj3 一个人的"Github" 提及了此话题。 09月02日 08:24
需要 登录 后方可回复, 如果你还没有账号请 注册新账号