Rails 3 - how to use an environment-specific configuration in haml partial - ruby-on-rails-3

Following the answer on How to define custom configuration variables in rails, I am trying to set up a configuration settings for different environments in config/environments/{env}.rb
e.g. in development.rb I set
config.elvis = 'alive'
and then in my haml template I can use this variable, e.g.
Elvis is #{Rails.configuration.elvis}.
However, when I want to wrap this in a condition:
- if Rails.configuration.elvis
<p>Elvis is #{Rails.configuration.elvis}</p>
it also works, but if the configuration isn't set, it throws a undefined method error.
If I try instead:
- if defined? Rails.configuration.elvis
<p>Elvis is #{Rails.configuration.elvis}</p>
it seems to always evaluate as false, even with the configuration defined.
Still very new to rails/ruby, so apologies if it's a very dumb question

You could use respond_to?:
- if Rails.configuration.respond_to?(:elvis)
<p>Elvis is #{Rails.configuration.elvis}</p>

Related

Scrapy : How to write a HttpProxyMiddleware?

The docs of Scrapy says about HttpProxyMiddleware is like this:
This middleware sets the HTTP proxy to use for requests, by setting the proxy meta value for Request objects.
Like the Python standard library modules urllib and urllib2, it obeys the following environment variables:
http_proxy
https_proxy
no_proxy
You can also set the meta key proxy per-request, to a value like http://some_proxy_server:port or http://username:password#some_proxy_server:port. Keep in mind this value will take precedence over http_proxy/https_proxy environment variables, and it will also ignore no_proxy environment variable.
docs:https://doc.scrapy.org/en/latest/topics/downloader-middleware.html?highlight=Proxy#module-scrapy.downloadermiddlewares.httpproxy
But there are no examples in the docs.
I have no ideas how to write a HttpProxyMiddleware.
Are there any suggestions?
In settings.py just do this.
DOWNLOADER_MIDDLEWARES = {
'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 100
}
And then while yielding each request do this
yield Request(meta={'proxy': "http://%s"%(random.choice(["IP:PORT", "IP:PORT"]))})
That's it!
You don't need to write one. HttpProxyMiddleware already exists in Scrapy.
As docs state, there are two ways of letting Scrapy know you need your requests to go through a proxy:
Setting environment variables
(e.g. from the command line)
export http_proxy="http://username:password#host:port"
You can also set the meta key "proxy" per-request, to a value like http://some_proxy_server:port or http://username:password#some_proxy_server:port.
Keep in mind this value will take precedence over http_proxy/https_proxy environment variables, and it will also ignore no_proxy environment variable
e.g.
yield Request("http://google.com", meta={'proxy':'http://username:password#some_proxy_server:port'}, callback=self.some_method)

getting a "need project id error" in Keen

I get the following error:
Keen.delete(:iron_worker_analytics, filters: [{:property_name => 'start_time', :operator => 'eq', :property_value => '0001-01-01T00:00:00Z'}])
Keen::ConfigurationError: Keen IO Exception: Project ID must be set
However, when I set the value, I get the following:
warning: already initialized constant KEEN_PROJECT_ID
iron.io/env.rb:36: warning: previous definition of KEEN_PROJECT_ID was here
Keen works fine when I run the app and load the values from a env.rb file but from the console I cannot get past this.
I am using the ruby gem.
I figured it out. The documentation is confusing. Per the documentation:
https://github.com/keenlabs/keen-gem
The recommended way to set keys is via the environment. The keys you
can set are KEEN_PROJECT_ID, KEEN_WRITE_KEY, KEEN_READ_KEY and
KEEN_MASTER_KEY. You only need to specify the keys that correspond to
the API calls you'll be performing. If you're using foreman, add this
to your .env file:
KEEN_PROJECT_ID=aaaaaaaaaaaaaaa
KEEN_MASTER_KEY=xxxxxxxxxxxxxxx
KEEN_WRITE_KEY=yyyyyyyyyyyyyyy KEEN_READ_KEY=zzzzzzzzzzzzzzz If not,
make a script to export the variables into your shell or put it before
the command you use to start your server.
But I had to set it explicitly as Keen.project_id after doing a Keen.methods.
It's sort of confusing since from the docs, I assumed I just need to set the variables. Maybe I am misunderstanding the docs but it was confusing at least to me.

