I’ve decided to move all of my online material over to my namesake site at patrickward.com. It’s easier for me to manage and uses my new Willow generator. Octopress was great, but still awkward to use for my purposes. The new set up is getting closer to what I originally wanted.
For one of my ongoing projects, I’m using the latest version of Rails (3.1.0.rc6 as of this post) along with the Compass CSS framework. At first, this turned out to be an adventure in maintaining a calm composure. But, my experience of the Rails Asset Pipeline coupled with the Compass framework is proving to be worth the effort.
My First Approach
My first approach to the problem was to keep them completely separate. I generated a Compass project outside of the asset pipeline folders and set it’s config parameters to generate CSS files within the normal app/assets/stylesheets folder under rails. The setup was essentially like this:
Using Guard or compass watch on the command line I would essentially pre-compile the Compass CSS files. Using the default Rails application.css file, Sprockets would then pick up the pre-compiled style.css file for use within the Rails framework.
While this worked, it was hackish and required additional steps to complete. Thankfully, the Rails, sass-rails, and Compass projects have all come a long way in the past few months.
My New Approach
I’ve since abandoned the idea of using Compass outside of the asset pipeline and now use it coupled with Sprockets own require system. In addition to the latest versions of the Compass and Rails projects, an understanding of how Sprockets and the asset pipeline work is essential to making this work.
Use the right version of Compass
To begin with, I found it necessary to use the git version of the rails31 branch of Compass, which seems to have some fixes for using it with Rails 3.1 conventions. Here’s a summary of the key Gemfile adjustments I’ve made recently to get things kickstarted.
At this point, I needed to understand the key differences betweeen Sprockets, Sass, and Compass.
Sprockets is essentially a pre-processor and rails uses it to stitch together your CSS files into a single, monolithic stylesheet. While it recognizes and precompiles (or filters) Sass files, it’s require system does not understand the concept of Sass partials or mixins through the use of imports and includes. So, you have to separate the logic used in Sass from the logic used in Sprockets. There is a linear process that you must be aware of when working with the two that looks something like this:
Rails starts up the asset pipeline (or sprockets), which begins to read in the “required” files you specified
When it finds a .sass or .scss file in it’s require path, it passes that file off to Sass for rendering. (This is true for any file that requires additional processing, such as .erb files.)
Sass then uses it’s own rendering engine to import, include, and process partials, variables, etc. This is separate and outside the scope of what Sprockets does. So, if you want to reference Sass variables or mixins in different files, you need to ensure that the proper Sass @import calls have been made in those files.
Sprockets then stitches all of the rendered files it finds back into it’s own process using the separate logic of its require system.
The key distiction here is that Sprockets does not render Sass files, it filters them through Sass before including them back into it’s own require system. They are separate and distinct in their knowledge of each other.
For Compass, remember that, at heart, it is a collection of Sass mixins. When used this way, you can create a folder structure that keeps Sass and Sprockets logically and visually separated.
Separating Sass from Sprockets
What helped me was physically separating the Sass based code from the Sprocket requires. This is not the standard way that the Rails 3.1 generators expect you to use the asset pipeline, but it made more sense to me for several reasons:
I tend to organize my Compass/Sass files in heirarchical order which depends on a liberal use of @import and @include for mixins
I felt I had more control over the order of requires and the process that Sprockets uses to include files.
I liked the visual and physical separation of CSS code
The folder structure for my most recent project ended up looking similar to the following:
This enabled me to separate key areas of the application’s CSS and use the Compass framework, along with the full capabilities of Sass, without worrying about how Sprockets was going to pull in each of my files.
Removing require_tree
Rails puts a few magical requires into the default application.css, which at first seem perfectly reasonable, until you start using it the way I’m describing here. Then, it becomes a bit of a hassle.
So, my first order of business was to remove the require_tree directive from my application.css file. That directive requires all stylesheets from the current directory at the location of the directive. Since I am trying to have more control over how stylesheets are ordered in my application, that directive doesn’t help me. So, out it goes and in go more specific requires based on my folder structure above.
Adding application.css.scss
I like to structure my Compass files using a primary css file that pulls in additional partials as needed. This led me to creating the application.css.scss file underneath the application subdirectory: application/application.css.scss
Rather than use Rails generated scss files (e.g. users.css.scss for a users_controller), I opted to use partials underneath the application directory and pull them into the main application.css.scss file instead. This gives me greater control over the order of files that are imported and let’s me use Compass and Sass the way that I’m used to using them. In fact, when Rails generates the users.css.scss file, I just delete it before I make a commit to git.
As you can see, the application.css.scss file becomes a mid-level processor for my Compass structured css:
application.css.scss
12345678910111213
// Framework
@import'compass/reset';
@import'compass/css3';
@import'susy';
// Application
@import'base';
@import'defaults';
@import'layout';
// etc...
// Controllers
@import'users';
I can now use Compass and Sass the way I like to without worrying about how the Rails asset pipeline is going to see them.
But, What About the application.css file?
Let’s not forget that we’re still using Sprockets. As I mentioned earlier, I take out the require_tree directive and replace it with specific requires for the Sass files I’m interested in including into my manifest.
In my case I’m adding both an application css file along with a jQuery UI file I converted to Sass for use in my application.
I keep the require_self directive, which leaves my application.css file looking similar to the following:
application.css
123456
/*
*= require_self
*= require "aristo/jquery.ui.all"
*= require "application/application"
*= require "some_additional_css_file"
*/
At this point, I can add additional plain css files, Sass files, vendor files, etc. all within the boundaries of how my application expects them to be ordered (i.e. required). An example of that is the use of my customized jquery.ui.all file that I’m requiring outside of my Compass framework.
Summary
This approach allows me to use the best of Compass and Sass along with the flexibility (and Rails oriented way) of the asset pipeline (or Sprockets), but without having to sacrifice the tried and true method that Compass users are used to.
Condensed into a few easy steps, the process is:
Use the rails31 branch of the Compass gem in your Gemfile.
Separate your application’s Compass/Sass files from Sprockets (e.g. I use a folder structure)
Remove the Rails generated css.scss files and use partials with Compass instead
Remove the require_tree directive from application.css
Add your additional Sass or CSS files using regular require directives in application.css
I ran into the pervavise issue of having to clear a DIV that contains only floated DIV elements in it recently. The problem is that the outer container does not stretch to accomodate the height of it’s child containers. So, if you have a background or a border on the containing element, it does not fully cover the child elements.
It’s an old issue, but I keep forgetting where to find the information on how to fix it. So, this is a note to self for future reference.
I found the following resources to be the most useful in terms of the pros and cons of each technique. Please see them for more detailed instruction. I’ve summarized the basics below.
The easiest, and oldest, fix is to add an empty DIV with a style of clear:both to the end of the outer container. This works, but it’s not semantic and makes a mess of the page’s markup.
sample.css
1234
#container{border1pxsolid#000000;}
#left{width:45%;float:left;}
#right{width:45%;float:right;}
.clear{clear:both;}
sample.html
12345
<divid="container">
<divid="left">Lorem ipsum...</div>
<divid="right">Lorem ipsum...</div>
<divclass="clear"></div>
</div>
Use the clearfix Hack
Beyond adding additional markup to the page, you can use the infamous ‘clearfix’ hack, which cheats by adding additional content after the containing element. While this prevents you from having to muddy the markup on the page, it feels a bid hackish to me.
sample.css
123456789101112131415
/* This fixes the problem for most browsers */
.clearfix:after
{
content:".";
display:block;
height:0;
clear:both;
visibility:hidden;
}
/* This fixes the problem for IE7 */
.clearfix{min-height:1%;}
/* This fixes the problem for IE6 */
*html.clearfix{height:1%;}
Use the overflow:hidden Technique
The method I’ve tended to use and that has the least problems in my experience is the overflow method, with some additional css to trigger hasLayout in IE.
This method works great as long as there is no fixed height on the outer container. See Quirksmode for ways to resolve issues related to this technique.
I’ve seen some references indicate that you can use overflow:auto to achieve the same results, but you risk having scrollbars show. So far, the overflow:hidden method has been the cleanest and most efficient technique for me.
sample.css
123456789101112
/* Cleanest method */
.container{
overflow:hidden;
display:inline-block;/* Necessary to trigger "hasLayout" in IE */
display:block;/* Sets element back to block */
}
/* Or, use the zoom method to trigger "hasLayout" in IE */
.container{
overflow:hidden;
zoom:1;/* Necessary to trigger "hasLayout" in IE */
I needed to write some shared examples in RSpec the other day for a simple ActiveRecord concern I was writing.
In doing so, it forced me to understand what RSpec means by the “subject” of an example. I’ll admit this is a very simple concept, but until now I didn’t take the time to understand it and the relish docs weren’t overly descriptive on how it works.
In general, the subject of an example is just the object being described. But what, specifically, does that mean?
In an implicit context, it means the subject is an instance of the object being described. For example, in a model spec, I might be describing a User class:
123
describeUserdo
it{shouldrespond_to:authenticate}
end
Which can also be written as:
123
describeUserdo
subject.shouldrespond_to:authenticate
end
Here, the subject is an instance of User. RSpec creates an instance of User by calling new on the User class without any arguments. It’s the same as saying this:
1234
describeUserdo
subject{User.new}
it{shouldrespond_to:authenticate}
end
That last example, is what RSpec calls an explicit subject. Instead of deducing the subject from the outer describe, an explicit subject is declared within the example and can be used afterwards the same way that an implicit subject would.
The key distinction for me, and one that I didn’t understand previously, was that the subject is an instance of the class being described (implicitly or explicitly).
This came up when I needed to test both an instance of a subject as well as a static class method of a subject’s parent class.
But how do I test a static class method against an instance?
It’s all very simple, but I just hadn’t grokked it until now. Fortunately, this realization came in handy when I was writing a simple shared example to test common functionality against multiple models.
In this case I wanted to test that a model had a specific instance method as well as some class-based scopes.
1234567891011121314151617181920212223
shared_examples_for"a Trashable"do|model_type|
before(:each)do
@objects=[
Factory(model_type,:trashed=>false),
Factory(model_type,:trashed=>true)
]
end
it"should respond to a trash method"do
subject.shouldrespond_to:trash
end
# Note - have to call class on the implicit subject to call a class method!
By using subject and passing in the model_type to generate some factories, I’m able to dynamically adjust to whatever model the shared example exists within at the time. Simple, dry, and efficient.
I needed to install PHPUnit with my local version of MAMP Pro 2.0.1 recently. After starting with this article for ideas, I came up with the following adjusted steps:
1. Create a soft link to the MAMP version of pear:
2. I found that the default pear.conf file was either corrupt or invalid. Following a forum suggestion on the mamp.info site, I just removed it by renaming it:
Note: I ran into a an issue at this point, where pear would not install an unstable version of HTTP_Request2 that it found. So, I just forced it to install the RC1 version instead:
1
pear install -f HTTP_Request2-2.0.0RC1
I ran the pear install command after this.
5. At this point, PHPUnit should be installed. So, I created a new soft link to the phpunit file:
This blog is a place for me to store notes to myself that are technical in nature. Hopefully, my notes will be useful to you as well. Feel free to browse around.