Can I pass additional params to the rails credentials? - ruby-on-rails

I have a file, for example:
config/credentials/development.yml.enc
Call for this file:
Rails.application.credentials[Rails.env.to_sym][:some_key]
Can I pass params in this call?
I need to do in file with credentials something like this:
development:
some_key: its_my_key_with_params_#{params}

Related

Rails: configuring applications

I am reading and coding along with a tutorial.
I have an application.yml file with some constants created to hold data. To include those constants in ENV and initialize them at start, this code was given :
config_file = Rails.application.config_for(:application) #this is the bothersome part
config_file.each do |key,value|
ENV[key] = value
end unless config_file.nil?
I fail to fully understand this code. In particular, on the first line, where do the chained objects come from what do they mean and how do I create such on my own ?
It loads data from a config file into the app. The example from the docs about #config_for:
#config/app.yml:
production:
url: http://127.0.0.1:8080
namespace: my_app_production
development:
url: http://localhost:3001
namespace: my_app_development
If you do rails c and type Rails.application.config_for(:app) into the console, you'll get:
{"url"=>"http://localhost:3001", "namespace"=>"my_app_development"}
which is just a regular hash you can loop through using #each or access it's values through keys.

Rails - Access file sitting in different port

I have two instances of web server. One is running on port 3000 and one is running on 9090. I want to access the JSON file sitting in the 9090 port.
In the rails model, I'm able to access the JSON file fine when I use
stream = open("http://localhost:9090/file.json")
But what I want to do is something more like
stream = open(":9090/file.json") # OUTPUT: No such file or directory - :9090/file.json
I want to avoid hardcoding the URL (obviously), and if I also want to avoid passing in the 'domain' from Rails controller to rails model.
Or is there a package that handles accessing different port, if openURI doesn't do this?
Thank you!
You can create a global CONFIG variable, that will load the content of config/config.yml for instance.
You can load this file in an initializer, here is mine :
if !defined? CONFIG
CONFIG = YAML.load_file(File.join(Rails.root, "config", "config.yml"))[Rails.env] rescue []
end
Then in your model :
stream = open("#{CONFIG['url']}:9090/file.json")
Assuming your config.yml looks like this :
development:
url: http://localhost
production:
url: http://what.ever

YAML configuration file: Why 'example' instead of :example?

I set up an environment YAML file for environment specific variables like username and password. To use these variables in my app, I need to use APP_CONFIG['username'] instead of APP_CONFIG[:username]. Why is this? How would I enable the latter instead? Not a major issue, but it bothers me to not know the cause of the difference.
config/initializers/load_app_config.rb
APP_CONFIG = YAML.load_file("#{Rails.root}/config/app_config.yml")[Rails.env]
config/app_config.yml
development:
username: development_name
password: secret
production:
username: production_name
password: super_secret
By default, a YAML key is rendered as String.
development:
username: development_name
password: secret
is accessible by
APP_CONFIG = YAML.load_file("#{Rails.root}/config/app_config.yml")[Rails.env]
APP_CONFIG['development']['username']
# => "development_name"
I you want a specific key to be a symbol, you should prefix it with : in the YAML file.
development:
:username: development_name
:password: secret
APP_CONFIG = YAML.load_file("#{Rails.root}/config/app_config.yml")[Rails.env]
APP_CONFIG['development'][:username]
# => "development_name"
APP_CONFIG['development']['username']
# => nil
Normally, this is not done because this is a specific Ruby behavior. Other languages might not be happy about the leading :.
If you specifically wants to access keys as symbol, you can either use symbolize_keys!
APP_CONFIG = YAML.load_file("#{Rails.root}/config/app_config.yml")[Rails.env].simbolize_keys!
but most of the time, the effort is not worth. Internally, the 90% of libraries converts Symbols to Strings during a comparison, especially when you deal with hashes with indifferent access. So, at the end of the story, you might want to keep strings in this case.
Last option would be to create a HashWithIndifferentAccess
APP_CONFIG = HashWithIndifferentAccess.new(YAML.load_file("#{Rails.root}/config/app_config.yml")[Rails.env])
This will allow you to access
APP_CONFIG[:development][:username]
APP_CONFIG['development'][:username]
APP_CONFIG['development']['username']
indifferently. It works by storing the hash keys to string internally and converting the request to [] to string, so that it always works. This is the class used by several Rails components, including the famous params[] hash in the controllers.
Use symbolize_keys on the hash returned by YAML.load_file

