Frankie Frankie - 1 month ago 17
Ruby Question

Getting rails error when using Spaceship::Tunes

In a rails app I am running:

54 def itunes_all_apps
55 begin
56 Spaceship::Tunes.login(params[:itunes_username], params[:itunes_password])
57 apps = Spaceship::Tunes::Application.all
58 render json: apps.to_json, status: 200
59 rescue => e
60 render json: {error: e}.to_json, status: 500
61 end
62 end


It returns a status 500 error with no other information every time.

However, if I change this around slightly, for example getting teams (note, from Spaceship, not Spaceship::Tunes) this works fine:

def itunes_all_apps
begin
spaceship = Spaceship.login(params[:itunes_username], params[:itunes_password])
teams = spaceship.teams
render json: teams.to_json, status: 200
rescue => e
render json: {error: e}.to_json, status: 500
end
end


I'm not using any fast file or or config or anything. Just passing in a username and password via an api call and trying to get a response back. I'm new to rails so it may be my implementation of the Spaceship examples provided.

Using spaceship 0.36.1 gem (the latest)

I've poured through the docs to no avail. Grasping for any leads on what I'm doing wrong.

http://www.rubydoc.info/gems/spaceship/Spaceship/Tunes

https://github.com/fastlane/fastlane/blob/master/spaceship/docs/iTunesConnect.md

Someone suggested I run these two commands in irb, which I did, and they worked perfect!

Spaceship::Tunes.login('myAppleId', 'myPassword')
Spaceship::Tunes::Application.all


So it's not an iTunes account problem or credentials problem (because it works in irb), routes problem (because I ran both rails methods above with same route), or params problem (because I ran both rails methods above with same param names).

I really appreciate any suggestions. Thanks.

Edit:

Commenting out begin, rescue, and rending the error, the stack trace is as follows:

2016-10-24T17:47:34.974650+00:00 app[web.1]: Started POST "/api/v1/users/13/itunes_all_apps" for 162.237.102.13 at 2016-10-24 17:47:34 +0000
2016-10-24T17:47:34.977478+00:00 app[web.1]: Processing by Api::V1::UsersController#itunes_all_apps as JSON
2016-10-24T17:47:34.977521+00:00 app[web.1]: Parameters: {"itunes_username"=>"myCorrectUsername", "itunes_password"=>"[FILTERED]", "team_id"=>"myCorrectTeamId", "id"=>"13", "user"=>{}}
2016-10-24T17:47:35.629629+00:00 heroku[router]: at=info method=POST path="/api/v1/users/13/itunes_all_apps" host=myHerokuApp.herokuapp.com request_id=002d906d-354e-4633-8b54-71aa5181e3a7 fwd="161.237.102.13" dyno=web.1 connect=2ms service=657ms status=500 bytes=259
2016-10-24T17:47:35.619597+00:00 app[web.1]: Completed 500 Internal Server Error in 642ms (ActiveRecord: 0.0ms)
2016-10-24T17:47:35.620430+00:00 app[web.1]:
2016-10-24T17:47:35.620432+00:00 app[web.1]: IOError (not opened for reading):
2016-10-24T17:47:35.620434+00:00 app[web.1]:
2016-10-24T17:47:35.620433+00:00 app[web.1]: app/controllers/api/v1/users_controller.rb:58:in `itunes_all_apps'

Answer

It seems that Spaceship::Fastlane::Application does not implement as_json method and the default as_json touches some IO object, which cannot be represented as json.

My suggestion would be to create JSON serializer. You could use active_model-serializer, but if you do not want to create a dependency just for one object, then you can create your own serializer.

class SpaceshipApplicationSerializer
  attr_reader :spaceship_applications

  def initialize(spaceship_applications)
    @spaceship_applications = spaceship_applications
  end

  def as_json(options = {})
    spaceship_applications.each_with_object([]) do |spaceship_application, memo|
      memo << object_as_json(spaceship_application)
    end
  end

  def object_as_json(object)
    attributes.each_with_object({}) do |attribute, memo|
      memo[attribute] = object.send(attribute)
    end
  end

  def attributes
    [
      :apple_id,
      :name,
      :vendor_id,
      :bundle_id,
      :last_modified,
      :issues_count,
      :app_icon_preview_url
    ]
  end
end

# In your controller

def itunes_all_apps
  begin
    Spaceship::Tunes.login(params[:itunes_username], params[:itunes_password])
    apps = Spaceship::Tunes::Application.all
    render json: SpaceshipApplicationSerializer.new(apps).to_json, status: 200
  rescue => e
    render json: {error: e}.to_json, status: 500
  end
end

I guess you could create an issue here: https://github.com/fastlane/fastlane/issues, specifying your use-case.