Discussion:
[Cucumber:3023] features specs constants and rails
Andrew Premdas
2010-01-02 21:17:09 UTC
Permalink
Hi all,

First of all apologies for this borderline off-topic post. I think it has
enough of a Cucumber element to be worth posting here

Looking for some comment on a general policy I'm trying to create for
dealing with various settings in our application. We have a number of things
like postage_rate, vat_rate, image_path etc. etc. which in our production
environment will be CONSTANTS. All of these things however need to be set to
a variety of values when running features and spec. What I am trying to do
is work out the best way to do this in a Rails app.

Currently my thinking is to make all these things CONSTANTS in a module in
an initializer, and then to freeze this module in production.rb. So a simple
version might be

module AppConstants
module Postage
RATE = 399
end

module Images
PATH = "#{RAILS_ROOT}/public/images"
end
end

and the last line of production.rb would be

AppConstants.freeze

Does this make sense? What do you do to address this problem?

I believe this approach will result in a lot of warnings being generated
when we run our features. Is there a way to turn the warnings of?

Thankyou for your help

Andrew

--

You received this message because you are subscribed to the Google Groups "Cukes" group.
To post to this group, send email to cukes-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to cukes+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
For more options, visit this group at http://groups.google.com/group/cukes?hl=en.
Bharat
2010-01-03 20:04:25 UTC
Permalink
Hello Andrew,
I am not a Cucumber Guru by any stretch of imagination, but I know
Rails fairly well. It seems to me that your concern might not be a
concern after all. All you have to do is require the class that you
are defining your constants in an appropriate place. e.g., test.rb in
Rails_root/conf/environments or env.rb file in your features/support/
env.rb and you should be all set.
I would encourage you to try with just one or two such constant
definitions. Speaking of class, you don't want to create inner
modules, instead, create classes as follows:

module AppConstants
class Postage
RATE = 399
end

class Images
PATH = "#{RAILS_ROOT}/public/images"
end
end

This should work.

Bharat

--

You received this message because you are subscribed to the Google Groups "Cukes" group.
To post to this group, send email to cukes-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to cukes+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
For more options, visit this group at http://groups.google.com/group/cukes?hl=en.
Andrew Premdas
2010-01-03 20:40:18 UTC
Permalink
Post by Bharat
Hello Andrew,
I am not a Cucumber Guru by any stretch of imagination, but I know
Rails fairly well. It seems to me that your concern might not be a
concern after all. All you have to do is require the class that you
are defining your constants in an appropriate place. e.g., test.rb in
Rails_root/conf/environments or env.rb file in your features/support/
env.rb and you should be all set.
I would encourage you to try with just one or two such constant
definitions. Speaking of class, you don't want to create inner
module AppConstants
class Postage
RATE = 399
end
class Images
PATH = "#{RAILS_ROOT}/public/images"
end
end
This should work.
Bharat
--
You received this message because you are subscribed to the Google Groups "Cukes" group.
To unsubscribe from this group, send email to
For more options, visit this group at
http://groups.google.com/group/cukes?hl=en.
Thanks for your reply Bharat, but I think you've missed the point. The
question isn't about how to define constants in Rails, its more about how to
define constants in a way that features and specs can change there values
when they run whilst keeping the constants as constant as possible when we
are running in production.

--

You received this message because you are subscribed to the Google Groups "Cukes" group.
To post to this group, send email to cukes-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to cukes+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
For more options, visit this group at http://groups.google.com/group/cukes?hl=en.
Matt Wynne
2010-01-03 23:39:50 UTC
Permalink
Post by Andrew Premdas
Hi all,
First of all apologies for this borderline off-topic post. I think
it has enough of a Cucumber element to be worth posting here
Looking for some comment on a general policy I'm trying to create
for dealing with various settings in our application. We have a
number of things like postage_rate, vat_rate, image_path etc. etc.
which in our production environment will be CONSTANTS. All of these
things however need to be set to a variety of values when running
features and spec. What I am trying to do is work out the best way
to do this in a Rails app.
Currently my thinking is to make all these things CONSTANTS in a
module in an initializer, and then to freeze this module in
production.rb. So a simple version might be
module AppConstants
module Postage
RATE = 399
end
module Images
PATH = "#{RAILS_ROOT}/public/images"
end
end
and the last line of production.rb would be
AppConstants.freeze
Does this make sense? What do you do to address this problem?
I believe this approach will result in a lot of warnings being
generated when we run our features. Is there a way to turn the
warnings of?
Thankyou for your help
Andrew
Hi Andrew,

I tend to take a slightly softer approach to this problem. I've seen a
pattern emerge where we use static attributes, rather than constants,
to hold / access these global constants. In the features we might then
change the value of that static attribute for the duration of a
scenario, then reset it again with an After hook.

class PostageSettings
attr_accessor :rate
def initialize
@rate = 999
end
end

module AppSettings
Postage = PostageSettings.new
end

module AfterCurrentScenario
def after_current_scenario(&block)
@after_blocks ||= []
@after_blocks << &block
end

def run_after_blocks
@after_blocks.each { |b| b.call }
@after_blocks = []
end
end

After do
run_after_blocks
end

Given /the postage rate is 101/ do
old_postage_rate = AppSettings::Postage.rate
after_current_scenario do
AppSettings::Postage.rate = old_postage_rate
end
AppSettings::Postage.rate = 101
end



cheers,
Matt

http://mattwynne.net
+447974 430184

--

