giant robots smashing into other giant robots

Written by thoughtbot

dancroak

Copycopter is now open source

One month ago, we informed Copycopter customers that we would be shutting the service down on April 15th and they would no longer be charged.

This news triggered a domino effect across the internet. AOL followed up by shutting down Instant Messenger. Milk then shut down Oink and users are fretting that Posterous will shut down after its acquisition by Twitter.

Copycopter logo

Why are we shutting it down?

Copycopter has worked beautifully for its purpose: editing live copy in Rails app using the I18n (internalization) API.

However, as a business, we try to make money and Copycopter has not served that purpose very well. So, we’ve been spending our time on other things.

What is happening to Copycopter now?

It is open source!

Why are we open sourcing it?

  1. It’s not really cool to run a service, then abruptly shut it down. We want to be awesome to our paying customers, many of whom still want to use the service.

  2. Copycopter is fantastic if you’re into Rails, translations, and not editing code and deploying every time copy changes.

  3. Open source code is the bee’s knees.

All the code has been moved over to the “copycopter” organization on Github. There, you’ll also find the Ruby client and a tight little style guide.

Who is maintaining it?

The fine folks at Crowdtap and Iora Health, two very strong Rails teams in New York and Boston, respectively.

They both use Copycopter for their own production apps.

How do I set it up as a new user?

Follow these instructions.

Or, watch this instructional, holiday-themed screencast:

How do I migrate my app from copycopter.com to open source?

Follow these instructions.

Thank you!

Thank you to all of Copycopter’s customers. We’re sorry we can no longer run the service but we’d be even sorrier if we gave you a half-assed effort.

We’re thrilled to be able to give Copycopter new life as an open source project and extremely grateful to the folks at Crowdtap and Iora Health for maintaining it.

We know them well from working together in the past. You might even call us friends.

Since open source is about people, you should get to know their handsome faces:

image image image image image image image image image John Norman Will Mernagh

Get to the choppah!

Written by .

lolconomy

This week in open source

bourbon

As a programmer I love the change that made it into version 1.3.6 (10f978d) of bourbon: Phil LaPier (plapier) added to work done by Frank (frankzilla) to add a monospaced font family, $monospace—with support for Bitstream Vera Sans Mono, my favorite monospace typeface (3467fe3 and c86e5687). Nice.

paperclip

Friday saw a new release of paperclip (1cb40e3), in accordance with the prophecy. It contains Windows support, a bug fix, and two new features.

Prem Sichanugrist (sikachu) has been working on handling characters that are not URL-safe; to this end he added a :restricted_characters option to has_attached_file, with a default value of &$+,\/:;=?@<>\[\]\{\}\|\\\^~%# , which specifies characters to replace with an underscore, _ (8353518 and 604304e). Benjamin Hüttinger (maxigs) added the ability to pass a block, evaluated at runtime, for :fog_host, :bucket_name, and :fog_credential options (e049ec5, 2b562a9, 8742615, and 1c88a72).

The gem itself had problems installing on Windows because a bundled test made sure that filenames with question marks were handled fine; turns out this simply breaks on Windows. Even though no actual programmers use Windows, we removed the offending file (ed5cd9f). Jon Yurek (jyurek) fixed a long-standing bug where the RSpec matchers (validate_attachment_content_type, validate_attachment_presence, and validate_attachment_size) didn’t handle the :if argument they were supposed to handle (5d4ba62).

capybara-webkit

A new release of capybara-webkit is in the works, and this is what you’ll see in it: Matthew Mongeau (halogenandtoast) added the ability to trigger mousedown and mouseup events (51c4dfe and 16c1637) while Joe Ferris (jferris) has commands block until the page finishes loading (18607d0).

clearance

Oh sweet, a new version of clearance is out (6c0c070)! In it you’ll find support for Rails 3.2 from Gabe Berke-Williams (gabebw), mostly in following deprecation warnings (6e57d10). Some prodding from Matthew Daubert (MDaubs) prompted us to upgrade cucumber-rails to 1.1.1 (691e867 and 91f4675). Dan Hodge (danhodge) dropped a totally awesome change on us, abstracting out the User class into Clearance.configuration.user_model, which can be changed at runtime (085a9b6, a582eec, and fc6af70). Dude, that’s awesome.

fake_braintree

Holy cow it’s version 0.2.0 of fake_braintree (0be2aea). In this Gabe Berke-Williams (gabebw) gave us the ability to specify a constant amount for a transaction (783719c), and mimics the behavior around customers with failing credit cards (a2ceb58).

factory_girl

No big news in factory_girl this week. Carlos Antonio da Silva (carlosantoniodasilva) updated the docs to mention that .stub is now .build_stubbed (08018f6). Michael Klishin (michaelklishin) fixed the build on Travis CI for Rails 3.2 by updating rubygems first (850116d). Joshua Clayton (joshuaclayton) found a spec that was not appropriately named, and fixed it (0d67a42).