How to set a condition with #auth.requires_login in Web2py

In my web2py web app, the controller function def index(): has the decorator #auth.requires_login().
For development and testing purpose I comment out this decorator. But I often forget to uncomment it before committing the code.
I would like to change this decorator into something that would test if a file is present (i.e. skipLogin) and if not to require login. I can then add the skipLogin file in my .gitignore file and don't need to worry about commenting and uncommenting the decorator line.
I suppose it should be something like #auth.requires(lambda: xxx) but I have no idea what xxx should be.
auth.requires takes a requires_login argument, so you can just set the condition to True, and then conditionally set the value of requires_login. For example, you can set it to require login for non-local requests:
#auth.requires(True, requires_login=not request.is_local)

Gradle / Groovy properties

I would like to control 'global' config in Gradle build scripts using external property files on each build machine (dev, ci, uat,...) and specify the filename with a command line argument.
e.g. gradle -DbuildProperties=/example/config/build.properties
I specifically don't want to use gradle.properties as we have existing projects that already use this approach and (for example) we want to be able to amend database urls and jdbc drivers without having to change every project.
So far have tried:-
Properties props = new Properties()
props.load(new FileInputStream("$filename"))
project.setProperty('props', props)
which works but has a deprecated warning, but I can't figure out how to avoid this.
Have also tried using groovy style config files with ConfigSlurper:-
environments {
dev {
db.security {
driver=net.sourceforge.jtds.jdbc.Driver
url=jdbc:someserver://somehost:1234/some_db
username=userId
password=secret
}
}
}
but the colons and forward slashes are causing exceptions and we don't want to have to mess up config with escape characters.
There must be a non-deprecated way to do this - can anyone suggest the 'right' way to do it?
Thanks
You can get rid of the deprecated warning quite easily. The message you got probably looks something like this:
Creating properties on demand (a.k.a. dynamic properties) has been deprecated and is scheduled to be removed in Gradle 2.0. Please read http://gradle.org/docs/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html for information on the replacement for dynamic properties.
Deprecated dynamic property: "props" on "root project 'private'", value: "true".
It can be fixed by replacing:
project.setProperty('props', props)
with
project.ext.props = props
Just to supplement the response given by #Steinar:
it's still possible to use next syntax:
project.ext.set('prop_name', prop_value)
in case you have several properties from file:
props.each({ project.ext.set(it.key, it.value)} )

change rails environment in the mid of testing

How to change the environment variable of rails in testing
You could do
Rails.stub(env: ActiveSupport::StringInquirer.new("production"))
Then Rails.env, Rails.development? etc will work as expected.
With RSpec 3 or later you may want to use the new "zero monkeypatching" syntax (as mentioned by #AnkitG in another answer) to avoid deprecation warnings:
allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new("production"))
I usually define a stub_env method in a spec helper so I don't have to put all that stuff inline in my tests.
An option to consider (as suggested in a comment here) is to instead rely on some more targeted configuration that you can set in your environment files and change in tests.
Rspec 3 onwards you can do
it "should do something specific for production" do
allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new("production"))
#other assertions
end
Sometimes returning a different environment variable can be a headache (required production environment variables, warning messages, etc).
Depending on your case, as an alternate you may be able to simply return the value you need for your test to think it's in another environment. Such as if you wanted Rails to believe it is in production for code that checks Rails.env.production? you could do something like this:
it "does something specific when in production" do
allow(Rails.env).to receive(:production?).and_return(true)
##other assertions
end
You could do the same for other environments, such as :development?, :staging?, etc. If you don't need the full capacity of returning a full environment, this could be another option.
As a simpler variation on several answers above, this is working for me:
allow(Rails).to receive(:env).and_return('production')
Or, for as I'm doing in shared_examples, pass that in a variable:
allow(Rails).to receive(:env).and_return(target_env)
I suspect this falls short of the ...StringInquirer... solution as your app uses additional methods to inspect the environment (e.g. env.production?, but if you code just asks for Rails.env, this is a lot more readable. YMMV.
If you're using something like rspec, you can stub Rails.env to return a different value for the specific test example you're running:
it "should log something in production" do
Rails.stub(:env).and_return('production')
Rails.logger.should_receive(:warning).with("message")
run_your_code
end