Can a YML file access another YML file?

We have a site wide config.yml file which contacts api keys etc...
Can another one of my YML files access a value in the config.yml?
config.yml:
development:
thing: 123123123123
plugin_config.yml:
development:
thing: config.yml.development.thing
is this possible?
You can always parse it with ERB:
development:
thing: 123123123123
development:
thing: <%= YAML.load(ERB.new(File.read(Rails.root.join('config','config.yml'))).result)['development'] %>
Then load the first one and also parse it with ERB (in an initializer or something):
CONFIG = YAML.load(ERB.new(File.read(Rails.root.join('config','plugin_config.yml'))).result)

What is the best way to keep web app config?

If I have some config for web admin to set e.g. number of post per page, some enum showing choice. How should I keep this settings in db ? Should I serialize it and save as blob.
Thanks,
I using rails and I want it to dynamically change this setting through web interface, so I think environment.rb would not fit this situation. So I should have a extra table with two tuples as name, value ?
Most languages/frameworks have a config file of sorts. such as the web.config in ASP or the environment.rb files in RoR. You could use one of these.
Or failing that have a key value pair table in your database.
If you're wanting to do this dynamically through the website I would definitely go for the key value pair table.
For the dynamic config values, you should create a model called Configuration with keys and values. I generally have multiple value columns (for number, string, and date) and then call the appropriate method for the configuration.
For "enums" you should create lookup tables with foreign key relationships to where they attach. For example if you have a Post model and you want an enumeration of Category, you should make the Post belong_to :category and Category has_many :posts.
Use a YAML file. YAML is way simpler than XML.
Make a file called "config.yml" in "config" directory. And load the file using YAML::load(). You can make a setting for each environment by naming the first level as environment (e.g., production, development, test).
See this episode of RailsCasts for details.
If you are using asp.net you can use the Web.Config file.
See Asp .net Web.config Configuration File
You could to create a single table in your database to store key-value pairs.
This is what I use. Got the idea from elsewhere, but the implementation is mine. Pulled from a production project of mine:
class AppConfig
# Loads a YAML configuration file from RAILS_ROOT/config/. The default file
# it looks for is 'application.yml', although if this doesn't match your
# application, you can pass in an alternative value as an argument
# to AppConfig.load.
# After the file has been loaded, any inline ERB is evaluated and unserialized
# into a hash. For each key-value pair in the hash, class getter and setter methods
# are defined i.e., AppConfig.key => "value"
# This allows you to store your application configuration information e.g., API keys and
# authentication credentials in a convenient manner, external to your application source
#
# application.yml example
#
# :defaults: &defaults
# :app_name: Platform
# :app_domain: dev.example.com
# :admin_email: admin#example.com
# :development:
# <<: *defaults
# :test:
# <<: *defaults
# :production:
# <<: *defaults
# :app_domain: example.com
#
# For example will result in AppConfig.app_domain => "dev.example.com"
# when Rails.env == "development"
#
class << self
def load(file='application.yml')
configuration_file = File.join Rails.root, 'config', file
File.open(configuration_file) do |configuration|
configuration = ERB.new(configuration.read).result
configuration = YAML.load(configuration)[Rails.env.to_sym]
configuration.each do |key, value|
cattr_accessor key
send "#{key}=", value
end
end if File.exists? configuration_file
end
end
end
AppConfig.load
Create config/initializers/app_config.rb and paste the above code into it. I'm going to make this into a gem. I figure other people will find it useful.
EDIT: Just saw you wish to edit the config as the app runs via a web based interface. You could do this with this method as both getter and setter methods are defined for each attribute.
in your controller:
def update
params[:configuration].each { |k,v| AppConfig.send "#{k}=", v }
…
end
I don't find a model is the right solution here. Forget about the DB overheard, the idea of being able to instantiate something that controls app configuration doesn't make sense. What's more how you implement it? An instance for each tuple?! It should be a singleton class.

Resources