Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[spaceship] rework reviews 📢 #8701

Merged
merged 9 commits into from
May 2, 2017
Merged

Conversation

hjanuschka
Copy link
Collaborator

@hjanuschka hjanuschka commented Mar 29, 2017

reworks interface for retreiving app store reviews.

require "spaceship"
Spaceship::Tunes.login("helmut@januschka.com")
app = Spaceship::Application.find("krone.at-fivexfive")


# get all reviews from AT
reviews = app.ratings.reviews("AT")

reviews.each do | review |
  puts "#{review.rating}"
  if review.responded? 
    puts "Already been responed to"
  end
end

@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for the commit author(s). If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google.

@googlebot
Copy link

CLAs look good, thanks!

@hjanuschka hjanuschka changed the title [WIP] [spaceship] rework reviews + support for developer response [spaceship] rework reviews + support for developer response 📢 Mar 29, 2017
Copy link
Collaborator

@giginet giginet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! 👍
I'm excited at this new feature.

I pointed some issues.
Let's discuss them.

def reviews(store_front, versionId = '')
client.get_reviews(application.apple_id, application.platform, store_front, versionId)
raw_reviews = client.get_reviews(application.apple_id, application.platform, store_front, versionId)
reviews = []
Copy link
Collaborator

@giginet giginet Mar 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can use map.

reviews = raw_reviews.map do |review|
  review["value"]["application"] = self.application
  AppReview.factory(review["value"])
end

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

many thx

attr_accessor :developer_response