You received this message because you are subscribed to the Google Groups "Cukes" group.
To post to this group, send email to cukes-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to cukes+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
For more options, visit this group at http://groups.google.com/group/cukes?hl=en.
Lenny Marks
2010-01-05 23:12:25 UTC
Permalink
Post by Matt Wynne
Post by Andrew Premdas
Hi all,
First of all apologies for this borderline off-topic post. I think
it has enough of a Cucumber element to be worth posting here
Looking for some comment on a general policy I'm trying to create
for dealing with various settings in our application. We have a
number of things like postage_rate, vat_rate, image_path etc. etc.
which in our production environment will be CONSTANTS. All of these
things however need to be set to a variety of values when running
features and spec. What I am trying to do is work out the best way
to do this in a Rails app.
Currently my thinking is to make all these things CONSTANTS in a
module in an initializer, and then to freeze this module in
production.rb. So a simple version might be
module AppConstants
module Postage
RATE = 399
end
module Images
PATH = "#{RAILS_ROOT}/public/images"
end
end
and the last line of production.rb would be
AppConstants.freeze
Does this make sense? What do you do to address this problem?
I believe this approach will result in a lot of warnings being
generated when we run our features. Is there a way to turn the
warnings of?
Thankyou for your help
Andrew
Hi Andrew,
I tend to take a slightly softer approach to this problem. I've seen a
pattern emerge where we use static attributes, rather than constants,
to hold / access these global constants. In the features we might then
change the value of that static attribute for the duration of a
scenario, then reset it again with an After hook.
class PostageSettings
attr_accessor :rate
def initialize
@rate = 999
end
end
module AppSettings
Postage = PostageSettings.new
end
module AfterCurrentScenario
def after_current_scenario(&block)
@after_blocks ||= []
@after_blocks << &block
end
def run_after_blocks
@after_blocks.each { |b| b.call }
@after_blocks = []
end
end
After do
run_after_blocks
end
Given /the postage rate is 101/ do
old_postage_rate = AppSettings::Postage.rate
after_current_scenario do
AppSettings::Postage.rate = old_postage_rate
end
AppSettings::Postage.rate = 101
end
cheers,
Matt
I would do something like Matt suggests for setting/resetting in
Cucumber. I'd suggest something like the following for the actual
AppSetting type class instead of using constants so you can avoid the
"warning: already initialized constant " thing.

class AppSettings
class << self
attr_accessor :postage_rate
end
..
end

As you suggest, you could then freeze it in production env for the
extra security.

-lenny
Andrew Premdas
2010-01-06 15:38:54 UTC
Permalink
Post by Andrew Premdas
Hi all,
Post by Andrew Premdas
First of all apologies for this borderline off-topic post. I think
it has enough of a Cucumber element to be worth posting here
Looking for some comment on a general policy I'm trying to create
for dealing with various settings in our application. We have a
number of things like postage_rate, vat_rate, image_path etc. etc.
which in our production environment will be CONSTANTS. All of these
things however need to be set to a variety of values when running
features and spec. What I am trying to do is work out the best way
to do this in a Rails app.
Currently my thinking is to make all these things CONSTANTS in a
module in an initializer, and then to freeze this module in
production.rb. So a simple version might be
module AppConstants
module Postage
RATE = 399
end
module Images
PATH = "#{RAILS_ROOT}/public/images"
end
end
and the last line of production.rb would be
AppConstants.freeze
Does this make sense? What do you do to address this problem?
I believe this approach will result in a lot of warnings being
generated when we run our features. Is there a way to turn the
warnings of?
Thankyou for your help
Andrew
Hi Andrew,
I tend to take a slightly softer approach to this problem. I've seen a
pattern emerge where we use static attributes, rather than constants,
to hold / access these global constants. In the features we might then
change the value of that static attribute for the duration of a
scenario, then reset it again with an After hook.
class PostageSettings
attr_accessor :rate
def initialize
@rate = 999
end
end
module AppSettings
Postage = PostageSettings.new
end
module AfterCurrentScenario
def after_current_scenario(&block)
@after_blocks ||= []
@after_blocks << &block
end
def run_after_blocks
@after_blocks.each { |b| b.call }
@after_blocks = []
end
end
After do
run_after_blocks
end
Given /the postage rate is 101/ do
old_postage_rate = AppSettings::Postage.rate
after_current_scenario do
AppSettings::Postage.rate = old_postage_rate
end
AppSettings::Postage.rate = 101
end
cheers,
Matt
I would do something like Matt suggests for setting/resetting in Cucumber.
I'd suggest something like the following for the actual AppSetting type
class instead of using constants so you can avoid the "warning: already
initialized constant " thing.
class AppSettings
class << self
attr_accessor :postage_rate
end
..
end
As you suggest, you could then freeze it in production env for the extra
security.
-lenny
This is using class variables for persistent storage and has some problems
with Rails in particular

i) it is very flakey in development mode, due to class reloading issues
ii) it (apparently) can be flakey in production mode in complex setups.

The problem is that although you may have loaded the class in some
initializer, at some later point it may not exist. So when you call code
like
AppSettings.postage_rate

you get an error like 'no method postage_rate for nil object'

This thread is about finding better ways to define these sorts of things
that avoid these probs.

Cheers

Andrew
--
You received this message because you are subscribed to the Google Groups "Cukes" group.
To unsubscribe from this group, send email to
For more options, visit this group at
http://groups.google.com/group/cukes?hl=en.
Lenny Marks
2010-01-06 16:25:22 UTC
Permalink
Post by Andrew Premdas
Hi all,
First of all apologies for this borderline off-topic post. I think
it has enough of a Cucumber element to be worth posting here
Looking for some comment on a general policy I'm trying to create
for dealing with various settings in our application. We have a
number of things like postage_rate, vat_rate, image_path etc. etc.
which in our production environment will be CONSTANTS. All of these
things however need to be set to a variety of values when running
features and spec. What I am trying to do is work out the best way
to do this in a Rails app.
Currently my thinking is to make all these things CONSTANTS in a
module in an initializer, and then to freeze this module in
production.rb. So a simple version might be
module AppConstants
module Postage
RATE = 399
end
module Images
PATH = "#{RAILS_ROOT}/public/images"
end
end
and the last line of production.rb would be
AppConstants.freeze
Does this make sense? What do you do to address this problem?
I believe this approach will result in a lot of warnings being
generated when we run our features. Is there a way to turn the
warnings of?
Thankyou for your help
Andrew
Hi Andrew,
I tend to take a slightly softer approach to this problem. I've seen a
pattern emerge where we use static attributes, rather than constants,
to hold / access these global constants. In the features we might then
change the value of that static attribute for the duration of a
scenario, then reset it again with an After hook.
class PostageSettings
attr_accessor :rate
def initialize
@rate = 999
end
end
module AppSettings
Postage = PostageSettings.new
end
module AfterCurrentScenario
def after_current_scenario(&block)
@after_blocks ||= []
@after_blocks << &block
end
def run_after_blocks
@after_blocks.each { |b| b.call }
@after_blocks = []
end
end
After do
run_after_blocks
end
Given /the postage rate is 101/ do
old_postage_rate = AppSettings::Postage.rate
after_current_scenario do
AppSettings::Postage.rate = old_postage_rate
end
AppSettings::Postage.rate = 101
end
cheers,
Matt
I would do something like Matt suggests for setting/resetting in
Cucumber. I'd suggest something like the following for the actual
AppSetting type class instead of using constants so you can avoid
the "warning: already initialized constant " thing.
class AppSettings
class << self
attr_accessor :postage_rate
end
..
end
As you suggest, you could then freeze it in production env for the
extra security.
-lenny
This is using class variables for persistent storage and has some
problems with Rails in particular
i) it is very flakey in development mode, due to class reloading issues
ii) it (apparently) can be flakey in production mode in complex setups.
The problem is that although you may have loaded the class in some
initializer, at some later point it may not exist. So when you call
code like
AppSettings.postage_rate
you get an error like 'no method postage_rate for nil object'
This thread is about finding better ways to define these sorts of
things that avoid these probs.
Is it really a problem? I avoid everything you site above with one
explicit require in one of my Rails initializers(config/
initializers/) . As long as the constant is defined before Rails
initialization is done the class will not be reloaded. Its never
caused me any grief.

