Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

add_configuration_property doesn't work as expected #803

Open
heygrady opened this Issue Mar 20, 2012 · 5 comments

Comments

Projects
None yet
1 participant

http://compass-style.org/help/tutorials/extending/#adding-configuration-properties

When developing a compass extension it's not easy to create new configuration variables. The available documentation is vague (to me) and it appears that this feature simply doesn't work (based on what I've tried).

Take this example config file:

# Require any additional compass plugins here.
Compass::Configuration.add_configuration_property(:foobar, "this is a foobar") do
  if environment == :production
    "foo"
  else
    "bar"
  end
end

# Set this to the root of your project when deployed:
http_path = "/"
css_dir = "stylesheets"
sass_dir = "sass"
images_dir = "images"
javascripts_dir = "javascripts"
foobar = "baz" # set my new custom property

puts Compass.configuration.foobar #-> bar
puts Compass.configuration.read(:foobar) #-> bar
puts foobar #-> baz
puts Compass.configuration.set?(:foobar) || false #-> false
puts Compass.configuration.read_without_default(:foobar) || "<not set>" #-> <not set>

The configuration variable is correctly created on the Compass.configure instance but the value in the config file is never getting picked up or properly processed. This is not what I was expecting. I'm not sure how to access that variable and the documentation doesn't make this process clear.

What is the proper way to create a new property that will exist on the Compass.configuration instance and will also read from the config file?

Here's an interesting addition. It appears that the instance of Compass.configuration in the config file itself is different from the Compass.configuration available to the rest of the project.

# Require any additional compass plugins here.
Compass::Configuration.add_configuration_property(:foobar, "this is a foobar") do
  if environment == :production
    "foo"
  else
    "bar"
  end
end

# Set this to the root of your project when deployed:
http_path = "/"
css_dir = "stylesheets"
sass_dir = "sass"
images_dir = "images"
javascripts_dir = "javascripts"
#foobar = "baz" # let's leave this at default
Compass.configuration.foobar = "baz" # we'll set the variable directly on the global instance instead

puts Compass.configuration.foobar #-> baz
puts Compass.configuration.read(:foobar) #-> baz
puts foobar #-> bar
puts Compass.configuration.set?(:foobar) || false #-> true
puts Compass.configuration.read_without_default(:foobar) || "<not set>" #-> baz

https://github.com/heygrady/compass-sprockets/blob/master/lib/compass/sprockets.rb

To help this along, what I'm trying to do is write an extension to compass that piggybacks on the command line utility and the watch capabilities but adds in additional functionality. Specifically I'm interested in using Sprockets for managing JavaScript or Coffeescript assets and being able to combine and minify them easily, very similar to how Compass works already.

Encouragingly I can get Sprockets to work correctly to suit my goals and I can even get it working with Compass if I just hack everything into the config.rb file and use the local variables there. What I can't get working is packaging this as an extension to Compass that would be easy for others to add to their projects. The documentation is focused more on adding scss files or adding new functions to Sass itself. I want to add functionality to the Compass command-line utility since it's already useful in my workflow and already does everything I need and even appears to have hooks to allow what I'm trying to do.

The main hurdle is how and where to initialize my plugin so that new config variables are properly registered and that they are available to the rest of my code. Additionally, I need to be able to run my code after all of the config stuff has been initialized and I can't seem to find any documentation on that. I've tried searching the code but it's pretty dense. So I'm stuck with the default config values that I'm registering with no way use anything that's set in the config.rb and that makes my extension pretty useless.

I've been searching for an example of a Compass extension that works with custom config variables and I can't seem to find a single one.

heygrady commented Apr 5, 2012

This remains a blocker for me. Is there an extension you could point me to that is successfully adding config variables and using them?

heygrady commented May 2, 2012

Ahem...no hints? I have a project that I could release if I could figure out how to add new configuration variables for a Compass extension.

I think there's a bit of a chicken and egg situation with the way plugin registration and config variables are handled. I think that what's missing is a callback for "configuration loaded" that extensions could use. But also, there's an issue that Compass::Configuration.add_configuration_property() is altering the Compass::Configuration::Data object after it has already been used to initialize at least one instance that is registered as Compass.configuration.

I've been pouring over the code to find a place that I could obviously inject a "configuration loaded" callback but I can't really find and obvious place. Is it possible to at least point me there?

heygrady commented May 3, 2012

I've added this to my local build of Compass and it's serviceable. I don't know if there's a better place to kick-off the Compass.configuration.run_complete call. But this gets around the issue I was having.

8e7d82cd3ef8de358b6ad4864d21621fa8e3ece2
 lib/compass/configuration/data.rb  |    6 ++++++
 lib/compass/exec/sub_command_ui.rb |    1 +
 2 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/lib/compass/configuration/data.rb b/lib/compass/configuration/data.rb
index 93e3be6..f5b4808 100644
--- a/lib/compass/configuration/data.rb
+++ b/lib/compass/configuration/data.rb
@@ -56,6 +56,12 @@ module Compass
       define_callback :stylesheet_error
       chained_method :run_stylesheet_error

+      # on_complete
+      # yields a boolean
+      # usage: on_complete {|status| do_something(status) }
+      define_callback :complete
+      chained_method :run_complete
+
       inherited_accessor *ATTRIBUTES

       strip_trailing_separator *ATTRIBUTES.select{|a| a.to_s =~ /dir|path/}
diff --git a/lib/compass/exec/sub_command_ui.rb b/lib/compass/exec/sub_command_ui.rb
index f348298..676999e 100644
--- a/lib/compass/exec/sub_command_ui.rb
+++ b/lib/compass/exec/sub_command_ui.rb
@@ -40,6 +40,7 @@ module Compass::Exec
         command_class.parse!(args)
       end
       cmd = command_class.new(Dir.getwd, @options)
+      Compass.configuration.run_complete true
       cmd.execute
       cmd.successful? ? 0 : 1
     rescue OptionParser::ParseError => e

Now I can write an extension that both creates configuration and utilizes it.

Compass::Configuration.add_configuration_property(:foo, "Location of JavaScript source files for use with Sprockets") do
  "bar"
end

def plugin_init
  puts Compass.configuration.foo # bar or whatever was set in config.rb
end

Compass.configuration.on_complete{|status| plugin_init() }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment