วิธีที่ดีที่สุดในการสร้างตัวเลือกการกำหนดค่าที่กำหนดเองสำหรับแอป Rails ของฉัน?


133

ฉันต้องการสร้างตัวเลือกการกำหนดค่าหนึ่งตัวสำหรับแอปพลิเคชัน Rails ของฉัน อาจเหมือนกันสำหรับทุกสภาพแวดล้อม ฉันพบว่าถ้าฉันตั้งค่าไว้environment.rbมันมีอยู่ในมุมมองของฉันซึ่งตรงกับที่ฉันต้องการ ...

environment.rb

AUDIOCAST_URI_FORMAT = http://blablalba/blabbitybla/yadda

ใช้งานได้ดี

อย่างไรก็ตามฉันไม่สบายใจเล็กน้อย วิธีนี้เป็นวิธีที่ดีหรือไม่? มีวิธีที่ฮิปกว่านี้ไหม?

คำตอบ:


191

สำหรับการตั้งค่าการใช้งานทั่วไปที่ไม่ต้องเก็บไว้ในตารางฐานข้อมูลผมชอบที่จะสร้างconfig.ymlไฟล์ภายในกำหนดค่าไดเรกทอรี สำหรับตัวอย่างของคุณอาจมีลักษณะดังนี้:

defaults: &defaults
  audiocast_uri_format: http://blablalba/blabbitybla/yadda

development:
  <<: *defaults

test:
  <<: *defaults

production:
  <<: *defaults

ไฟล์คอนฟิกูเรชันนี้ถูกโหลดจาก initializer แบบกำหนดเองในconfig / initializers :

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

# Rails 3+
APP_CONFIG = YAML.load_file(Rails.root.join('config/config.yml'))[Rails.env]

หากคุณใช้ Rails 3 ตรวจสอบให้แน่ใจว่าคุณไม่ได้เพิ่มเครื่องหมายทับลงในพา ธ การกำหนดค่าสัมพัทธ์ของคุณ

จากนั้นคุณสามารถดึงค่าโดยใช้:

uri_format = APP_CONFIG['audiocast_uri_format']

ดูRailscastสำหรับรายละเอียดทั้งหมด


1
คุณอาจต้องYAML::ENGINE.yamler = 'syck'ใช้สิ่งนี้เพื่อทำงานstackoverflow.com/a/6140900/414220
evanrmurphy

45
เพียง FYI ใน Rails 3.x คุณจะต้องแทนที่RAILS_ENVด้วยRails.envและมีRAILS_ROOT Rails.root
JeanMertz

5
สำหรับ Rails 3+ คุณควรเข้าร่วมเส้นทางสัมพัทธ์ไม่ใช่แบบสัมบูรณ์ อย่านำหน้าไดเร็กทอรี config ด้วยเครื่องหมายทับ
wst

10
ไม่แน่ใจเกี่ยวกับเวอร์ชันก่อนหน้า แต่ใน Rails 4.1 คุณสามารถทำได้Rails.application.config.whatever_you_want = YAML.load_file(Rails.root.join('config', 'config.yml'))[Rails.env]
d4rky

2
@ iphone007 เป็นไปได้ที่จะโหลดไฟล์ yaml โดยพลการจากไดเร็กทอรี config ดูคำตอบของ smathyด้านล่างซึ่งในความคิดของฉันควรเป็นคำตอบที่ยอมรับแล้ว
omnikron

82

รหัสเริ่มต้นรุ่น Rails 3 มีดังนี้ (RAILS_ROOT & RAILS_ENV เลิกใช้แล้ว)

APP_CONFIG = YAML.load_file(Rails.root.join('config', 'config.yml'))[Rails.env]

นอกจากนี้ Ruby 1.9.3 ยังใช้ Psych ซึ่งทำให้การผสานคีย์เป็นตัวพิมพ์เล็กและใหญ่ดังนั้นคุณจะต้องเปลี่ยนไฟล์กำหนดค่าของคุณเพื่อนำมาพิจารณาเช่น

defaults: &DEFAULTS
  audiocast_uri_format: http://blablalba/blabbitybla/yadda

development:
  <<: *DEFAULTS

test:
  <<: *DEFAULTS

production:
  <<: *DEFAULTS

3
คุณไม่ต้องการ"#{Rails.root.to_s}"; "#{Rails.root}"ได้ผล
David J.

3
ขอแนะนำRails.root.join('config', 'config.yml')แทน"#{Rails.root.to_s}/config/config.yml"
David J.

2
และแทนที่จะใช้ APP_CONFIG ขอแนะนำให้ใช้:AppName::Application.config.custom
David J.

1
เดวิดความคิดเห็นสองครั้งแรกของคุณเป็นแนวทางปฏิบัติที่ดีที่สุดและฉันจะแก้ไขโค้ด แต่อันสุดท้ายฉันจะละทิ้งเพราะนั่นหมายความว่าคุณต้องอย่าลืมเปลี่ยน AppName ทุกครั้งที่คุณใช้รหัสนี้
David Burrows

55

ราง> = 4.2

เพียงสร้างYAMLไฟล์ลงในconfig/ไดเร็กทอรีตัวอย่างเช่น: config/neo4j.yml.

เนื้อหาneo4j.ymlสามารถเป็นสิ่งที่ต้องการด้านล่าง (เพื่อความง่ายฉันใช้ค่าเริ่มต้นสำหรับทุกสภาพแวดล้อม):

default: &default
  host: localhost
  port: 7474
  username: neo4j
  password: root

development:
  <<: *default

test:
  <<: *default

production:
  <<: *default

ในconfig/application.rb:

module MyApp
  class Application < Rails::Application
    config.neo4j = config_for(:neo4j)
  end
end

ตอนนี้การกำหนดค่าที่กำหนดเองของคุณสามารถเข้าถึงได้ดังนี้:

Rails.configuration.neo4j['host'] #=>localhost
Rails.configuration.neo4j['port'] #=>7474

ข้อมูลเพิ่มเติม

เอกสาร API อย่างเป็นทางการของ Rails อธิบายconfig_forวิธีการดังนี้:

สะดวกในการโหลด config / foo.yml สำหรับ Rails ปัจจุบัน


หากคุณไม่ต้องการใช้yamlไฟล์

ตามที่คู่มืออย่างเป็นทางการของ Rails กล่าวว่า:

คุณสามารถกำหนดค่าโค้ดของคุณเองผ่านอ็อบเจ็กต์คอนฟิกูเรชัน Rails ด้วยคอนฟิกูเรชันแบบกำหนดเองภายใต้config.xคุณสมบัติ

ตัวอย่าง

config.x.payment_processing.schedule = :daily
config.x.payment_processing.retries  = 3
config.x.super_debugger = true

จากนั้นจุดกำหนดค่าเหล่านี้จะพร้อมใช้งานผ่านอ็อบเจ็กต์คอนฟิกูเรชัน:

Rails.configuration.x.payment_processing.schedule # => :daily
Rails.configuration.x.payment_processing.retries  # => 3
Rails.configuration.x.super_debugger              # => true
Rails.configuration.x.super_debugger.not_set      # => nil

ข้อมูลอ้างอิงอย่างเป็นทางการสำหรับconfig_forวิธีการ | คู่มือรางอย่างเป็นทางการ


25

ขั้นตอนที่ 1:สร้าง config / initializers / appconfig.rb

require 'ostruct'
require 'yaml'

all_config = YAML.load_file("#{Rails.root}/config/config.yml") || {}
env_config = all_config[Rails.env] || {}
AppConfig = OpenStruct.new(env_config)

ขั้นตอนที่ 2:สร้าง config / config.yml

common: &common
  facebook:
    key: 'asdjhasxas'
    secret : 'xyz'
  twitter:
    key: 'asdjhasxas'
    secret : 'abx'

development:
  <<: *common

test:
  <<: *common

production:
  <<: *common

ขั้นตอนที่ 3: รับค่าคงที่ที่ใดก็ได้ในโค้ด

facebook_key = AppConfig.facebook['key']
twitter_key  = AppConfig.twitter['key']

เราจะอ่านตัวแปร ENV ใน config.yml ได้อย่างไรการกำหนดค่าของฉันเหมือนกัน .. ฉันได้เพิ่มตัวแปรใน bashrc และฉันพยายามอ่านใน config.yml โดยใช้คีย์: <% = ENV [URL]%> ... ไม่ทำงาน
shiva

@shiva มองเข้าไปในอัญมณี Figaro สำหรับตัวแปร ENV การตั้งค่าการกำหนดค่านี้มีไว้สำหรับค่าที่ไม่จำเป็นต้องซ่อนจากตัวควบคุมต้นทาง
Shadoath

17

ฉันแค่ต้องการอัปเดตสิ่งนี้สำหรับสิ่งดีๆล่าสุดใน Rails 4.2 และ 5 ตอนนี้คุณสามารถทำสิ่งนี้ภายในconfig/**/*.rbไฟล์ของคุณ:

config.x.whatever = 42

(และนั่นคือตัวอักษรxในนั้นคือconfig.x.ตัวอักษรต้องเป็นอย่างนั้นจากนั้นคุณสามารถเพิ่มสิ่งที่คุณต้องการได้หลังจากนั้นx)

... และสิ่งนี้จะพร้อมใช้งานในแอปของคุณเป็น:

Rails.configuration.x.whatever

ดูเพิ่มเติมที่นี่: http://guides.rubyonrails.org/configuring.html#custom-configuration


3
แค่คำชี้แจงที่ทำให้เกิดปัญหาในตอนแรก x ไม่ใช่ตัวยึดตำแหน่งสำหรับสิ่งที่คุณต้องการใส่มันจำเป็นต้องเป็นตัวอักษรxจริงๆ
tobinibot

จุดยอดเยี่ยม @tobinibot - ฉันได้เพิ่มคำชี้แจงนั้นในคำตอบของฉันแล้วขอบคุณ
smathy

น่าสนใจที่คำแนะนำไม่ได้พูดถึง 'x' แต่ฉันยืนยันได้ว่ายังจำเป็นสำหรับ Rails 5.0
Don

คุณพูดถูกดอนมันแปลก - ฉันแน่ใจว่ามันเคยพูด
smathy

1
จากเอกสารรางปัจจุบัน: You can configure your own code through the Rails configuration object with custom configuration under either the config.x namespace, or config directly. The key difference between these two is that you should be using config.x if you are defining nested configuration (ex: config.x.nested.nested.hi), and just config for single level configuration (ex: config.hello).ที่มา: guide.rubyonrails.org/configuring.html#custom-configuration
David Gay

6

ข้อมูลเพิ่มเติมเกี่ยวกับหัวข้อนี้:

APP_CONFIG = YAML.load_file(Rails.root.join('config', 'config.yml'))[Rails.env].with_indifferent_access

".with_indifferent_access" ช่วยให้คุณสามารถเข้าถึงค่าในแฮชโดยใช้คีย์สตริงหรือด้วยคีย์สัญลักษณ์ที่เทียบเท่า

เช่น.
APP_CONFIG['audiocast_uri_format'] => 'http://blablalba/blabbitybla/yadda' APP_CONFIG[:audiocast_uri_format] => 'http://blablalba/blabbitybla/yadda'

เป็นเพียงสิ่งอำนวยความสะดวก แต่ฉันชอบให้คีย์ของฉันแสดงเป็นสัญลักษณ์


5

ฉันใช้สิ่งที่คล้ายกับ John for Rails 3.0 / 3.1 แต่ฉันได้แยกวิเคราะห์ไฟล์ erb ก่อน:

APP_CONFIG = YAML.load(ERB.new(File.new(File.expand_path('../config.yml', __FILE__)).read).result)[Rails.env]

สิ่งนี้ช่วยให้ฉันใช้ ERB ในการกำหนดค่าของฉันได้หากฉันต้องการเช่นการอ่าน URL redistogo ของ heroku:

production:
  <<: *default
  redis:                  <%= ENV['REDISTOGO_URL'] %>

2
ฉันไม่คิดว่าฉันจะต้องการสิ่งนี้ทุกวัน แต่นี่เป็นวิธีแก้ปัญหาที่ยอดเยี่ยมสำหรับเวลาที่คุณต้องการ ฉันคิดว่าฉันจะเปลี่ยนชื่อไฟล์เป็น config.yml.erb แม้ว่าจะตรงกับรูปแบบราง
Andrew Burns

2

Rails 4

หากต้องการสร้าง yaml การกำหนดค่าที่กำหนดเองและโหลด (และทำให้พร้อมใช้งานในแอปของคุณ) คล้ายกับวิธีการ database_configurationคล้ายกับวิธีการ

สร้างของคุณ*.ymlในกรณีของฉันฉันต้องการไฟล์กำหนดค่า redis

config/redis.yml

default: &default
  host: localhost
  port: 6379

development:
  <<: *default

test:
  <<: *default

production:
  <<: *default
  host: <%= ENV['ELASTICACHE_HOST'] %>
  port: <%= ENV['ELASTICACHE_PORT'] %>

จากนั้นโหลดการกำหนดค่า

config/application.rb

module MyApp
  class Application < Rails::Application

    ## http://guides.rubyonrails.org/configuring.html#initialization-events
    config.before_initialize do
      Rails.configuration.redis_configuration = YAML.load_file("#{Rails.root}/config/redis.yml")
    end

  end
end

เข้าถึงค่า:

Rails.configuration.redis_configuration[Rails.env]คล้ายกับวิธีที่คุณสามารถเข้าถึงdatabase.ymlโดยRails.configuration.database_configuration[Rails.env]


Rails.configuration.redis_configuration = YAML.load_file("#{Rails.root}/config/redis.yml")[Rails.env]นอกจากนี้คุณยังสามารถประหยัดเวลาตัวเองบางอย่างโดยเฉพาะการตั้งค่าสำหรับสภาพแวดล้อมในปัจจุบันของคุณซึ่งคงจะเป็นคนเดียวที่คุณต้องอยู่แล้ว: อย่างไรก็ตามในราง 4.2 ขึ้นไปคำตอบของ smathyน่าจะเป็นวิธีที่ง่ายกว่า
omnikron

1

ด้วยโซลูชันที่หรูหราของ Omer Aslam ฉันตัดสินใจที่จะแปลงกุญแจเป็นสัญลักษณ์ สิ่งเดียวที่เปลี่ยนแปลงคือ:

all_config = YAML.load_file("#{Rails.root}/config/config.yml").with_indifferent_access || {}

สิ่งนี้ช่วยให้คุณสามารถอ้างอิงค่าด้วยสัญลักษณ์เป็นคีย์ได้เช่น

AppConfig[:twitter][:key]

นี่ดูดีกว่าสำหรับตาของฉัน

(โพสต์เป็นคำตอบเนื่องจากชื่อเสียงของฉันไม่สูงพอที่จะแสดงความคิดเห็นในการตอบกลับของ Omer)



0

ดูคำตอบของฉันต่อตำแหน่งที่ดีที่สุดในการจัดเก็บพารามิเตอร์แอปพลิเคชันอยู่ที่ไหน: ฐานข้อมูลไฟล์รหัส ...

รูปแบบของสิ่งที่คุณมีซึ่งเป็นการอ้างอิงง่ายๆไปยังไฟล์อื่น จะเห็นว่า environment.rb ไม่ได้รับการอัปเดตอย่างต่อเนื่องและไม่มีเนื้อหาเฉพาะของแอปอยู่ในนั้น แม้ว่าจะไม่ใช่คำตอบที่เฉพาะเจาะจงสำหรับคำถามของคุณที่ว่า 'เป็นทางรถไฟหรือไม่' แต่อาจมีการพูดคุยเกี่ยวกับเรื่องนี้


0

ฉันชอบเข้าถึงการตั้งค่าผ่านกองแอปพลิเคชันส่วนกลาง ฉันหลีกเลี่ยงตัวแปรส่วนกลางที่มากเกินไปในขอบเขตท้องถิ่น

config / initializers / myconfig.rb

MyAppName::Application.define_singleton_method("myconfig") {YAML.load_file("#{Rails.root}/config/myconfig.yml") || {}}

และเข้าถึงได้ด้วย.

MyAppName::Application.myconfig["yamlstuff"]

0

วิธีของฉันในการโหลดการตั้งค่าก่อนที่ Rails จะเริ่มต้น

ให้คุณใช้การตั้งค่าในการเริ่มต้น Rails และกำหนดการตั้งค่าตามสภาพแวดล้อม

# config/application.rb
Bundler.require(*Rails.groups)

mode = ENV['RAILS_ENV'] || 'development'
file = File.dirname(__FILE__).concat('/settings.yml')
Settings = YAML.load_file(file).fetch(mode)
Settings.define_singleton_method(:method_missing) {|name| self.fetch(name.to_s, nil)}

คุณสามารถรับการตั้งค่าได้สองวิธี: การตั้งค่า ['อีเมล']หรือSettings.email


0

วิธีที่ดีที่สุดของฉันในการกำหนดค่าแบบกำหนดเองโดยมีข้อความเพิ่มขึ้นเมื่อไม่มี setting.yml

ได้รับการโหลดจากตัวเริ่มต้นที่กำหนดเองใน config / initializers / custom_config.rb

setting_config = File.join(Rails.root,'config','setting.yml')
raise "#{setting_config} is missing!" unless File.exists? setting_config
config = YAML.load_file(setting_config)[Rails.env].symbolize_keys

@APP_ID = config[:app_id]
@APP_SECRET = config[:app_secret]

สร้าง YAML ใน config / setting.yml

development:
  app_id: 433387212345678
  app_secret: f43df96fc4f65904083b679412345678

test:
  app_id: 148166412121212
  app_secret: 7409bda8139554d11173a32222121212

production:
  app_id: 148166412121212
  app_secret: 7409bda8139554d11173a32222121212
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.