-lenny
Post by Andrew Premdas
--
You received this message because you are subscribed to the Google Groups "Cukes" group.
.
For more options, visit this group at http://groups.google.com/group/cukes?hl=en
.
--
You received this message because you are subscribed to the Google Groups "Cukes" group.
.
For more options, visit this group at http://groups.google.com/group/cukes?hl=en
.
Andrew Premdas
2010-01-06 17:15:59 UTC
Permalink
Post by Andrew Premdas
Post by Andrew Premdas
Hi all,
Post by Andrew Premdas
First of all apologies for this borderline off-topic post. I think
it has enough of a Cucumber element to be worth posting here
Looking for some comment on a general policy I'm trying to create
for dealing with various settings in our application. We have a
number of things like postage_rate, vat_rate, image_path etc. etc.
which in our production environment will be CONSTANTS. All of these
things however need to be set to a variety of values when running
features and spec. What I am trying to do is work out the best way
to do this in a Rails app.
Currently my thinking is to make all these things CONSTANTS in a
module in an initializer, and then to freeze this module in
production.rb. So a simple version might be
module AppConstants
module Postage
RATE = 399
end
module Images
PATH = "#{RAILS_ROOT}/public/images"
end
end
and the last line of production.rb would be
AppConstants.freeze
Does this make sense? What do you do to address this problem?
I believe this approach will result in a lot of warnings being
generated when we run our features. Is there a way to turn the
warnings of?
Thankyou for your help
Andrew
Hi Andrew,
I tend to take a slightly softer approach to this problem. I've seen a
pattern emerge where we use static attributes, rather than constants,
to hold / access these global constants. In the features we might then
change the value of that static attribute for the duration of a
scenario, then reset it again with an After hook.
class PostageSettings
attr_accessor :rate
def initialize
@rate = 999
end
end
module AppSettings
Postage = PostageSettings.new
end
module AfterCurrentScenario
def after_current_scenario(&block)
@after_blocks ||= []
@after_blocks << &block
end
def run_after_blocks
@after_blocks.each { |b| b.call }
@after_blocks = []
end
end
After do
run_after_blocks
end
Given /the postage rate is 101/ do
old_postage_rate = AppSettings::Postage.rate
after_current_scenario do
AppSettings::Postage.rate = old_postage_rate
end
AppSettings::Postage.rate = 101
end
cheers,
Matt
I would do something like Matt suggests for setting/resetting in Cucumber.
I'd suggest something like the following for the actual AppSetting type
class instead of using constants so you can avoid the "warning: already
initialized constant " thing.
class AppSettings
class << self
attr_accessor :postage_rate
end
..
end
As you suggest, you could then freeze it in production env for the extra
security.
-lenny
This is using class variables for persistent storage and has some problems
with Rails in particular
i) it is very flakey in development mode, due to class reloading issues
ii) it (apparently) can be flakey in production mode in complex setups.
The problem is that although you may have loaded the class in some
initializer, at some later point it may not exist. So when you call code
like
AppSettings.postage_rate
you get an error like 'no method postage_rate for nil object'
This thread is about finding better ways to define these sorts of things
that avoid these probs.
Is it really a problem? I avoid everything you site above with one explicit
require in one of my Rails initializers(config/initializers/) . As long as
the constant is defined before Rails initialization is done the class will
not be reloaded. Its never caused me any grief.
I can confirm it really is a problem in development mode. In production well
I'm not so sure. If you have a look at http://gist.github.com/270423. The
exception on line 10 in payment.rb is often raised in development mode under
rails, but never in test mode. I've cut alot of the actual code out (for
clarity), but hopefully it should be clear enough.

hope this is useful

Andrew

-lenny
Post by Andrew Premdas
--
You received this message because you are subscribed to the Google Groups "Cukes" group.
To unsubscribe from this group, send email to
.
For more options, visit this group at
http://groups.google.com/group/cukes?hl=en.
--
You received this message because you are subscribed to the Google Groups "Cukes" group.
To unsubscribe from this group, send email to
For more options, visit this group at
http://groups.google.com/group/cukes?hl=en.
--
You received this message because you are subscribed to the Google Groups "Cukes" group.
To unsubscribe from this group, send email to
For more options, visit this group at
http://groups.google.com/group/cukes?hl=en.
Lenny Marks
2010-01-06 17:44:33 UTC
Permalink
Post by Lenny Marks
Post by Andrew Premdas
Hi all,
First of all apologies for this borderline off-topic post. I think
it has enough of a Cucumber element to be worth posting here
Looking for some comment on a general policy I'm trying to create
for dealing with various settings in our application. We have a
number of things like postage_rate, vat_rate, image_path etc. etc.
which in our production environment will be CONSTANTS. All of these
things however need to be set to a variety of values when running
features and spec. What I am trying to do is work out the best way
to do this in a Rails app.
Currently my thinking is to make all these things CONSTANTS in a
module in an initializer, and then to freeze this module in
production.rb. So a simple version might be
module AppConstants
module Postage
RATE = 399
end
module Images
PATH = "#{RAILS_ROOT}/public/images"
end
end
and the last line of production.rb would be
AppConstants.freeze
Does this make sense? What do you do to address this problem?
I believe this approach will result in a lot of warnings being
generated when we run our features. Is there a way to turn the
warnings of?
Thankyou for your help
Andrew
Hi Andrew,
I tend to take a slightly softer approach to this problem. I've seen a
pattern emerge where we use static attributes, rather than constants,
to hold / access these global constants. In the features we might then
change the value of that static attribute for the duration of a
scenario, then reset it again with an After hook.
class PostageSettings
attr_accessor :rate
def initialize
@rate = 999
end
end
module AppSettings
Postage = PostageSettings.new
end
module AfterCurrentScenario
def after_current_scenario(&block)
@after_blocks ||= []
@after_blocks << &block
end
def run_after_blocks
@after_blocks.each { |b| b.call }
@after_blocks = []
end
end
After do
run_after_blocks
end
Given /the postage rate is 101/ do
old_postage_rate = AppSettings::Postage.rate
after_current_scenario do
AppSettings::Postage.rate = old_postage_rate
end
AppSettings::Postage.rate = 101
end
cheers,
Matt
I would do something like Matt suggests for setting/resetting in
Cucumber. I'd suggest something like the following for the actual
AppSetting type class instead of using constants so you can avoid
the "warning: already initialized constant " thing.
class AppSettings
class << self
attr_accessor :postage_rate
end
..
end
As you suggest, you could then freeze it in production env for the
extra security.
-lenny
This is using class variables for persistent storage and has some
problems with Rails in particular
i) it is very flakey in development mode, due to class
reloading issues
ii) it (apparently) can be flakey in production mode in complex setups.
The problem is that although you may have loaded the class in some
initializer, at some later point it may not exist. So when you call
code like
AppSettings.postage_rate
you get an error like 'no method postage_rate for nil object'
This thread is about finding better ways to define these sorts of
things that avoid these probs.
Is it really a problem? I avoid everything you site above with one
explicit require in one of my Rails initializers(config/
initializers/) . As long as the constant is defined before Rails
initialization is done the class will not be reloaded. Its never
caused me any grief.
I can confirm it really is a problem in development mode. In
production well I'm not so sure. If you have a look at http://gist.github.com/270423
. The exception on line 10 in payment.rb is often raised in
development mode under rails, but never in test mode. I've cut alot
of the actual code out (for clarity), but hopefully it should be
clear enough.
hope this is useful
Andrew
Its only a problem because your class variable lives in a model class
which is reloaded in development causing it to disappear.

If instead you handle it like here: http://gist.github.com/270446
there is no problem because the AppConfig class will not be
reloaded(because it is required before initialization is complete)

-lenny
Post by Lenny Marks
-lenny
Post by Andrew Premdas
--
You received this message because you are subscribed to the Google Groups "Cukes" group.
.
For more options, visit this group at http://groups.google.com/group/cukes?hl=en
.
--
You received this message because you are subscribed to the Google Groups "Cukes" group.
.
For more options, visit this group at http://groups.google.com/group/cukes?hl=en
.
--
You received this message because you are subscribed to the Google Groups "Cukes" group.
.
For more options, visit this group at http://groups.google.com/group/cukes?hl=en
.
--
You received this message because you are subscribed to the Google Groups "Cukes" group.
.
For more options, visit this group at http://groups.google.com/group/cukes?hl=en
.
Andrew Premdas
2010-01-06 18:10:17 UTC
Permalink
Post by Andrew Premdas
Post by Andrew Premdas
Post by Lenny Marks
Post by Andrew Premdas
Hi all,
Post by Andrew Premdas
First of all apologies for this borderline off-topic post. I think
it has enough of a Cucumber element to be worth posting here
Looking for some comment on a general policy I'm trying to create
for dealing with various settings in our application. We have a
number of things like postage_rate, vat_rate, image_path etc. etc.
which in our production environment will be CONSTANTS. All of these
things however need to be set to a variety of values when running
features and spec. What I am trying to do is work out the best way
to do this in a Rails app.
Currently my thinking is to make all these things CONSTANTS in a
module in an initializer, and then to freeze this module in
production.rb. So a simple version might be
module AppConstants
module Postage
RATE = 399
end
module Images
PATH = "#{RAILS_ROOT}/public/images"
end
end
and the last line of production.rb would be
AppConstants.freeze
Does this make sense? What do you do to address this problem?
I believe this approach will result in a lot of warnings being
generated when we run our features. Is there a way to turn the
warnings of?
Thankyou for your help
Andrew
Hi Andrew,
I tend to take a slightly softer approach to this problem. I've seen a
pattern emerge where we use static attributes, rather than constants,
to hold / access these global constants. In the features we might then
change the value of that static attribute for the duration of a
scenario, then reset it again with an After hook.
class PostageSettings
attr_accessor :rate
def initialize
@rate = 999
end
end
module AppSettings
Postage = PostageSettings.new
end
module AfterCurrentScenario
def after_current_scenario(&block)
@after_blocks ||= []
@after_blocks << &block
end
def run_after_blocks
@after_blocks.each { |b| b.call }
@after_blocks = []
end
end
After do
run_after_blocks
end
Given /the postage rate is 101/ do
old_postage_rate = AppSettings::Postage.rate
after_current_scenario do
AppSettings::Postage.rate = old_postage_rate
end
AppSettings::Postage.rate = 101
end
cheers,
Matt
I would do something like Matt suggests for setting/resetting in
Cucumber. I'd suggest something like the following for the actual AppSetting
type class instead of using constants so you can avoid the "warning: already
initialized constant " thing.
class AppSettings
class << self
attr_accessor :postage_rate
end
..
end
As you suggest, you could then freeze it in production env for the extra
security.
-lenny
This is using class variables for persistent storage and has some problems
with Rails in particular
i) it is very flakey in development mode, due to class reloading issues
ii) it (apparently) can be flakey in production mode in complex setups.
The problem is that although you may have loaded the class in some
initializer, at some later point it may not exist. So when you call code
like
AppSettings.postage_rate
you get an error like 'no method postage_rate for nil object'
This thread is about finding better ways to define these sorts of things
that avoid these probs.
Is it really a problem? I avoid everything you site above with one
explicit require in one of my Rails initializers(config/initializers/) . As
long as the constant is defined before Rails initialization is done the
class will not be reloaded. Its never caused me any grief.
I can confirm it really is a problem in development mode. In production
well I'm not so sure. If you have a look at http://gist.github.com/270423.
The exception on line 10 in payment.rb is often raised in development mode
under rails, but never in test mode. I've cut alot of the actual code out
(for clarity), but hopefully it should be clear enough.
hope this is useful
Andrew
Its only a problem because your class variable lives in a model class which
is reloaded in development causing it to disappear.
If instead you handle it like here: http://gist.github.com/270446 there is
no problem because the AppConfig class will not be reloaded(because it is
required before initialization is complete)
-lenny
Thanks for that Lenny

So then are class variables only a problem in Rails models, or is that a
simplification. Is the bad rep of class variables in Rails just due to this
particular problem? Finally can we be sure AppConfig will behave correctly
in a complex production configuration.

all best

Andrew
Matt Wynne
2010-01-06 19:10:04 UTC
Permalink
Post by Andrew Premdas
Is the bad rep of class variables in Rails just due to this
particular problem?
The bad rep of class variables is because they're global variables
lite. I use them sparingly and with caution.

cheers,
Matt

http://mattwynne.net
+447974 430184
Andrew Premdas
2010-01-07 00:11:08 UTC
Permalink
Is the bad rep of class variables in Rails just due to this particular
Post by Andrew Premdas
problem?
The bad rep of class variables is because they're global variables lite. I
use them sparingly and with caution.
I find this really bizarre, is this just a Ruby thing? Class variables have
been around in OO languages for ages, and whilst they're usage is pretty
specific, and any write operation to them after class creation is something
that needs careful consideration, they seem pretty standard to me and are
certainly a big improvement over global variables. However in Ruby, they
seem to have an especially bad reputation. I'm not sure if this is because
of the slightly confusing syntax in ruby, the lack of differentiation from
variables for nubies to ruby, or something else that I'm missing. If anyone
could educate me further I'd appreciate it :)
cheers,
Matt
http://mattwynne.net
+447974 430184
--
You received this message because you are subscribed to the Google Groups "Cukes" group.
To unsubscribe from this group, send email to
For more options, visit this group at
http://groups.google.com/group/cukes?hl=en.
Steve Klabnik
2010-01-07 00:20:01 UTC
Permalink
Post by Andrew Premdas
I find this really bizarre, is this just a Ruby thing? Class variables have
been around in OO languages for ages, and whilst they're usage is pretty
specific, and any write operation to them after class creation is something
that needs careful consideration, they seem pretty standard to me and are
certainly a big improvement over global variables. However in Ruby, they
seem to have an especially bad reputation. I'm not sure if this is because
of the slightly confusing syntax in ruby, the lack of differentiation from
variables for nubies to ruby, or something else that I'm missing. If anyone
could educate me further I'd appreciate it :)
I would hazard a guess that it's because Rubyists tend to be all about best
practices. The Ruby community at large places a large social stigma on doing
things the Ugly Way or the Wrong Way. Class variables are one of those grey
areas where it's not really the Wrong Way, but could be. So they get a
slightly larger warning label than other languages' communities have.
Lenny Marks
2010-01-06 19:31:02 UTC
Permalink
Post by Lenny Marks
Post by Lenny Marks
Post by Andrew Premdas
Hi all,
First of all apologies for this borderline off-topic post. I think
it has enough of a Cucumber element to be worth posting here
Looking for some comment on a general policy I'm trying to create
for dealing with various settings in our application. We have a
number of things like postage_rate, vat_rate, image_path etc. etc.
which in our production environment will be CONSTANTS. All of these
things however need to be set to a variety of values when running
features and spec. What I am trying to do is work out the best way
to do this in a Rails app.
Currently my thinking is to make all these things CONSTANTS in a
module in an initializer, and then to freeze this module in
production.rb. So a simple version might be
module AppConstants
module Postage
RATE = 399
end
module Images
PATH = "#{RAILS_ROOT}/public/images"
end
end
and the last line of production.rb would be
AppConstants.freeze
Does this make sense? What do you do to address this problem?
I believe this approach will result in a lot of warnings being
generated when we run our features. Is there a way to turn the
warnings of?
Thankyou for your help
Andrew
Hi Andrew,
I tend to take a slightly softer approach to this problem. I've seen a
pattern emerge where we use static attributes, rather than
constants,
to hold / access these global constants. In the features we might then
change the value of that static attribute for the duration of a
scenario, then reset it again with an After hook.
class PostageSettings
attr_accessor :rate
def initialize
@rate = 999
end
end
module AppSettings
Postage = PostageSettings.new
end
module AfterCurrentScenario
def after_current_scenario(&block)
@after_blocks ||= []
@after_blocks << &block
end
def run_after_blocks
@after_blocks.each { |b| b.call }
@after_blocks = []
end
end
After do
run_after_blocks
end
Given /the postage rate is 101/ do
old_postage_rate = AppSettings::Postage.rate
after_current_scenario do
AppSettings::Postage.rate = old_postage_rate
end
AppSettings::Postage.rate = 101
end
cheers,
Matt
I would do something like Matt suggests for setting/resetting in
Cucumber. I'd suggest something like the following for the actual
AppSetting type class instead of using constants so you can avoid
the "warning: already initialized constant " thing.
class AppSettings
class << self
attr_accessor :postage_rate
end
..
end
As you suggest, you could then freeze it in production env for the
extra security.
-lenny
This is using class variables for persistent storage and has some
problems with Rails in particular
i) it is very flakey in development mode, due to class
reloading issues
ii) it (apparently) can be flakey in production mode in complex setups.
The problem is that although you may have loaded the class in some
initializer, at some later point it may not exist. So when you
call code like
AppSettings.postage_rate
you get an error like 'no method postage_rate for nil object'
This thread is about finding better ways to define these sorts of
things that avoid these probs.
Is it really a problem? I avoid everything you site above with one
explicit require in one of my Rails initializers(config/
initializers/) . As long as the constant is defined before Rails
initialization is done the class will not be reloaded. Its never
caused me any grief.
I can confirm it really is a problem in development mode. In
production well I'm not so sure. If you have a look at http://gist.github.com/270423
. The exception on line 10 in payment.rb is often raised in
development mode under rails, but never in test mode. I've cut alot
of the actual code out (for clarity), but hopefully it should be
clear enough.
hope this is useful
Andrew
Its only a problem because your class variable lives in a model
class which is reloaded in development causing it to disappear.
If instead you handle it like here: http://gist.github.com/270446
there is no problem because the AppConfig class will not be
reloaded(because it is required before initialization is complete)
-lenny
Thanks for that Lenny
So then are class variables only a problem in Rails models, or is
that a simplification.
It would be a problem in any class if it gets reloaded. Here is a
quote I found from http://weblog.rubyonrails.org/2006/8/11/reloading-revamped
that might help explain..