attr_mapping({
'id' => :id,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you don't need to align columns.

attr_mapping({
  'id' => :id,
  'rating' => :rating,
....

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch, was inconsistent too 😢

response_attrs[:application] = obj.application
response_attrs[:review_id] = obj.id
obj.developer_response = DeveloperResponse.factory(response_attrs)
return obj
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove return.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sometimes i just forget about the non requirement for explicit return, was stuck in few other languages the last weeks - where return was explicit. -> fixed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok after testing, removing return here is faulty, and thats exactly the case why i like explicit returns, in this case a DeveloperResponse (which is in a attr of obj) is returned, where as it is intended to return a AppReview (which is hold in obj)

r = request(:get, "ra/apps/#{app_id}/reviews?platform=#{platform}&storefront=#{storefront}&versionId=#{versionId}")
parse_response(r, 'data')['reviews']
index = 0
per_page = 100 # apple default
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be constants.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this would mean a constant of TunesClient? - i dont like that.

parse_response(r, 'data')['reviews']
index = 0
per_page = 100 # apple default
all_fetched = false
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can get rid of this variable to reduce side-effects.
It is better to break when the loop condition is filled.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed to loop do


def response?
return true if raw_developer_response
return false
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove return.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thx

end
end

def response?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean this method?

If you mean this app review is already responded from developers.
I think it is better responded?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, changed

all_fetched = false
all_reviews = []
until all_fetched
r = request(:get, "ra/apps/#{app_id}/platforms/#{platform}/reviews?storefront=#{storefront}&versionId=#{versionId}&index=#{index}")
Copy link
Collaborator

@giginet giginet Mar 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this OK these requests are executed synchronously?

Isn't it needed delay between each request?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they are synchronously, i tested it on a quiet large app - with a few hundreds of reviews and i haven't had a issue - the web interface also pages one after another.

client.create_developer_response(app_id: application.apple_id, platform: application.platform, review_id: review_id, response: text)
end

def update(text)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should also have bang suffix. because, this change is destructive.

update!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, fixed

@@ -323,9 +323,46 @@ def get_rating_summary(app_id, platform, versionId = '')
parse_response(r, 'data')
end

def create_developer_response(app_id: nil, platform: nil, review_id: nil, response: "")
data = {
responseText: response,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Question] If responseText is default value (empty string).
will API pass the value?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i bet it will fail 👍

Copy link
Collaborator Author

@hjanuschka hjanuschka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@giginet thx for your time, i addressed almost all of the feedback.

def reviews(store_front, versionId = '')
client.get_reviews(application.apple_id, application.platform, store_front, versionId)
raw_reviews = client.get_reviews(application.apple_id, application.platform, store_front, versionId)
reviews = []
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

many thx

attr_reader :last_modified
attr_reader :hidden
attr_reader :state
attr_accessor :application
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it simply didn't work with _reader if you look at the other spaceship classes, almost all of the attrs are by _accessor

attr_accessor :review_id

attr_mapping({
'responseId' => :id,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

heard about that, but i tried to stick to the current coding style used across the codebase - and attr_mapping always has the => (e.g: application.rb)

client.create_developer_response(app_id: application.apple_id, platform: application.platform, review_id: review_id, response: text)
end

def update(text)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, fixed

attr_accessor :developer_response

attr_mapping({
'id' => :id,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch, was inconsistent too 😢

@@ -323,9 +323,46 @@ def get_rating_summary(app_id, platform, versionId = '')
parse_response(r, 'data')
end

def create_developer_response(app_id: nil, platform: nil, review_id: nil, response: "")
data = {
responseText: response,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i bet it will fail 👍

parse_response(r, 'data')
end

def update_developer_response(app_id: nil, platform: "ios", review_id: nil, response_id: nil, response: "")
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above

r = request(:get, "ra/apps/#{app_id}/reviews?platform=#{platform}&storefront=#{storefront}&versionId=#{versionId}")
parse_response(r, 'data')['reviews']
index = 0
per_page = 100 # apple default
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this would mean a constant of TunesClient? - i dont like that.

parse_response(r, 'data')['reviews']
index = 0
per_page = 100 # apple default
all_fetched = false
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed to loop do

all_fetched = false
all_reviews = []
until all_fetched
r = request(:get, "ra/apps/#{app_id}/platforms/#{platform}/reviews?storefront=#{storefront}&versionId=#{versionId}&index=#{index}")
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they are synchronously, i tested it on a quiet large app - with a few hundreds of reviews and i haven't had a issue - the web interface also pages one after another.

Copy link
Collaborator

@giginet giginet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you to fix them!

I have a few concerns yet.
If they would be fixed, LGTM.

end

def responded?
return true if raw_developer_response
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If raw_developer_response is nil, responded don't returns false but nil .

I meant dropping return only. 🙇‍♂️

def responded?
  return true if raw_developer_response
  false
end

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

omg, thx for that, feeling a bit dumb now, fixed

@@ -323,9 +323,43 @@ def get_rating_summary(app_id, platform, versionId = '')
parse_response(r, 'data')
end

def create_developer_response!(app_id: nil, platform: nil, review_id: nil, response: "")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can app_id, platform and review_id be nil?

According to L332, these seem to be required.
If these values are required, default arguments should not be passed.
They have to be nonnull.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i know something like

def def create_developer_response!(app_id:, platform: , review_id: , response: "")

but it does not work on some older ruby's - i did a similar mistake on the IAP-Implementation, where we reverted to default values.

Copy link
Collaborator

@giginet giginet Mar 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These values must not be nil.
I think you can drop argument labels.

def create_developer_response!(app_id, platform, review_id, response)
end

Are labels needed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i personally preffer labels, in case of any refactoring its easier to handle.

eg adding a param in the middle.

def create_developer_response!(app_id, platform,new_param, review_id, response)

is sort a nightmare to refactor without labels, with labels it is no big deal.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I understood reasons.
Instead, how about adding nil checking?

Copy link
Collaborator Author

@hjanuschka hjanuschka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feedback addressed.

end

def responded?
return true if raw_developer_response
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

omg, thx for that, feeling a bit dumb now, fixed

@@ -323,9 +323,43 @@ def get_rating_summary(app_id, platform, versionId = '')
parse_response(r, 'data')
end

def create_developer_response!(app_id: nil, platform: nil, review_id: nil, response: "")
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i know something like

def def create_developer_response!(app_id:, platform: , review_id: , response: "")

but it does not work on some older ruby's - i did a similar mistake on the IAP-Implementation, where we reverted to default values.

Copy link
Collaborator Author

@hjanuschka hjanuschka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@giginet i addressed the handling of the nil params, let me know if this is ready to be merged now 👍

Copy link
Collaborator

@giginet giginet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

@hjanuschka
Copy link
Collaborator Author

@KrauseFx could you review this too, about the BC break (see pr body)

Copy link
Member

@KrauseFx KrauseFx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please wait with merging

@KrauseFx
Copy link
Member

KrauseFx commented May 1, 2017

Hey @hjanuschka, sorry for not coming back earlier. I'd be much in favor to merge the fetching the app reviews first. I personally would prefer not to include the replying to reviews part into spaceship itself. Do you think we could separate those 2?

@hjanuschka hjanuschka changed the title [spaceship] rework reviews + support for developer response 📢 [spaceship] rework reviews 📢 May 2, 2017
@hjanuschka
Copy link
Collaborator Author

@KrauseFx write ops - have been removed.

Copy link
Member

@KrauseFx KrauseFx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wonderful 🎷

@hjanuschka hjanuschka merged commit 5e180b3 into fastlane:master May 2, 2017
@nafu
Copy link
Collaborator

nafu commented May 2, 2017

Rock! 🚀

@hjanuschka
Copy link
Collaborator Author

and roll 🎶

@fastlane-bot
Copy link

Hey @hjanuschka 👋

Thank you for your contribution to fastlane and congrats on getting this pull request merged 🎉
The code change now lives in the master branch, however it wasn't released to RubyGems yet.
We usually ship about once a week, and your PR will be included in the next one.

Please let us know if this change requires an immediate release by adding a comment here 👍
We'll notify you once we shipped a new release with your changes 🚀

@fastlane-bot
Copy link

Congratulations! 🎉 This was released as part of fastlane 2.28.8 🚀

@fastlane fastlane locked and limited conversation to collaborators Aug 2, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants