Jason

Jul 172017
 

Sometimes in the life of a hybrid Rails-Javascript app you may want to do something unique: have a config file written in YAML available to you in your Javascript code.

A simple trick will make Sprockets, the Asset Pipeline in Rails 4+, do this automagically for you. This example comes from https://github.com/rails/sprockets/issues/366

I’ve created an example app that you can read the source or see live demo here.

First, we’ll need to create a special hook for Sprockets called “depend on config”. Create a file at lib/process_depend_on_config.rb

Sprockets::DirectiveProcessor.class_eval do
 def process_depend_on_config_directive(file)
  path = File.expand_path(file, “#{Rails.root}/config”)
  context.depend_on(path)
 end
end

Now, in your Sprockets-managed Javascript, use this directive before you include Ruby evaluation inside of javacript

assets/javascripts/pull_yaml_into_json.js.erb

//= depend_on_config ‘my_configs_in.yml’

ExampleApp = {};

ExampleApp.MyConfigs = {
 getConfigs: function() {
  var mySettings = <%= YAML.load_file(“config/my_configs_in.yml”).to_json %>;
  return mySettings;
 }
};

Finally, for demonstration purposes, create a file at config/my_config_in.yml, you actually have the YAML configuration you want to port from Ruby to JSON, something like

hello:
 world: 12345
 country: 678
 state: 90
 city: 11

The depends on config directive tells Sprockets to invalidate the cache for the resulting JS file when the YAML file changes, hence why it is needed here.

Voila! Your Ruby-based output (here, a YAML config but theoretically could be anything) is now included in each build during the Sprockets compilation phase.

Mar 062017
 

This is to fix build, slug, and caching problems related to asset compilation during slug compilation.

Everyone needs a little spring cleaning, right? No, really. Sometimes when I switch around buildpacks or change up assets I run into a strange asset cache problem. Here’s the five magic commands to purge your slug compile process, from less-invasive to more-invasive. When you have a nasty asset cache problem, usually #4 is the one you need.

To use the Heroku repo plugin, I think you’ll want to install it following these instructions.
Note that the Heroku plugins are installed LOCALLY on your machine not on your environment. They are simply shell scripts that perform a series of actions on a remote Heroku environment.

Use with caution. After each one, re-push your branch to Heroku.

1.

heroku run rake tmp:cache:clear -a appname

(then push your branch to Heroku)

2.

heroku run rake assets:clobber -a appname

(Rails 4+, for Rails < 3, use heroku run rake assets:clean instead)
(then push your branch to Heroku)

3.

heroku repo:gc -a appname

This will run a git gc -agressive against the applications repo.

(then push your branch to Heroku)

4.

heroku repo:purge_cache -a appname

This will delete the contents of the build cache stored in the repository. This is done inside a run process on the application.
(then push your branch to Heroku)

5.

heroku repo:reset -a appname

This will fully empty the remote repository.
(then push your branch to Heroku)

Feb 202017
 

Site speed can be said to be the number one issue facing web developers today.

Whether it’s this KISS Metrics block post, another KISS Metrics block post, study after study show that delivering your content fast, fast, fast is make-or-break factor in today’s web economony. That’s why it’s so important that your images are optimized for the web.

Photoshop and other tools export notoriously large files -- well over 1 MB. This is unacceptable in today’s world, where 33% of mobile users in the US are on 3G connections.

If you’re on Rails using Paperlcip, I’ve got a great solution to explore for you today: Image-Optim. You can automagically compress all your images, inside the Rails pipeline and also the ones you upload with Paperclip. On Heroku, you’ll need to use two special buildpacks to make this work. As well, because Heroku uses an ephemeral file system, Paperclip needs to be configured to use an AWS bucket as its storage.

First, refer to my blog post from last year, about how to add the ImageMagick buildpack to your Cedar-14 herokubuikd.

The instructions above will direct you to do add this buildpack first:

heroku buildpacks:add -i 1 https://github.com/jasonfb/heroku-buildpack-cedar14-imagemagick704

Then add another buildpack to your Heroku environment

heroku buildpacks:add -i 2 https://github.com/bobbus/image-optim-buildpack

(you’ll note here you are using the index flag to put this buildpack into position 2 because you already should have the Imaegmagick buildpack at position 1)

You should now have 3 buildpacks, which can be check with heroku buildpacks like so:

$ heroku buildpacks -a your-heroku-app
=== your-heroku-app Buildpack URLs
1. https://github.com/jasonfb/heroku-buildpack-cedar14-imagemagick704
2. https://github.com/bobbus/image-optim-buildpack
3. heroku/ruby

Then add to your Gemfile these 4 gems, (for the sake of this post I will assume you already have gem ‘paperclip’ in your Gemfile).

gem ‘paperclip-optimizer’
gem ‘image_optim’
gem ‘image_optim_rails’
gem ‘image_optim_pack’

To get this working on Heroku, you’ll actually need to work through a few more steps: database setup, AWS. For the lazy, check out the example which you can find at the end of the blog post.

Here’s my has_attached_file. In this example, I’m creating only two styles: a thumbnail, and an optimized version.

Notice that I’ve turned off lossless compression, in other words, allow_lossy: true

With this safeguard on (allow_lossy: false, which is default), I’m usually able to only get an image down to about 75% of its original size.

A large 909KB file was only reduced down to 730 KB; whereas Optimizilla was able to get it down to a whopping 189 KB.

With the safety guard switched off allow_lossy: true, I get much better results but much worse quality.

1st Example
Here, I define a thumb and a optimized.

has_attached_file :attachment, {
 styles: {
  :thumb => ‘125×100>’,
  :optimized => ‘%’
 },
 processors: [:thumbnail, :paperclip_optimizer],
 paperclip_optimizer: {
  nice: 19,
  jpegoptim: { strip: :all, max_quality: 10, allow_lossy: true },
  jpegrecompress: {quality: 1},
  jpegtran: {progressive: true},
  optipng: { level: 2 },
  pngout: { strategy: 1}
 },
 convert_options: { :all => ‘-auto-orient +profile “exif”‘ },
 s3_headers: { ‘Cache-Control’ => ‘max-age=31536000’}
}

2nd Example
Here, I define a thumb and a large.

Remember, when configured together the whole thing looks like this, see the “Per style setting” on this paperlclip-optimizer doc:

(this is an example that mimics the paperclip-optimizer docs)

 has_attached_file :avatar,
          processors: [:thumbnail, :paperclip_optimizer],
          paperclip_optimizer: {

          },
          styles: {
           thumb: { geometry: “100×100>” },
           large: {
            geometry: “%”,
            paperclip_optimizer: {
             paperclip_optimizer:
{
              jpegrecompress: { allow_lossy: true, quality: 4}},
              jpegoptim: { allow_lossy: true, strip: :all, max_quality: 75 }
            }
           }
          }

The Magic Sauce

The docs say you should have allow_lossy set to its default, which is is false. Using this setting this way means your images come out with no quality loss. In my tests, I’ve found that this setting should be turned on, overriding the default.

I recommend paying attention to two important settings
jpegoptim max_quality – 0 through 4, with 4 being best quality
jpegrecompress quality – 0 through 100%, with 100% being best quality

In my tests, I’ve found that the following are acceptable for production websites with high-quality images.

Option A
jpegoptim max_quality quality: 4; jpegrecompress quality: 80
this yields 20-40% compress images of the uncompressed JPGS

Option B
jpegoptim max_quality quality: 3; jpegrecompress quality: 60
this yields 10-20% compress images of the uncompressed JPGS

As far as I can tell, jpegoptim max_quality setting appears to have very little effect on the file size, where as the jpegrecompress quality setting has the most dramatic effect, especially on larger files. The values for jpegrecompress quality are 0-4, with 0 being the least quality (most savings) and 4 being the best quality. With a settle of 4, you can’t perceive any quality loss, but you don’t get the benefit of extremely optimized files. I recommend a setting of 3, which is barely noticeable in terms of quality loss but a significant boost in file size.

Test App

I threw together a test demo here. It lets you upload your own JPGs and see how they compress. It’s important to examine your own files, weighing the quality loss with the file size gain (that is, speed gain in having smaller file sizes).

https://image-optim-paperclip-exmp-41.herokuapp.com/assets

You can read the source of this demo app on Github.

Please note this Heroku (production) app is configured with a few extra goodies:

AWS setup for a basic Amazon S3 bucket
Postgres setup for Heroku

This app is configured to use an Amazon S3 bucket called jasonfb-example1. Because I pay for this bucket, please do not abuse. This demo app is provided for developer testing purposes only; I reserve the right to delete any images uploaded for any reason, including copyright infringement or simply lack-of-space. Please do not upload any inappropriate photos or photos you do not own.

You can hit the “Destroy” button on any image you upload.

The jpegoptim max_quality and the jpegrecompress max_quality

You’ll notice my example app here creates 5 different versions, using the same jpegoptim setting (jpegoptim: { allow_lossy: true, strip: :all, max_quality: 75 }, but 5 different quality settings on the jpegrecompress setting (be sure to note the jpegrecompress takes a quality parameter of 0-4; the jpegoptim setting takes a max_quality setting of 0-100)

In my example app I’ve split the settings for jpegrecompress and jpegoptim into a global setting and a per-style setting. Its setup differs from the examples above.

In my sample app, I’ve set the jpegoptim max_quality setting to 75 and created five different jpegrecompress settings: 0, 1, 2, 3, and 4, named:

optimized_compress_0
optimized_compress_1
optimized_compress_2
optimized_compress_3
optimized_compress_4

(you’ll see these in the has_attached_file in app/models/asset.rb)

So go ahead, upload a color-rich un-optimized image. In my experiments, I found that quality settings 4, 3, 2, and 1 yield approximately the same file size, with only a small dip in file size when you went down to 0.

However, the noticeable loss in quality begins to happen even at quality setting 3, so it seems to me why not use quality setting 4. You will be baking in an automatic guard against very large un-optimized images coming into your app. You’ll need to play around with these two settings.

Important Addendum (2017-03-09)

I am adding an important addendum to this post. After switching around my buildpacks on Heroku, I ran into a strange Sprockets error:

undefined method `dependency_digest’ for #<Sprockets::StaticAsset:0x007fefb93d0d28>

The only way I found to fix this was to purge my assets in slug compilation. This will mean your 1st push after purging will take an extra long time to slug compile.

If you run into that error, do this before you push to your environment:

heroku repo:purge_cache -a appname

Also see this Stack overflow post. I corresponded with the maintainer of Sprockets regarding this issue, and he suggested later versions of Sprockets may have addressed this issue (we are on Rails 4.1 with Sprockets 2.12.4).

Feb 152017
 

In your Google Trusted Store set-up, there is a process where you need to use a special link to validate your GTS badge.

You find this special link in the popup after the blue “Test” button where you see your store listed. Here, you see a panel called “Browsers to test” and an instruction to “Copy and paste this URL into your browser window”

Once you do this, you’ll see a beige bar like so:

This lets you preview your GTS integration so they can certify your website in their program. Annoyingly, this bar appears not to go away by itself, nor can I find a way to disable it in GTS.

To remove it, you must remove the cookies in your browser associated with

googlecommerce.com

and

www.googlecommerce.com

In Chrome, go to Advanced > Content Settings > All Cookies and Data and search for the specific domains above.

Then delete those cookies completely from your browser.

Feb 122017
 

My colleagueReid Cooper and I discovered a nice little trick of controller concerns, something we sometimes call “behaviors” in our app (typically implemented as modules). We found a trick from this link that lets us mix in behavior into both a controller and view helper, but first a brief introduction to controller concerns.

Concerns were born in Rails 4 as a nod to the limitations, vis-a-vi the domain model, of a a “strict” interpretation MVC as implemented by Rails. Around 2012 or 2013, most experience Rails developers would explain that the MVC structure created by default doesn’t necessarily dictate a strict MVC paradigm. Thanks in part to DCI architecture -- which complements but does not replace MVC -- a more modern understanding of larger apps includes a domain layer, i.e., where you put the business domain that is not in the traditional Rails models.

There are various options, and in a small nod to the problem the Rails core team added a blank empty folder to default Rails installs. You might notice this folder at app/controllers/concerns. What, the Rails newbie says, am I to do with a blank empty folder?

Good question. You would do well do study the excellent work of Sandi Metz and James Coplien, who cover domain abstraction (and a specific pattern the latter calls “DCI,” or domain-context interaction) in two excellent books (POODR and Lean Archtecture, respectively). The scope of these is well beyond this blog post, but since they are such my heroes I want to take an opportunity to plug these excellent books.

Reid and I wanted a behavior, a-la “concern”, that we could mix into a controller to inherit instance methods for the controller. We also wanted a view helper automagically mixed into our views for the view to access while it is rendering. To the rescue: the obscure included hook that gets called after modules are included into controllers, where you can re-access the controller itself and add both helper and actions (formerly known as filters.)

app/controllers/abc_controller.rb

class AbcController < ApplicationController
 include FancyConcern
 
 def index

 end 
end

and here’s the magic, in app/controllers/concern/fancy_concern.rb

module FancyConcern
 def self.included(base)
  # http://www.railstips.org/blog/archives/2009/05/15/include-vs-extend-in-ruby/
  base.helper FancyConcernViewHelper
  base.before_action :set_my_instance_variable
 end
 
 def set_my_instance_variable
  @my_instance_variable = “_instance variable value_”
 end 
end

app/views/abc/index.html

Hello world!

<fieldset>
<legend>An instance variable set in a before_filter</legend>
<%= @my_instance_variable %>
</fieldset>

<fieldset>
<legend>A call to the view</legend>
<%= my_view_helper_method %>
</fieldset>

Check out the full test app.

I don’t have a demo up & running, but it works (I took a screenshot below). If you want you can pull it locally and run it yourself to see.

 Posted by at 11:14 am  Tagged with:
Jun 052016
 

If you’re a Ruby or Rails developer looking for some advice on how to get better at integration testing: congratulations! You’ve reached the highest level of difficulty in all of the areas of the stack you must conquer to become a great Ruby developer.

Integration testing is hard, but it doesn’t have to be. This the subtle of this truth lies in the fact that you must be skilled in both the backend and front-end of your app: you must understand factories and your Ruby objects, and if you have a Javascript-heavy app, the deep fundamentals of Javascript as well.

First things first, you will want to learn how to debug in both the front and back-ends. For the sake of this post, I’m going to assume you have learned a backend debugging tool like byebug. If not, try this tutorial now.

Second, you need to know that Capybara is a syntax for writing Ruby – “a DSL” – for telling a browser what to do. It can work against several of different browsers – Firefox, Chrome, and ‘headless’ browsers you can’t see. If you use a browser you can see, you get the neat effect of being able to view your results as they run, which can be fun (and you should do it) but may not work on a Continuous Testing / Continuous Integration platform.

A headless browser (of which I will discuss two: webkit and poltergeist) is complex to debug, and requires a command of all the parts of the stack.

Occasionally, you may write some Javascript code that will work in one browser and not another (you should learn to avoid this) – that’s why you can run Capybara with a single syntax against many different browsers.

The bad news is, in short, despite it being 2016 and Rails having been around for nearly 12 years none of the drivers is perfect.

Sometime ago I wrote about a neat little trick to view console messages while debugging Capybara webkit.

Driver’s name Browser The Bad The Good
Selenium Firefox Firefox doesn’t let you paste into the console
Chrome Chrome The Chrome debugging experience has some annoying gotchas. Don’t try to open the debugger while your spec is running, unless you pause on the back-end (for example, byebug). If you do pause on the Rails-side, you should be able to also fall into the debugger on the Chrome driver side too. If you do actually manage to open Developer Tools, you can reasonably debug your Javascript
webkit headless There are problems with PATCH requests when using this legacy headless driver. Take note that this PATCH problem was fixed in PhantomJS version 2.0. Webkit also requires you install QT on your system. Webkit lets you inspect status codes using driver.status_code and as mentioned in the post above, console messages too.
poltergeist headless If you app makes PATCH requests, note that poltergeist needs you to be running on Phantom JS 2.0 or higher to be able to process PATCH requests corruptly (when they aren’t, they come through on the server side as empty requests)
By default, anything that is sent from your Javascript as a console message makes your spec run fail (this can be turned off).
“The Worst Except For All the Others” (as Churchill said). This is the one I use primarily. Your console.log output is automatically ported from your Javascript into your test results.

Here’s a list of other notes of things to keep in mind.

  1. You should be using Capybara version 2.7.1 or higher. Earlier versions do not wait for all sessions to close before kicking off Database cleaner’s truncation. When truncation happens before all sessions are closed, bad things happen (like intermittent failing tests). Waiting and timing is explained in detail below.
  2. This applies to you if you app makes PATCH requests: Make sure you are on Phantom JS 2.0 or higher. Note this is a binary to install and on CI server it probably is a global (shell) configuration. (On ours, Semaphore, you need to specify the Phantom JS in the global build commands, not just in your Gemfile.) You to be running on Phantom JS 2.0 or higher to be able to process PATCH requests corruptly. When they aren’t, they come through on the server side as empty requests, which can lead to unexpected results.
  3. Capybara-webkit sucks. It just does. Don’t use it. The intermittent issues alone are enough to throw it out. Use Poltergeist instead. It was an older technology and by and large it has been replaced by Poltergeist. Experienced developers know this and don’t use webkit for this reason. Junior developers fight in vein trying to get webkit to work and waste lots of time believing in something that simply is a shitty piece of technology.
  4. When working with ChromeDriver note that it is annoyingly difficult to open the Developer Tools while the test is running. This is a knonw-issue, and the Chrome developers advise you pause your test to open Chrome Dev toos. This is explained here.
  5. When using Database cleaner with Truncation, Make sure you have it in an append_after hook and not in config.after(:each) (several tutorials will mistakenly lead you down the wrong path here.) It should look like this:
    config.append_after(:each) do
     DatabaseCleaner.clean
    end
  6. Prefer transaction instead of truncation for all non-Javascript tests (unit tests, controller tests, etc). For Javascript integration specs, you need truncation. An explanation about why can be found at https://github.com/DatabaseCleaner/database_cleaner#rspec-with-capybara-example
  7. Use Factories and don’t use fixture data. Fixture data can lead to brittle tests. Generally the entire Rails community has learned from the Dark Days and recommends factories over fixtures.
  8. Don’t use connection pooling. Some people on the internet will tell you to use connection pooling to solve thread-locking problems – don’t listen to them. Capybara already has dealt with this under the hood, make sure you are on a recent version of Capybara.
  9. Avoid using .trigger. Sometimes if an element isn’t visible Capybara will advise you when it fails you can ‘work around’ the element not being on the page by referencing the element and calling .trigger. You’re just trying to get around the on-screen-and-visible enforcement by Capybara, but this isn’t a good idea. If the thing isn’t on the screen and visible, it probably means there’s a bug and you want to catch that as a failure. Remember your tests are only as valuable as what they catch when things mess up.
  10. Circular Dependancy when trying to load ___
    This development issue that causes race condition (intermittent) failures has been explained on this Thoughtbot blog post.

    To fix if you’re on Rails 4.1 or prior, set allow_concurrency = false in test.rb (Rails 4.1 + earlier only)

    Set this in your config/environments/test.rb file set this:

    config.allow_concurrency = false

    You do not need this if you are on Rails 4.2 and above.

Timing

Timing is super hard to debug, but there’s an art to it. Tame your Capy specs like a lion tamer. Make them jump through hoops and bedazzel them to calm them down. You need to understand 3 things: Capybara’s native waiting, (2) a wait helper, and (3) an explicit sleep.

Capybara Native Waiting Behavior
If you’re on Capy 2.7 understand that Capybara natively waits for content on a page when you assert it to be there, even when Ajax and rendering might not have it ready to be there at the very moment the assertion runs. Thomas Wolpole, author of Capybara, advises me:

The way 2.7.1 is handling this is through middleware that keeps a counter of any current requests being processed by the app. First it tells the browser to visit about:blank and waits for that to happen, at which point the browser should not be initiating any more requests to the app. Then it waits for the active request counter to be 0, and then continues on.

Instead of using sleep, use expect(page).to have_content(…) to wait for the content you want to appear. Specifically I believe that using expect/have_content waits for the page to have the content you want it to have, but expect/value/to eq does not actually wait. For this reason, sprinkle in some expect(page).to have_content even when you don’t have to just to get Capybara to pause until the page is re-rendered.

You often find yourself writing

expect(page).to have_content(“xxx”)

over and over again. Contrary to the instinct to not Repeat Yourself, that’s a good thing! If this really irks you may write yourself helpers to make this repeated step more encapsulated. What you are really doing is putting the UX through it paces, so think of it like a player piano instructions not like the code you so work on to make beautiful.

It will be easier to do this if your app has natural-language responses like “You have logged in successfully.” For this reason you should encourage your Product Owners/Stakeholders to put in such natural language indicators – it makes your site easier, safer, and your regression suite more solid. And your users will appreciate instant feedback it too. If your product managers insist on ‘silent’ feedback, remember you can use Capybara to assert that things are or aren’t disabled, grayed-out, etc.

Basically, although you can sometimes get away with expectations that do direct Ruby object lookup, you really shouldn’t, or should use it as infrequently as possible

Wait Helpers (Ruby metaprograms Javascript)

Sometimes you’ll see a spec failure that will pass if you add sleep 1 or sleep 2. Avoid this, but use a very fast sleep (I use 0.1) when necessary. Instead of sleeping, turn off animations and write wait helpers for yourself to pause until certain conditions are met.

You should use wait helpers to wait for:

– Ajax requests that Capybara doesn’t seem to pick up natively (Later versions of Capy are supposed to count the number of outstanding Ajax requests but I’ve had difficulty getting this to work consistently. You can and should assert content is on page and prefer Capybara’s native waiting to a wait helper)

– Your app is doing something like initializing (you can even write your app to set itself a global flag when initialization has finished which can be checked from Capy helpers)

Here’s an example of a wait helper that waits for an Ajax request. Note here we are using page.evaluate_script to metaprogram Javascript by way of Ruby code, waiting until a condition is met before continuing the spec.

def wait_for_ajax
 counter = 0
 while page.evaluate_script(“$.active > 0”)
  counter += 1
  print “_”
  $stdout.flush
  sleep(0.1)
  if counter >= 100
   msg = “AJAX request took longer than 10 seconds.”
   if page.driver.respond_to?(:console_messages)
    msg << ” console messages at time of failure: ” + page.driver.console_messages.inspect
   end
   raise msg
  end
 end
end

Here’s an example of a wait helper that would wait for your app’s own initialization cycle, provided yourApp is the variable in Javascript where you app is namespaced, and when it is finished with its own initialization cycle it sets _initialized to true (on itself). You can write your own wait helpers appropriate to things you app does.

def wait_for_your_app
 counter = 0
 while page.evaluate_script(“typeof(yourApp) === ‘undefined’ || typeof(yourApp._initialized) === ‘undefined'”)
  counter += 1
  print “~”
  $stdout.flush
  sleep(0.1)
  raise “Your app failed to initialize after 10 seconds” if counter >= 100
 end
end

Explicit Sleeps

When all else fails sometimes you just need a sleep, which you just do in ruby as sleep X where [X] is the number of seconds you want to sleep.

You should use sleeps very rarely, but I’ve found they are needed in these cases:
– After an Ajax request, sometimes a sleep is needed to let the database catch up. (I try to keep these at about 0.5 seconds)
– A small timing delay (no longer than 0.1 seconds) for your app doing something like re-rendering

In theory you can wait for anything, so try to use Capybara’s internal waiting mechanisms first. In this order, your toolkit is:

1. Capybara’s internal waiting
2. A wait helper (as explained above)
3. An actual explicit sleep (try to keep all sleeps under 0.2 secs)

Remember each knife is shaper than the next, and so you should strive for minimal intrusiveness, but know that a combination of all three is likely necessary. The more astray you go from the art the more likely you experience timing delays.

Warning for anyone who has an expires_in set as a cache-control header in your controller endpoints (html or json).

Yes you! Go look in your code right now for expires_in set in your controllers and if you have any pay attention.

As I documented here, you’ve got to watch out if you have endpoints that have non-Zero cache-control headers on them. The headless driver (poltergeist or webkit) will hang onto the HTTP response between specs. This can be detrimental to you, if, say, the content of that endpoint’s response is what you are testing. In my case, I just used an inelegant hack to work around this- suggestions for improvements welcome.

if Rails.env.test?
 expires_in 0.minutes, :public => false
else
 expires_in 3.minutes, :public => true
end

Conclusion

Try to keep your feature specs to about 1-3 minutes to run per file, also maybe split them off when they are about 200-300 lines long. Be mindful of the total run time – since they are so valuable you can afford a little leeway here but keep in mind it slows down you time to develop new features.

Be careful about assertions that reach back into the database. Although you can get it to work, reloading objects and asserting things have changed is prone to race conditions, particularly with database cleaner. Remember that you have two threads operating separately, and even if you are able to do .reload on the object to get it into the right state, it’s actually nearly always better when writing Capybara specs to just assert the UX has changed the way you think it will.

And finally: Patience, discipline, know that others have been here before you and others will come here again. You are on the pinnacle of Rails development – don’t fall! Patience and faith.

Suggestion or feedback? Log in with your Stackoverflow, Github, Facebook or Google account to leave a comment.

May 252016
 
def wait_for_ajax
 counter = 0
 while page.evaluate_script(“typeof($) === ‘undefined'”)
  counter += 1
  print “^”
  $stdout.flush
  sleep(0.1)
  raise “Jquery not initialized after 10 seconds.” if counter >= 100
 end

 counter = 0
 while page.evaluate_script(“$.active > 0”)
  counter += 1
  print “_”
  $stdout.flush
  sleep(0.1)
  if counter >= 100
   msg = “AJAX request took longer than 10 seconds.”
   if page.driver.respond_to?(:console_messages)
    msg << ” console messages at time of failure: ” + page.driver.console_messages.inspect
   end
   raise msg
  end
 end
end

May 212016
 

First, on Heroku, you’ll need to add a special buildpack to your slug:

(note that all of the following commands you may need to append with -a if you manage more than one Heroku app)

heroku buildpacks:add -i 1 https://github.com/jasonfb/heroku-buildpack-cedar14-imagemagick695

(Here -i 1 tells the command you want the buildpack at index 1. It’s important that you include this flag or else the Heroku API will add your buildpack before the default build, which is known simply as heroku/ruby)

(If you’d prefer to use ImageMagick 7.0.24, I’ve also made a buildpack for that available here: https://github.com/jasonfb/heroku-buildpack-cedar14-imagemagick704)

You can and should examine what you just added with:

To examine what you just did:

heroku buildpacks

You should see the response:

$ heroku buildpacks:add -i 1 https://github.com/jasonfb/heroku-buildpack-imagemagick695

Buildpack added. Next release on app-xyz will use:
 1. https://github.com/jasonfb/heroku-buildpack-imagemagick695
 2. heroku/ruby
Run git push heroku master to create a new release using these buildpacks.

To undo what you just did

heroku buildpacks:remove https://github.com/jasonfb/heroku-buildpack-imagemagick695

Then push your app to your repo. You will notice it takes a few minutes to compile the new ImageMagick binary and install it into the slug.

You can set the :convert_options in your paperclip definitions, or to make a global change to all your definitions use a monkeypatch like so:

Create a file for paperclip init if you don’t already have one

config/initializers/paperclip_defaults.rb

Monkeypatch the Paperclip processor with the resize filter of your choice.

module Paperclip
 class Processor
def convert(arguments = “”, local_options = {})
 if (arguments =~ /-resize/)
  arguments.sub!(“-resize”, “-filter Lanczos -resize”)
 end
 Paperclip.run(‘convert’, arguments, local_options)
end
 end
end

You can read all about the kinds of filters here.