"The actual mechanics of Dependencies are now relatively simple.
Instead of using Reloadable to decide which classes to unload, Rails
records which constants are loaded via const_missing. When the request
is completed, each autoloaded constant is removed, leaving the process
in a clean state. The actual mechanics are slightly more complex, but
not inordinately so. Feel free to open dependencies.rb and peruse the
code."
Post by Lenny Marks
Is the bad rep of class variables in Rails just due to this
particular problem? Finally can we be sure AppConfig will behave
correctly in a complex production configuration.
Depending on what your using attempting to use class variables for it
may still be a problem. As Matt mentioned they are essentially global
variables. For some things like global/write once configuration that
is not a bad thing. I think one major concern about class variables in
Rails(or other) is people attempting to persist state(ex. request
count) which fails miserably in production when requests are most
likely being distributed among multiple processes.

-lenny
Post by Lenny Marks
all best
Andrew
--
You received this message because you are subscribed to the Google Groups "Cukes" group.
.
For more options, visit this group at http://groups.google.com/group/cukes?hl=en
.
Andrew Premdas
2010-01-07 00:27:28 UTC
Permalink
Post by Lenny Marks
Post by Lenny Marks
Post by Andrew Premdas
Hi all,
First of all apologies for this borderline off-topic post. I think
it has enough of a Cucumber element to be worth posting here
Looking for some comment on a general policy I'm trying to create
for dealing with various settings in our application. We have a
number of things like postage_rate, vat_rate, image_path etc. etc.
which in our production environment will be CONSTANTS. All of these
things however need to be set to a variety of values when running
features and spec. What I am trying to do is work out the best way
to do this in a Rails app.
Currently my thinking is to make all these things CONSTANTS in a
module in an initializer, and then to freeze this module in
production.rb. So a simple version might be
module AppConstants
module Postage
RATE = 399
end
module Images
PATH = "#{RAILS_ROOT}/public/images"
end
end
and the last line of production.rb would be
AppConstants.freeze
Does this make sense? What do you do to address this problem?
I believe this approach will result in a lot of warnings being
generated when we run our features. Is there a way to turn the
warnings of?
Thankyou for your help
Andrew
Hi Andrew,
I tend to take a slightly softer approach to this problem. I've seen a
pattern emerge where we use static attributes, rather than constants,
to hold / access these global constants. In the features we might then
change the value of that static attribute for the duration of a
scenario, then reset it again with an After hook.
class PostageSettings
attr_accessor :rate
def initialize
@rate = 999
end
end
module AppSettings
Postage = PostageSettings.new
end
module AfterCurrentScenario
def after_current_scenario(&block)
@after_blocks ||= []
@after_blocks << &block
end
def run_after_blocks
@after_blocks.each { |b| b.call }
@after_blocks = []
end
end
After do
run_after_blocks
end
Given /the postage rate is 101/ do
old_postage_rate = AppSettings::Postage.rate
after_current_scenario do
AppSettings::Postage.rate = old_postage_rate
end
AppSettings::Postage.rate = 101
end
cheers,
Matt
I would do something like Matt suggests for setting/resetting in
Cucumber. I'd suggest something like the following for the actual AppSetting
type class instead of using constants so you can avoid the "warning: already
initialized constant " thing.
class AppSettings
class << self
attr_accessor :postage_rate
end
..
end
As you suggest, you could then freeze it in production env for the extra
security.
-lenny
This is using class variables for persistent storage and has some
problems with Rails in particular
i) it is very flakey in development mode, due to class reloading issues
ii) it (apparently) can be flakey in production mode in complex setups.
The problem is that although you may have loaded the class in some
initializer, at some later point it may not exist. So when you call code
like
AppSettings.postage_rate
you get an error like 'no method postage_rate for nil object'
This thread is about finding better ways to define these sorts of things
that avoid these probs.
Is it really a problem? I avoid everything you site above with one
explicit require in one of my Rails initializers(config/initializers/) . As
long as the constant is defined before Rails initialization is done the
class will not be reloaded. Its never caused me any grief.
I can confirm it really is a problem in development mode. In production
well I'm not so sure. If you have a look at
http://gist.github.com/270423. The exception on line 10 in payment.rb is
often raised in development mode under rails, but never in test mode. I've
cut alot of the actual code out (for clarity), but hopefully it should be
clear enough.
hope this is useful
Andrew
Its only a problem because your class variable lives in a model class
which is reloaded in development causing it to disappear.
If instead you handle it like here: http://gist.github.com/270446 there
is no problem because the AppConfig class will not be reloaded(because it is
required before initialization is complete)
-lenny
Thanks for that Lenny
So then are class variables only a problem in Rails models, or is that a
simplification.
It would be a problem in any class if it gets reloaded. Here is a quote I
found from http://weblog.rubyonrails.org/2006/8/11/reloading-revamped that
might help explain..
"The actual mechanics of Dependencies are now relatively simple. Instead of
using Reloadable to decide which classes to unload, Rails records which
constants are loaded via const_missing. When the request is completed, each
autoloaded constant is removed, leaving the process in a clean state. The
actual mechanics are slightly more complex, but not inordinately so. Feel
free to open dependencies.rb and peruse the code."
So I think this might be why I was thinking that using constants (and then
forcing writes to them if required) would be safer than class variables,
because if the constant could not be found for some reason const_missing
would end up reloading the constant.
Is the bad rep of class variables in Rails just due to this particular
Post by Lenny Marks
problem? Finally can we be sure AppConfig will behave correctly in a complex
production configuration.
Depending on what your using attempting to use class variables for it may
still be a problem. As Matt mentioned they are essentially global variables.
For some things like global/write once configuration that is not a bad
thing. I think one major concern about class variables in Rails(or other) is
people attempting to persist state(ex. request count) which fails miserably
in production when requests are most likely being distributed among multiple
processes.
-lenny
As Ruby provides us with the power to be able to write to constants do we
longer need to use class variables for global/write once configuration? The
flexibility of the language making this particular use case for class
variables redundant?
all best
Post by Lenny Marks
Andrew
--
You received this message because you are subscribed to the Google Groups "Cukes" group.
To unsubscribe from this group, send email to
.
For more options, visit this group at
http://groups.google.com/group/cukes?hl=en.
--
You received this message because you are subscribed to the Google Groups "Cukes" group.
To unsubscribe from this group, send email to
For more options, visit this group at
http://groups.google.com/group/cukes?hl=en.
Andrew Premdas
2010-01-06 15:56:27 UTC
Permalink
Post by Matt Wynne
Post by Andrew Premdas
Hi all,
First of all apologies for this borderline off-topic post. I think
it has enough of a Cucumber element to be worth posting here
Looking for some comment on a general policy I'm trying to create
for dealing with various settings in our application. We have a
number of things like postage_rate, vat_rate, image_path etc. etc.
which in our production environment will be CONSTANTS. All of these
things however need to be set to a variety of values when running
features and spec. What I am trying to do is work out the best way
to do this in a Rails app.
Currently my thinking is to make all these things CONSTANTS in a
module in an initializer, and then to freeze this module in
production.rb. So a simple version might be
module AppConstants
module Postage
RATE = 399
end
module Images
PATH = "#{RAILS_ROOT}/public/images"
end
end
and the last line of production.rb would be
AppConstants.freeze
Does this make sense? What do you do to address this problem?
I believe this approach will result in a lot of warnings being
generated when we run our features. Is there a way to turn the
warnings of?
Thankyou for your help
Andrew
Hi Andrew,
I tend to take a slightly softer approach to this problem. I've seen a
pattern emerge where we use static attributes, rather than constants,
to hold / access these global constants. In the features we might then
change the value of that static attribute for the duration of a
scenario, then reset it again with an After hook.
class PostageSettings
attr_accessor :rate
def initialize
@rate = 999
end
end
module AppSettings
Postage = PostageSettings.new
end
So basically your using instance variables named like classes to avoid the
Rails class variable problem

