Rails Rails 的两个 Tips,ENV 变量和 CarrierWave 文件路径

chunlea · 2014年09月08日 · 最后由 zsusyt 回复于 2016年06月05日 · 7656 次阅读

需要将应用程序从 Heroku 转到 DigitalOcean 上,遇到两个问题,问题描述和解决方案如下:

问题一:ENV 环境变量。

Heroku 有非常好的管理 ENV 变量的机制,但是对于 VPS 一直未见特别完美的方案。有很多的 Gem 可以用,我也用过 SettingsLogics,但是显然,受制于加载顺序,SettingsLogic 对于 database.yml 或者 initializers 一类的文件基本就没用了。今天发现下面的这个方法,感觉符合自己的预期,故推荐下。 参考:http://quickleft.com/blog/simple-rails-app-configuration-settings

主要两点: 在 config/application.rb 文件的 module Whatever 之前,加入:

ENV.update YAML.load_file('config/application.yml')[Rails.env] rescue {}

然后创建 config/application.yml, 内容如下:

defaults: &defaults
  email: [email protected]
  secret: foo123

development:
  <<: *defaults

test:
  <<: *defaults
  email: [email protected]

production:
  <<: *defaults
  email: [email protected]
  secret: 321oof

之后你就可以使用类似 ENV['email'] 的变量了。不过这个也有一个非常小的问题,就是 YAML 文件只能一层,不能进行嵌套,也不支持 YAML 的数组或者列表的结构。

不要将 config/application.yml 签到你的代码库中,由于 rescue {} 的存在,因此,即使没有 config/application.yml 这个文件,也不会挂掉。


问题二:CarrierWave 环境和路径问题

项目开发环境用 file 存储,生产环境通过 fog 来用 s3 这个也没有问题,唯独用的时候才发现 file 默认的是相对路径。可是我这个是给移动端用的,你给我想对路径我还怎么搞…… 后来发现,可以简单的设置 CarrierWave.configure.asset_host 来给开发环境设置默认使用绝对路径。直接贴配置文件吧,相信大家明白什么意思。

# File at config/initializers/carrierwave.rb

require 'carrierwave'
require 'carrierwave/orm/activerecord'

CarrierWave.configure do |config|
  if Rails.env.development? || Rails.env.test?
    config.storage    = :file
    config.asset_host = ENV['asset_host'] # 这行的作用就是强制在file的url前面附加 ENV['asset_host'] 的内容
  else
    config.storage = :fog

    config.fog_credentials = {
      :provider                            => 'AWS',                                        # required
      :aws_access_key_id         => ENV['aws_access_key_id'],        # your aws access key id
      :aws_secret_access_key  => ENV['aws_secret_access_key']  # your aws secret access key
      # :region                            => ENV['S3_REGION']                    # your bucket's region in S3, defaults to 'us-east-1'
    }
    # your S3 bucket name
    config.fog_directory  = '*********'
    # custome your domain on aws S3, defaults to nil
    # config.fog_host       = 'http://myapp.com'
    config.fog_public     = false                                     # optional, defaults to true
    # config.fog_attributes = {'Cache-Control'=>'max-age=315576000'}  # optional, defaults to {}
  end
end

#1 楼 @leomayleomay 我有看过第三方 Gem,有时候就有点小纠结,不喜欢用他们……

我有个问题,如何让 carrierwave 在没有 AWS 这些云的时候,也就是直接上传在自己服务器的时候,也支持保存绝对路径给移动端用呢?实际生产环节,我也遇到了这个问题。

#3 楼 @hanluner 设置 config.asset_host = http://domain.com, 具体参考给出的config/initializers/carrierwave.rb文件。

支持,刚好为 ENV 头痛,我之前还在生产机的 /etc/environment 里面定义的:

export [email protected]

ruby-china 用的 settingslogic,方便是方便,但不如楼主的直接,觉得能少用 Gem 就少用吧,看着长长的列表头痛。

#6 楼 @Peter #1 楼推荐的 Figaro 跟我这里推荐的方法功能是一样的,settingslogic 由于加载顺序的问题,对于 database.yml 以及 config/initializers 里的文件应该不起作用。另外,我的建议是两种方法配合使用,毕竟 settingslogic 支持多级别的 yaml 文件,这样数据的组织更清晰,而我的这个方法,主要配置一些环境变量,如数据库密码等。好处是再也不用担心 database.yml 一类的文件是否需要签入到 git 库里面了。同时兼容 Heroku。

在次之前,我是直接将 export [email protected] 写入.bashrc 文件的……

rails4.2 支持这种写法 Rails.application.config_for(:application),返回一个 hash ~~ 😃

#7 楼 @chunlea 又要麻烦你一下,我在 yml 文件里用了中文,保证是 utf-8 保存的,但在 view 中使用的时候会报错,

incompatible character encodings: ASCII-8BIT and UTF-8
<%= ENV['homepage_name'] %>

你方便试一下吗?

#9 楼 搞定了,如果每次都要这样用,还是有点点淡淡的悲伤:

<%= ENV['HOMEPAGE_NAME'].dup.force_encoding("UTF-8")  %>
zsusyt 邮件配置信息设置 提及了此话题。 06月05日 15:42
需要 登录 后方可回复, 如果你还没有账号请 注册新账号