JavaScript DRY Your Ruby Constants Configs and Routes In Javascript

hooopo · 2012年10月18日 · 最后由 hooopo 回复于 2012年10月19日 · 3145 次阅读

Rails 的设计哲学之一就是 DRY。但是在 Rails 引入 Asset Pipeline 之前,一个项目里的 Ruby 代码和 Javascript/CSS 代码是很难交互的。 这样就带来了很多问题,比如:

  1. 重复的常量在 Ruby 里一份,在 Javascript 里一份
  2. 重复的应用配置在 Ruby 里一份,在 Javascript 里一份,甚至 Javascript 里都不配置,因为 Js 里很难区分是 Production 环境还是 Development 环境。
  3. 重复的路由生成。

上面的重复带来几个问题,就是常量/配置/路由散落在 Ruby 和 Javascript 里给修改带来了麻烦。 Javascript 很难根据不同环境做不同的配置,比如一个读取通知的接口在 dev 环境下是 192.168.1.1,在生产环境是 notify.xxx.com,在 Javascript 里有时候只好硬编码成 notify.xxx.com,需要使用的时候临时修改成 192.168.1.1,提交代码之前又要修改回去,麻烦的一塌糊涂。 路由也是一样,前端使用路由的时候不像 Rails 那样有 RESTful 的方法,可以像questions_path这样生成路径,即使拼错路径也会 FaiFast,即时得到反馈。总之,前端拼 URL 不方便,并且对错误不敏感。

但是,Rails3 引入了 Asset Pipeline 之后,everything changed.

在发布之前的构建(build)过程把静态文件和 Ruby 代码结合起来,然后才是最终的发布。

![alt text][1]

下面是简单的例子:

常量:

# app/model/event.rb
class Event < ActiveRecord::Base
  NAME_MAX_LENGTH = 70

  validates :name, length: { maximum: NAME_MAX_LENGTH }

  # ...
end
# countdown_event_name.js.erb #
var max = <%= Event::NAME_MAX_LENGTH %>

配置:

config/config.yml

development:
    notify_url: 192.168.1.1
production:
    notify_url: notify.xxx.com

config/initializers/

APP_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/config.yml")[RAILS_ENV]

config.js.erb

(function(){
  this.Config = {
    notify_url: "<%= APP_CONFIG['notify_url'] %>",
    other_config: "<%= APP_CONFIG['other_config'] %>",
    # ...
    }
}).call(this);

app/assets/applications.js

//= require cofnig

in other js file

Config.notify_url;

路由:

路由有点小复杂,目前只找到了一个插件: https://github.com/railsware/js-routes 等我的 Javascript 学好了自己写一个...

Refs:

  1. http://robots.thoughtbot.com/post/32392361476/dont-repeat-your-ruby-constants-in-javascript
  2. http://stackoverflow.com/questions/592554/best-way-to-create-custom-config-options-for-my-rails-app
  3. http://www.12factor.net/build-release-run

[1]: http://www.12factor.net/images/release.png

这个方法好,谢谢分享了

嗯,的确不错!

提个小建议:

APP_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/config.yml")[RAILS_ENV]

以上代码建议用 settingslogic 重构一下。

还是有些复杂

#2 楼 @tech_blogbin 觉得没有必要再引入一个 gem 了,需要优化的话可以自己再简单封装

在磁盘是主要瓶颈的今天,项目引入 gem 数量直接影响 rails 的启动直接,启动慢开发时不爽

我现在的做法都是再 application.html.erb 里面写一个 APP_DOMAIN = "<%= Setting.app_domain %>" 的方式,JS 里面需要增加一个 App.urlWithPath 之类的方法来组合 URL

除了配置,如果更动态的请求,还是需要用 controller 做一个 view 返回这些参数。类似看到很多的 http://xxx.com/domain_config.js?params_a=xxx

#5 楼 @huacnlee yeah! so quick, so dirty...

需要 登录 后方可回复, 如果你还没有账号请 注册新账号