module AfterCurrentScenario
Post by Matt Wynne
def after_current_scenario(&block)
@after_blocks ||= []
@after_blocks << &block
end
def run_after_blocks
@after_blocks.each { |b| b.call }
@after_blocks = []
end
end
After do
run_after_blocks
end
Given /the postage rate is 101/ do
old_postage_rate = AppSettings::Postage.rate
after_current_scenario do
AppSettings::Postage.rate = old_postage_rate
end
AppSettings::Postage.rate = 101
end
I like this bit, very elegant. Is the location of AfterCurrentScenario
important? Also do you have to add it to your World?

Thanks for your input

Andrew
cheers,
Post by Matt Wynne
Matt
http://mattwynne.net
+447974 430184
--
You received this message because you are subscribed to the Google Groups "Cukes" group.
To unsubscribe from this group, send email to
For more options, visit this group at
http://groups.google.com/group/cukes?hl=en.
Matt Wynne
2010-01-06 16:02:03 UTC
Permalink
Post by Matt Wynne
Post by Andrew Premdas
Hi all,
First of all apologies for this borderline off-topic post. I think
it has enough of a Cucumber element to be worth posting here
Looking for some comment on a general policy I'm trying to create
for dealing with various settings in our application. We have a
number of things like postage_rate, vat_rate, image_path etc. etc.
which in our production environment will be CONSTANTS. All of these
things however need to be set to a variety of values when running
features and spec. What I am trying to do is work out the best way
to do this in a Rails app.
Currently my thinking is to make all these things CONSTANTS in a
module in an initializer, and then to freeze this module in
production.rb. So a simple version might be
module AppConstants
module Postage
RATE = 399
end
module Images
PATH = "#{RAILS_ROOT}/public/images"
end
end
and the last line of production.rb would be
AppConstants.freeze
Does this make sense? What do you do to address this problem?
I believe this approach will result in a lot of warnings being
generated when we run our features. Is there a way to turn the
warnings of?
Thankyou for your help
Andrew
Hi Andrew,
I tend to take a slightly softer approach to this problem. I've seen a
pattern emerge where we use static attributes, rather than constants,
to hold / access these global constants. In the features we might then
change the value of that static attribute for the duration of a
scenario, then reset it again with an After hook.
class PostageSettings
attr_accessor :rate
def initialize
@rate = 999
end
end
module AppSettings
Postage = PostageSettings.new
end
So basically your using instance variables named like classes to
avoid the Rails class variable problem
Actually I had forgotten about that (this is all pseudo-code, but we
do have *something* a lot like this that works) - I have no idea
whether that works around the problem, but it looks like it might,
doesn't it!?
Post by Matt Wynne
module AfterCurrentScenario
def after_current_scenario(&block)
@after_blocks ||= []
@after_blocks << &block
end
def run_after_blocks
@after_blocks.each { |b| b.call }
@after_blocks = []
end
end
After do
run_after_blocks
end
Given /the postage rate is 101/ do
old_postage_rate = AppSettings::Postage.rate
after_current_scenario do
AppSettings::Postage.rate = old_postage_rate
end
AppSettings::Postage.rate = 101
end
I like this bit, very elegant. Is the location of
AfterCurrentScenario important? Also do you have to add it to your
World?
Sorry missed that bit (this is pseudo-code remember!) - same as usual:

World(AfterCurrentScenario)

cheers,
Matt

http://mattwynne.net
+447974 430184
byrnejb
2010-01-05 20:44:10 UTC
Permalink
Post by Andrew Premdas
Looking for some comment on a general policy I'm trying to create for
dealing with various settings in our application. We have a number of things
like postage_rate, vat_rate, image_path etc. etc. which in our production
environment will be CONSTANTS. All of these things however need to be set to
a variety of values when running features and spec. What I am trying to do
is work out the best way to do this in a Rails app.
I would advise against making anything to do with values supplied from
an external source an actual constant, however you treat them in your
application. Having dealt with varying tax rates and regimes over
many years I have adopted the practice of using time sensitive EAV
rows for such things. For example I presently use something like this
for Canadian sales tax regimes (federal, provincial and harmonized):

country_code
region_code
tax_regime_code
effective_from
superseded_after
tax_calculation_code
tax_rate

You can wrap this in a class method and set a constant for the
purposes of the application if you desire. My experience is that this
is not worth the effort. It proves much simpler in the long run to
provide a date together with the tax criteria and simply pull in the
effective rate and calculation for that time whenever the information
is required.

Tax rates, applicability, and even the basis of calculation, do change
over time and it is frequently required that adjustments are made to
client and vendor accounts that refer to periods where a different tax
rate or calculation method applied. In Canada we have had two
reductions in the federal VAT (GST) rates since 2006 and we are about
to merge (harmonize) the Ontario provincial sales tax with the federal
GST this coming July. In five provinces this is already the case.

However, four of the remaining five provinces retain separate federal
and provincial tax rates. In these regimes the federal and provincial
taxes both apply to some goods but some goods attract only the federal
tax while services are generally exempt from all provincial sales
taxes. One province and all three territories presently have no sales
taxes at all but federal taxes apply nonetheless. Doubtless, these
will eventually harmonize but at some indeterminate future date and
changes that straddle the implementation date need be accommodated.

Postage rates, tax brackets and similar things require much the same
handling. My point of view is that if the enterprise has no control
over the value of a thing, or the period in which it applies, then the
thing really is not a constant.
Noel
2010-01-05 21:02:18 UTC
Permalink
This is a pretty interesting use case. I know this is off topic so
maybe you can email me directly or direct me to a blog post. How do
you handle the business rules that go along with applying the
different tax rates depending on province, good/service, etc. Do you
use a rules engine like ruleby?

I'm still a n00b and welcome the opportunity to learn.

Thanks,
Noel
Post by byrnejb
Post by Andrew Premdas
Looking for some comment on a general policy I'm trying to create for
dealing with various settings in our application. We have a number of things
like postage_rate, vat_rate, image_path etc. etc. which in our production
environment will be CONSTANTS. All of these things however need to be set to
a variety of values when running features and spec. What I am trying to do
is work out the best way to do this in a Rails app.
I would advise against making anything to do with values supplied from
an external source an actual constant, however you treat them in your
application.  Having dealt with varying tax rates and regimes over
many years I have adopted the practice of using time sensitive EAV
rows for such things.  For example I presently use something like this
country_code
region_code
tax_regime_code
effective_from
superseded_after
tax_calculation_code
tax_rate
You can wrap this in a class method and set a constant for the
purposes of the application if you desire.  My experience is that this
is not worth the effort. It proves much simpler in the long run to
provide a date together with the tax criteria and simply pull in the
effective rate and calculation for that time whenever the information
is required.
Tax rates, applicability, and even the basis of calculation, do change
over time and it is frequently required that adjustments are made to
client and vendor accounts that refer to periods where a different tax
rate or calculation method applied.   In Canada we have had two
reductions in the federal VAT (GST) rates since 2006 and we are about
to merge (harmonize) the Ontario provincial sales tax with the federal
GST this coming July.  In five provinces this is already the case.
However, four of the remaining five provinces retain separate federal
and provincial tax rates. In these regimes the federal and provincial
taxes both apply to some goods but some goods attract only the federal
tax while services are generally exempt from all provincial sales
taxes. One province and all three territories presently have no sales
taxes at all but federal taxes apply nonetheless.  Doubtless, these
will eventually harmonize but at some indeterminate future date and
changes that straddle the implementation date need be accommodated.
Postage rates, tax brackets and similar things require much the same
handling.  My point of view is that if the enterprise has no control
over the value of a thing, or the period in which it applies, then the
thing really is not a constant.
--
You received this message because you are subscribed to the Google Groups "Cukes" group.
For more options, visit this group at http://groups.google.com/group/cukes?hl=en.
Andrew Premdas
2010-01-06 15:51:13 UTC
Permalink
Post by Andrew Premdas
Post by Andrew Premdas
Looking for some comment on a general policy I'm trying to create for
dealing with various settings in our application. We have a number of
things
Post by Andrew Premdas
like postage_rate, vat_rate, image_path etc. etc. which in our production
environment will be CONSTANTS. All of these things however need to be set
to
Post by Andrew Premdas
a variety of values when running features and spec. What I am trying to
do
Post by Andrew Premdas
is work out the best way to do this in a Rails app.
I would advise against making anything to do with values supplied from
an external source an actual constant, however you treat them in your
application. Having dealt with varying tax rates and regimes over
many years I have adopted the practice of using time sensitive EAV
rows for such things. For example I presently use something like this
country_code
region_code
tax_regime_code
effective_from
superseded_after
tax_calculation_code
tax_rate
You can wrap this in a class method and set a constant for the
purposes of the application if you desire. My experience is that this
is not worth the effort. It proves much simpler in the long run to
provide a date together with the tax criteria and simply pull in the
effective rate and calculation for that time whenever the information
is required.
Tax rates, applicability, and even the basis of calculation, do change
over time and it is frequently required that adjustments are made to
client and vendor accounts that refer to periods where a different tax
rate or calculation method applied. In Canada we have had two
reductions in the federal VAT (GST) rates since 2006 and we are about
to merge (harmonize) the Ontario provincial sales tax with the federal
GST this coming July. In five provinces this is already the case.
However, four of the remaining five provinces retain separate federal
and provincial tax rates. In these regimes the federal and provincial
taxes both apply to some goods but some goods attract only the federal
tax while services are generally exempt from all provincial sales
taxes. One province and all three territories presently have no sales
taxes at all but federal taxes apply nonetheless. Doubtless, these
will eventually harmonize but at some indeterminate future date and
changes that straddle the implementation date need be accommodated.
Postage rates, tax brackets and similar things require much the same
handling. My point of view is that if the enterprise has no control
over the value of a thing, or the period in which it applies, then the
thing really is not a constant.
Thanks for this, and I will bear it in mind. However for now a super simple
approach to application settings is a business priority, so I still need to
find a stable way to do things

Cheers

Andrew
Post by Andrew Premdas
--
You received this message because you are subscribed to the Google Groups "Cukes" group.
To unsubscribe from this group, send email to
For more options, visit this group at
http://groups.google.com/group/cukes?hl=en.
Loading...