using domainFACTORY with heroku and SSL

I’m working on a small side project that requires proper SSL configuration. Since I like using heroku to bootstrap my projects, I thought it would also be a great idea to do that in this case… As it turns out, it was quite a hassle to get it up and running the way I want it to be.

When you create a new app on the cedar stack you get SSL for fee. The only downside here is that this is only true for the your-app.herokuapp.com subdomain that hosts your application. If you want to add SSL to your custom domain it get’s a bit hairy.

Custom Domain SSL

Once you have added your domain to heroku and delegated the the name-server lookup via CNAME, you need to provision a SSL addon that costs $20 per month. This is just for the addon, no batteries included! So you also need to buy a SSL-certificate from the authority of your choice.

This setup is unfortunately not working with my hosting provider domainFACTORY as they allow only subdomains to be aliased via CNAME, the root-domain is not configurable. So you can forward www.yourdomain.de but not yourdomain.de.

CloudFlare to the rescue

The CDN provider CloudFlare has free SSL support when using the Pro Plan that also costs $20. This is a bargain compared to the heroku SSL-plugin as CloudFlare has way more use-cases than just SSL.

Configuring the DNS on domainFACTORY is quite simple. Just go to Für Profis > Nameserver-Einstellungen in your admin setup and remove all the DNS entries. Add the CloudFlare name-server settings to the bottom:

53b2316ec38aa55143368943

DNS + SSL made simple!

structuring your RSpec project

it is an established convention to put all your rails tests or spec in the test/spec folder. even jasmine javascript files go in spec/javascripts… seriously, wtf?

cucumber features on the other hand go in the features folder… so?

while i don’t like cucumber (because of the additional complexity that comes with gherkin), i like the idea that they think about features as something different.

when writing acceptance tests i put them in the acceptance folder and have a different spec_helper file (usually called acceptance_spec_helper.rb as RSpec runners get confused with multiple spec_helper-files).

acceptance tests and normal rails tests have orthogonal requirements that should be handled in using different setups!

i like to have use_transactional_fixtures and random test execution turned on for regular Rails tests because it’s super fast and each spec should be independent of other tests.

it’s a different thing when writing acceptance specifications with capybara and a real browser that cover a user-session on a separate rails process and runs arbitrary actions against the server, executing JavaScript code within that context.

those acceptance tests have a basic problem when it comes to database queries. changes in one process/thread might not be seen in another one because of transactional visibility. this is often times hard to debug and mind-boggling. there are some “hacks” to get rid of this problem by sharing the same database connection, but they introduce other problems like race conditions.

long story short, i like to turn use_transactional_fixtures of and use fixtures (or hard-coded factory data) for running acceptance tests, as this fits more into the idea of acceptance tests. if you combine this approach with state-full page-objects, than you can write pretty readable tests like LoginPage.new.login(:bob).

I like to run DatabaseCleaner between each group of specs and recreate the fixtures, so they are fresh for each capybara spec file.
This setup comes pretty close to how cucumber does it, without all the cucumber-world craziness.

Some benefits that come with this approach:

  • faster spec runs for both suites
  • easy to separate out suites for CI
  • great for coverage reports
  • simple spec_helpers
  • separation of concerns via custom test modules

See the example configurations for more details.

monkey-patching Rails

I’ve been working a bit on a rails plugin for debugging html templates that we use at Shopify called partially_useful.

It’s a very simple helper that adds HTML-comments to the rendered source, so that you can inspect it easily in your browser’s developer toolbar. The comment hints look like this:

<-- start rendering 'some_partial' with locals '[:all, :assigned, :locals]'-->
<div class="hello">
    <div class="world">
      [...]
    </div>
</div>
<-- end rendering 'some_partial' with locals '[:all, :assigned, :locals]'-->

There are way more sophisticated plugins out there like xray-rails, but I prefer to have very simple tools that can be used without installing plugins or the like.

I used the plugin in various projects and ported it from Rails 3 to Rails 4, but it has never been more than a GIST on GitHub. Taking the time to actually convert it into a Railtie did not take long and allows everyone to use this plugin in their Rails projects.

All it does is intercepting the ActionView::PartialRenderer#render method, taking the return value of the call and wrapping it in HTML comments.

The tricky bit is how to inject this functionality into the original Rails code…

shoot yourself in the foot way

Just open up the ActionView::PartialRenderer class and overwrite the method!

While this might seem like the obvious way to do it, it makes everyones life worse, because it makes it much harder to find out where the f**** this new behavior is coming from…