kumade

While kumade did not see a deploy this week, it did see some feature improvements, some of which come with an API change.

The hook for running code just before deployment was originally run_predeploy_task but is now run_pre_deploy_task (764aebe). Chad Boyd (hoverlover) made this change so he could introduce the run_post_deploy_task, which is further exposed as kumade:post_deploy to Rake (da74087, f68a487, and 9679018).

Kumade now works with more stuff: Jammit 0.6.5 (ec63310) thanks to Vesa Vänskä (vesan), and Ruby 1.9.3 (8e73b90) thanks to Gabe Berke-Williams (gabebw).

Gabe also fiddled with some source code (7e0e11e, bb695b9 and 92aa8f4).

copycopter_client

A small documentation update occured in copycopter_client by Joe Ferris (jferris), reminding us that you can leave the name of the controller or model off of the translation key only when using t from a view (6416897).

jasonmorrisontb

Copycopter now supports editing multiple locales

Does your Rails app have more than one locale? Is it a pain to edit your internationalized copy?

We’ve heard your requests to better support multiple locales, and are excited to roll out multiple locale support in Copycopter.

You can try out the new multiple locale support in your existing Copycopter-backed apps, read more about how it works, or check it out during a free trial.

You’ll be able to manage the copy for multiple locales, share this responsibility with content experts on your team, and continue to roll out fresh updated copy without the overhead of redeploying your app. Copycopter will continue to hum along, serving up draft content to your development and staging environments while delivering content you mark as “published” to production.

If you already have multiple locales in your Copycopter app, great news! The locales are already in Copycopter, ready for editing. In fact, adding new locales to Copycopter is as easy as adding them to your Rails app. We’re continuing to stick with the Rails I18n API as a solid foundation, and adhering to its use for Copycopter.

We’d love to hear how you are using the multiple locale support in Copycopter. Let us know how it fits into your workflow.

Want to edit live copy in your Rails app without redeploying? Try Copycopter free for 30 days.

jferris

Copycopter: introducing a simpler way to edit copy

Around four months ago we launched our service for managing copy text in web applications: Copycopter. If you’re already riding the choppa, you’ve probably noticed steady improvements in the user interface. Today, we rolled out another change to make things nicer for non-technical users that want to edit copy text: a simpler editor.

What you see is what you get

We’ve done a lot to keep Copycopter simple to use. However, we also didn’t want to limit developers and designers by enforcing a limited language like textile, so we stuck to good old HTML. The draw back of this approach is that nontechnical users were occasionally confused by the markup in the copy text they wanted to edit. Worse, it was easy for such a user to break the page by accidentally changing the HTML to be invalid. We didn’t think it was acceptable for every user to be one “<” away from a broken page, so we changed this:

HTML editor

To this:

Simple editor

If you’d rather see HTML, don’t worry - we’re not leaving anyone out in the cold. One click will bring you back to the HTML editor you know and love:

Switch editor mode

We used the excellent jwysiwyg library to create our simple editor. Getting the editor up and running was easy, but making our integration tests work with the editor to ensure that it continued to work was a bit of a challenge.

TDDWYSIWYG

We used Cucumber to make sure that users could apply formatting to blurbs:

@javascript
Scenario: Apply formatting to blurbs
  Given the following blurb exists:
    | project         | key      | draft content |
    | name: Breakfast | test.key | <p>hello</p>  |
  When I go to the edit blurb page for "test.key" on "Breakfast"
  And I apply the "bold" editor function to "ell"
  And I apply the "italic" editor function to "el"
  And I press "Save Blurb"
  And I go to the blurbs index for the "Breakfast" project
  Then I should see "<p>h<b><i>el</i>l</b>o</p>"

To apply editor functions, we use this step:

When /^I apply the "([^"]+)" editor function to "([^"]+)"$/ do |function, selection|
  steps %{
    When I select "#{selection}" from the editor
    And I click the "#{function}" editor button
    And I unfocus the editor
  }
end

The secret sauce there is being able to select text. We used capybara-webkit to run Javascript scenarios in Copycopter, so we can use the DOM range and selection API:

When /^I select "([^"]+)" from the editor$/ do |text|
  within_editor do
    page.execute_script(<<-JS)
      var xpath = "//*/child::text()[contains(., '#{text}')]";
      var node = document.evaluate(xpath, document, null, XPathResult. ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
      if (!node)
        throw("Couldn't find text to select");
      var start = node.data.indexOf('#{text}');
      var end = start + #{text.size};
      var selection = window.getSelection();
      var range = window.document.createRange();
      range.setStart(node, start);
      range.setEnd(node, end);
      selection.removeAllRanges();
      selection.addRange(range);
    JS
  end
end

The “within_editor” method selects the iframe created by jwysiwyg, which is possible because of Aaron Gibralter’s contributions to capybara-webkit. We have several other scenarios for switching modes, handling newlines, and so on.

If you want to see our new editor in action, you should check out Copycopter!