Module#prepend

The nicest solution is to use Module#prepend. It allows you to inject a Ruby module in the first position of the inheritance chain. By doing this, your new render-method will get called and you can just pass everything along to super aka the original method.

The big downsides here are that this is not compatible with Ruby 1.9 and JRuby.

Module#alias_method_chain

This is a feature that Rails adds to Module and that allows you put another method in the call-chain by aliasing methods. I’m not a huge fan of it as I find the API rather confusing and it just works with Rails.

bare metal

If you include a Module that has a method with the same name as the method in the target class, the method of the Module will not get called when you invoke it on the class. This is because the methods of the class take precedence in the method-dispatch over those of ancestors in the inheritance chain (hence the Module#prepend). Because of that, you have to make way for the new method so that it can be invoked properly when you include a Module to override a method.

A way to do that is to use the Module#included callback to alter the class and alias the old method and remove the original afterwards

  def self.included(klass)
    klass.send :alias_method, :original_rails_render, :render
    klass.send :remove_method, :render
  end

conclusion

Meta-programming is hard, especially if you want to support multiple Ruby runtimes…

Debugging Rails Applications in Development

I’ve been spending a lot of time answering questions on Stack Overflow lately. From what I read, most of the questions come from unexperienced developers. It’s not easy to understand their questions because they often lack code examples, stack-traces or application logs. Because of that I keep repeating a lot of stuff in the comments or in my answers. I thought that it might be better to write everything down in a blogpost, so everyone has a chance to pick it up all at once.

The basics

When working with Ruby on Rails you will have to learn a lot of stuff to master debugging your own application. There are so many moving parts in a Rails app, it’s not just MVC…

  • Views (Partials, Layouts, Templating-Engines)
  • Controllers (Actions, Filter)
  • Models (Relations, AREL, Callbacks, Database-Systems)
  • Mailers
  • Routes (REST, HTTP-Verbs, Constraints)
  • Environments and Initializers
  • Caching (Redis, Memcached)
  • Assets (CSS, SASS, JavaScript, CoffeeScript, Pipelining)
  • Bundler and dependency management
  • Tests (RSpec, Capybara)
  • gems, plugins and engines used in the app

WOW, that is a LOT and I probably forgot some stuff…

Because of this overwhelming complexity, it is very important to know the basic tools that come with Rails and that help me in my everyday computering.

Using rake

Rake was intended as a Make for Ruby. It’s basically a build-tool that handles tasks. It has become the swiss-army-knife of Ruby and Rails. So make sure you know when it can be useful for you! The basic commands are rake -T to get a list of public commands and rake -D to get the full description of the tasks. If one of the commands fail, you can pass the --trace option to see what rake is doing under the hood and find possible error causes.

Here is a list of useful commands that I use when running into strange errors during development:

rake routes
rake middleware
rake assets:clobber
rake assets:clean
rake tmp:clear
rake log:clear

Reading stack-traces

It is happening to me all the time. The application spits out an error and I have no clue what is going on. Providing meaningful error messages is one of most neglected parts in writing maintainable software. On average, Ruby is very helpful in that regard, Rails is not! Nevertheless, you should always read the errors and stack-traces because they contain helpful information like the source file and the line number where an error was caused. It even provides information about the context, like the calling object and the call-stack when the error happened.

Let me give you an example exception:

undefined local variable or method `role' for #<Cucumber::Rails::World:0xc4722f8> (NameError)
  ./features/step_definitions/event_steps.rb:10:in `create_visitor'
  ./features/step_definitions/event_steps.rb:14:in `create_user'
  ./features/step_definitions/kid_steps.rb:107:in `/^I am exists as a parent$/'
  features/manage_kids.feature:11:in `And I am exists as a parent'

What I can see at a glance:

  • it’s about cucumber
  • we are in a step definition
  • the context object is of class Cucumber::Rails::World
  • there should be a role but it is not available
  • calling create_visitor caused this error
  • the source of create_visitor is in event_steps.rb on line 10

The source code that matches this error is this:

# event_steps.rb
def create_visitor
  @visitor ||= { 
    :email => "user@example.com",
    :password => "test123", 
    :password_confirmation => "test123", 
    :role => Role.find_by_name(role.to_s) # this is line 10
  }
end

It is just an excerpt of the code, so it’s a good idea to add real line-numbers or an anchor so other people know where we are. In this example, this would not even be necessary, because role is only called once. Without knowing anything about the source, I can immediately see that the author wanted to use something that is not there.
So possible solutions to this might be to use @role or maybe @visitor.role or to have a method called role or pass it in as a parameter to that method. If the test has run successfully before doing any changes, the error was probably introduced by some changes you did and should be easy to find.
So always make sure your test suite passes before writing new code.

Side Note

Never throw away exception information unless there is a good reason! Swallowing exceptions causes a lot of pain for people that have to maintain the running application, so please at least log the error message when you rescue from something.

Reading code

One of the key skills for writing code is reading code in the first place. Whether it is code I wrote some time ago, code of my coworkers or library code. It’s super important to understand the code at hand and the code that my application is executing. Compared to other languages, where one has to deal with compiled sources, it’s incredibly easy to have a look at ruby sources. I often run bundle open some_gem to look at the source or when you are not using bundler run gem env and look at GEM PATHS where your gems are installed

gem env

RubyGems Environment:
  - RUBYGEMS VERSION: 2.1.5
  - RUBY VERSION: 2.0.0 (2013-06-27 patchlevel 247) [x86_64-darwin12.4.0]
  [...]
  - GEM PATHS:
     - /Users/paule/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0
  [...]

subl ~/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/rails-4.0.0/

I also often use dash to get method documentation.

Debugging the running server

Rails coding is often CMD+R driven. I sit in front of the browser and reload the page to see if something happens… Unluckily it does not work the way I expected, so what to do next?

It’s in the logs stupid!

When I am working on a Ruby or Rails application i like to run stuff in iTerm2 with split views. One session for running spec, rails or the console and one session with the corresponding logs with tail -f log/development.log

Screen Shot 2013-10-16 at 10.22.00

Logs help with a lot of stuff and are a powerful tool to debug your running code. Things that can be extracted from the logs:

  • direct error information
    • error-messages
    • complete stack-traces
    • logged warnings or errors (attribute accessible warnings, deprecations)
  • context information
    • request parameters
    • request types (html, json, xhr…)
    • response codes
    • sql queries
    • rendered views and partials
    • callback informations

Since Rails introduced the asset pipeline, logs became pretty useless, because they were cluttered with asset calls. Disabling those logs does not need any ugly middleware monkey patches anymore because you can use the quiet_assets gem for this purpose!

One thing that I do to pimp my logs to be even more useful is to use the tagged logger that was introduced in Rails 3.2. It allows you to put even more context information into the log like the session-id and request-id:

# application.rb
config.log_tags = [
  :host,
  :remote_ip,
  lambda { |request| "#{request.uuid}"[0..15] },
  lambda { |request| "#{request.cookie_jar["_on_ruby_session"]}"[0..15] },
]

Quick inspects

There are a couple of “workflows” which I tend to use in my everyday debugging, starting with simply adding p some_object, puts some_object.inspect or logger.debug some_object calls randomly to the code. For view templates i use = debug(some_object).
This helps in about 50% of the error cases because it gives me enough context to find the problem quickly.

Another thing is putting a raise some_object.to_s into the code. This is especially helpful if I want to find out when and how some part of the code is executed. Callbacks are a good example where this is a nice shorthand method for debugging.

Insight tools

A running Rails server can provide a lot of useful information for debugging, especially if you curry it with the right helpers. Rails 4 already comes with some better error reporting and a route helper that can be accessed through navigating to an unknown route (thx ecki for the clarification). I use the /routes path for this purpose:

Screen Shot 2013-10-16 at 13.04.18

This functionality can be improved with a nice UI and a mini Rails console running in your browser if you add Better Errors and the Binding of Caller gem. These tools allow you to dive right into the error context and find out what might have went wrong. Combining this with raising my own errors gives me a lot of flexibility to quickly get to the point where I assume that something fishy is going on in the code.

Screen Shot 2013-10-16 at 13.02.46

When you are doing a lot of ActionMailer related stuff, you probably want to install the Letter Opener gem to develop and inspect your E-Mails.

The debugger

Having tools like Better Errors is super nice, but they are only suited for usage in the Browser. This is not always possible and I fall back to real debuggers that allow for moving around in the call-stack and inspecting objects at runtime.

The ruby-debug gem was the go-to-guy for a long time in Ruby land. It was a PITA to get this up and running in latest Ruby versions. That’s why I use the IRB replacement pry with a lot of extensions like pry-debugger or pry-nav. If you want to hook into a remote Rails process (ie. running rails via foreman) you can hook into it with pry-remote. Have a look at the Pry Railscast for more information.

Debugging through the console

The console is very important for me when writing new or changing existing code. I often create new finders and scopes in the console directly. A very important command in the console is reload!. It reloads all the code in the current session, similar to what happens when you hit CMD+R in the browser:

reload!; something_i_changed_in_the_editor.check_if_it_works

A thing that I find very helpful when stuck in a debugging session is the method.source_location functionality introduced in Ruby 1.9. It allows me to see where a method is defined:

user.method(:url).source_location
=> ["/Users/paule/Documents/rails/on_ruby/app/models/user.rb", 39]

Use the force Luke

I like to use pry-rails as my default Rails Console. It enables me to browse source code, inspect objects and do a lot of other crazy stuff. Just type help in a pry session to see what commands are available. My favorite command is wtf? which shows the last raised exception and stack-trace.

Debugging through testing

I love test driven development! It is an everyday part of my programming routine. The only thing that I hate when doing TDD in Rails is the slow feedback loop. I don’t like using tools like spork or zeus as they introduce a lot of complexity and make debugging even harder.

So my approach to get away with minimal turnaround time is to start my new expectations by writing somthing like this:

describe User do
  it "does crazy stuff" do
    pry
  end
end

This rspec expectation will just open a new pry session where I can start coding right away, exploring my test with direct feedback from executing the code I want to test. This eliminates all the iteration- and startup time when running red/green cycles. It is especially useful when I don’t know exactly how something should function in the first place…

Debugging capybara

The last pattern is super useful when writing acceptance tests in capybara! I always forget how to use capybara expectations and matchers, because I write only a few of those tests. This is mainly due to the test pyramid and me being a backend developer.

There are also a lot more moving parts in acceptance tests, especially when running JavaScript tests in a headless browser. It’s super useful when you can just check page.body or temper with X-PATH expressions directly in the pry session.

If there is some strange behavior during test execution, I just put a breakpoint somewhere in the test and call save_and_open_page or even better: print out current_url and open the running test instance directly in the browser!

Other helpful tools

The Rails ecosystem comes with a lot of tools for debugging, but it can be enhanced even further:

Rails Panel

If you are using Google Chrome like me, you can use the Rails Panel plugin in combination with the Meta Request gem to get a Rails Developer Console in your browser. Super sweet!

Screen Shot 2013-10-16 at 11.21.51

cURL

If I want to look into response headers or other request/response specific information, I use curl in addition to the Chrome Developer Tools:

curl -I "http://hamburg.onruby.dev:5000/"

HTTP/1.1 200 OK
[...]

It is even possible to use the “Copy as cURL” option in the Chrome Developer Tools to get all the parameters necessary to redo some request!

Navicat

I use Navicat as a multi db frontend. It allows me to inspect what is going on in the database, check query results, indices and create data on the fly. Always have a good client for your data stores available!

GIT

I love git! It’s not the most self explanatory tool on the planet but it helps me so much when debugging applications. Just one example here is using git bisect. It executes a command for a range of commits, so that it is possible to find out which commit introduced a problem I am trying to debug.

Resources worth reading

Here are some websites that I keep referring to in a lot of my answers on stackoverflow. Go ahead and check all of them, really, I mean it!

freifunk

OMG, Apple rejected my App!

After releasing my first RubyMotion app (FC St.Pauli chants), I’m currently working on another one for Freifunk Hamburg.

I am using Testflight with a group of 10+ beta testers, to verify that my app is working properly and has no issues whatsoever.

The Review Process

When I think that an app is close to be feature complete, I create a version that can be pushed to the AppStore. This process involves setting up a distribution certificate and other stuff in iTunes connect. It’s a little time consuming and the review-process usually takes some weeks, especially for new apps.

I was not totally surprised that the first revision got rejected by Apple, eventhough they stated, that the app crashed on startup, which none of my beta testers had experienced. I thought that this might be due to some iOS 7 related changes.

So I just submitted an updated version to the review process. Unfortunately that version also got rejected…

The Crash Report

The latest reject was also due to a crash on startup. In case of a crash, Apple provides a Crash Report in the Resolution Center (it’s super easy to find… NOT: iTunes Connect>Manage Your Apps>[The App Icon]>View Details>Links>Resolution Center).

There is a lot of info in such a crash report. It starts with some basic infos about the device and app environment:

Incident Identifier: 7B2A05A2-E9C3-47F8-90DC-3C37BA634D69
CrashReporter Key:   edb549cbc4b5919b7c8a04beb0db00da1ada7c41
Hardware Model:      xxx
Process:             freifunk [6726]
Path:                /var/mobile/Applications/44317BE9-04A0-4B3E-A3D8-24134AE1B06C/freifunk.app/freifunk
Identifier:          de.nofail.freifunk
Version:             0.0.1 (0.0.1)
Code Type:           ARM (Native)
Parent Process:      launchd [1]
 
Date/Time:           2013-09-13 08:06:36.406 -0700
OS Version:          iOS 7.0 (11A465)
Report Version:      104

then comes the root cause:

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Triggered by Thread:  0

followed by the backtrace when the crash occured:

Last Exception Backtrace:
(0x2fe08f4e 0x3a6156aa 0x2f85ac 0x2f86d8 0x2608f4 0x25df9c 0x2c78f8 0x2e887c 0x2e003a 0x2c81c4 0x232d50 0x2e8854 0x2e003a 0x22f9e8 0x22fc60 0x2302f0 0x325eacb2 0x325ea702 0x325e4d0e 0x3257f6a2 0x3257e9a4 0x325e44f8 0x34a38708 0x34a382f2 0x2fdd39e2 0x2fdd397e 0x2fdd2152 0x2fd3cce2 0x2fd3cac6 0x325e3794 0x325dea3c 0x42d9c 0x42860)

infos about the threads that were active during the crash:

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
[...]
9   CoreFoundation                	0x2fd3cd58 CFRunLoopRunSpecific + 636
10  CoreFoundation                	0x2fd3cac6 CFRunLoopRunInMode + 102
11  UIKit                         	0x325e3794 -[UIApplication _run] + 756
12  UIKit                         	0x325dea3c UIApplicationMain + 1132
13  freifunk                      	0x00042d9c 0x32000 + 69020
14  freifunk                      	0x00042860 0x32000 + 67680
 
Thread 1 name:  Dispatch queue: com.apple.libdispatch-manager
Thread 1:
0   libsystem_kernel.dylib        	0x3abc183c kevent64 + 24
1   libdispatch.dylib             	0x3ab02220 _dispatch_mgr_invoke + 228
2   libdispatch.dylib             	0x3ab01fa6 _dispatch_mgr_thread$VARIANT$mp + 34
 
Thread 2:
0   libsystem_kernel.dylib        	0x3abd4c7c __workq_kernreturn + 8
1   libsystem_pthread.dylib       	0x3ac3adc6 _pthread_wqthread + 306
2   libsystem_pthread.dylib       	0x3ac3ac80 start_wqthread + 4
 
Thread 3 name:  WebThread
Thread 3:
[...]
6   WebCore                       	0x37ebebae RunWebThread(void*) + 414
7   libsystem_pthread.dylib       	0x3ac3cc1a _pthread_body + 138
8   libsystem_pthread.dylib       	0x3ac3cb8a _pthread_start + 98
9   libsystem_pthread.dylib       	0x3ac3ac8c thread_start + 4

Thread 4:
0   libsystem_kernel.dylib        	0x3abd4c7c __workq_kernreturn + 8
1   libsystem_pthread.dylib       	0x3ac3adc6 _pthread_wqthread + 306
2   libsystem_pthread.dylib       	0x3ac3ac80 start_wqthread + 4
 
Thread 0 crashed with ARM Thread State (32-bit):
    r0: 0x00000000    r1: 0x00000000      r2: 0x00000000      r3: 0x00002060
    r4: 0x00000006    r5: 0x3ca9318c      r6: 0x00000000      r7: 0x27dce594
    r8: 0x1450efa0    r9: 0x00000001     r10: 0x14569fb0     r11: 0x00000000
    ip: 0x00000148    sp: 0x27dce588      lr: 0x3ac3da33      pc: 0x3abd41fc
  cpsr: 0x00000010 

and the address space:

Binary Images:
0x32000 - 0x334ffb freifunk armv7  <3ae0aadc89773fe8a07f885fdaff2237> /var/mobile/Applications/44317BE9-04A0-4B3E-A3D8-24134AE1B06C/freifunk.app/freifunk
0x2bee8000 - 0x2bf0878a dyld armv7  <b37cba000c7d3f8ea414f060d45ce144> /usr/lib/dyld
0x2edd9000 - 0x2edd9fff Accelerate armv7  <8e17835efc9234da89e3080c47fad906> /System/Library/Frameworks/Accelerate.framework/Accelerate
[...]

Analyzing the Report

It’s not obvious what to do with such a report so Apple gives a Technical Note on this topic. You can also find some information in the Debugging Guide of the RubyMotion docs.

The big problem with the crash report are the missing identifiers. There is no hint for what might stand behind any of the memory addresses noted in the backtrace or whatever. That’s were Symbolication comes into play.

Symbolicating your RubyMotion Crash Report

Symbolication is the the process of converting the numeric addresses in the stacktrace to matching parts of the codebase. In order to get this working, you will have to keep the *.dSYM files that were generated with your release build. They are in the same folder as your .ipa file, that you are uploading to the AppStore (ie build/iPhoneOS-5.1-Release/freifunk.dSYM/).

It’s a good idea to backup those files! Otherwise you won’t have the possibility to ever know why a crash happened.

Symbolication is pretty easy once you know what to do. You can use the atos command line utility to “convert numeric addresses to symbols of binary images or processes”. Go to the release folder of your app and run the command with the exception backtrace, use the first address of the binary image as your base address and point to the executable binary:

cd build/iPhoneOS-5.1-Release
atos -o freifunk -l 0x32000 -arch armv7 0x2fe08f4e 0x3a6156aa 0x2f85ac 0x2f86d8 0x2608f4 0x25df9c 0x2c78f8 0x2e887c 0x2e003a 0x2c81c4 0x232d50 0x2e8854 0x2e003a 0x22f9e8 0x22fc60 0x2302f0 0x325eacb2 0x325ea702 0x325e4d0e 0x3257f6a2 0x3257e9a4 0x325e44f8 0x34a38708 0x34a382f2 0x2fdd39e2 0x2fdd397e 0x2fdd2152 0x2fd3cce2 0x2fd3cac6 0x325e3794 0x325dea3c 0x42d9c 0x42860

This produces a somewhat readable output:

0x2fe08f4e
0x3a6156aa
__vm_raise() (in freifunk) + 468
rb_vm_raise (in freifunk) + 280
rb_exc_raise (in freifunk) + 4
rb_name_error (in freifunk) + 92
rb_mod_const_missing (in freifunk) + 116
dispatch_rimp_caller(objc_object* (*)(objc_object*, objc_selector*, ...), unsigned long, objc_selector, int, unsigned long const*) (in freifunk) + 272
rb_vm_dispatch (in freifunk) + 4502
rb_const_get_0 (in freifunk) + 684
rb_scope__init_testflight__ (in freifunk) (app_delegate.rb:45)
dispatch_rimp_caller(objc_object* (*)(objc_object*, objc_selector*, ...), unsigned long, objc_selector, int, unsigned long const*) (in freifunk) + 232
rb_vm_dispatch (in freifunk) + 4502
vm_dispatch (in freifunk) + 504
rb_scope__application:didFinishLaunchingWithOptions:__ (in freifunk) (app_delegate.rb:3)
__unnamed_2 (in freifunk) + 316
0x325eacb2
0x325ea702
0x325e4d0e
0x3257f6a2
0x3257e9a4
0x325e44f8
0x34a38708
0x34a382f2
0x2fdd39e2
0x2fdd397e
0x2fdd2152
0x2fd3cce2
0x2fd3cac6
0x325e3794
0x325dea3c
main (in freifunk) (main.mm:15)
start (in freifunk) + 36

The interesting parts here in this stack are rb_scope__application:didFinishLaunchingWithOptions:__ (in freifunk) (app_delegate.rb:3) and rb_scope__init_testflight__ (in freifunk) (app_delegate.rb:45). They show that the app crashes during initialization in didFinishLaunchingWithOptions when calling the method init_testflight with the error const_missing. This is the matching code part:

  def init_testflight
    TestFlight.takeOff(NSBundle.mainBundle.objectForInfoDictionaryKey('testflight_apitoken'))
  end

So the problem seems to be that TestFlight was missing somehow. This was kind of weird, because I was using TestFlight for distributing my beta builds and all worked fine. Doing some grep in the compiled sources, I saw that the TestFlight SDK was not included in the distribution build. The underlying problem was, that the TestFlight source path was only set in an development block:

  app.development do
    app.testflight.sdk = 'vendor/TestFlightSDK'
    [...]
  end

Moving out of there fixed my crashing App version.

So the Freifunk App finally made it and you can get the in the AppStore!