Asana API: How do I remove a parent from a subtask with the new setParent endpoint - asana

According to the Asana API documentation it should be possible to remove a parent from a subtask, so the subtask becomes a normal task:
Creating a subtask is the same as a creating an normal task, but instead of specifying a workspace you must specify a parent task. Each task can only have a single parent and you can use the setParent endpoint to add or remove a parent from an existing task.
However it's not clear to me how i can remove a parent with this endpoint.
I've tried the following things as the body of the request
parent=0
=> 400 bad request
{"errors":[{"message":"parent: Not an ID: 0"}]}
null
=> 400 bad request
{"errors":[{"message":"Could not parse request data, invalid JSON"}]}
parent={subtaskid}
=> 500 error (makes sense that you can't add a subtask as parent of itself, but shouldn't be a 500 error I think)
{"errors":[{"message":"Server Error","phrase":"14 orange apes run smoothly"}]}
parent=
=> 400 bad request
{"errors":[{"message":"parent: Not an ID: "}]}
Is this at all possible, and if so, how?

(I work at Asana.) Have you tried parent=null?

Related

SAPUI5 & ODataModel V2: Find out which request groups have pending requests

I'm using ODataModel V2 and have 3 deferred request groups. If there are requests for more than one group I have to submit them in specific order.
Therefore I need to know which group has pending requests. Is there already a smart method for?
Definition of my request groups
Entry creations via Method "createEntry" are collected into group "create"
Entry deletions via Method "remove" are collected into group "delete"
Everything else is collected into group "changes"
What I've found out so far
The "delete" group is easy, if there is one, it's contained in "oDataModel.mDeferredRequests".
The "create" group is only contained in "mDeferredRequests" if there are also requests for the "changes" group. So if it's contained in "mDeferredRequests" I know that there are requests for both "create" and "changes".
But if there are only requests for either "create" or "changes" I've found only the way via method "getPendingChanges".
The newly created entities have the groupId included within the metadata like so:
NewObject('id-123456-00'):
Attribute: "123"
__metadata:
created:
changeSetId: "chgSet"
eTag: undefined
error: undefined
groupId: "create"
...
type: "..."
uri: "/sap/opu/odata/sap/..."
The changed entities have no groupId, they look like so:
UpdatedObject(Key='123'):
Attribute: "abc"
__metadata:
id: ".../sap/opu/odata/sap/..."
type: "..."
uri: ".../sap/opu/odata/sap/..."
So my only idea at the moment is to loop over the entries from "getPendingChanges" and check if there's a groupId or not.
As I'm not happy with this solution I'd like to ask you if there's a smarter way to determine the groups with pending requests.

Request inside request

I have two systems, which are communicating with each other.
Ideal state:
SystemA makes POST to SystemB
SystemB is processing create action
SystemB needs update data in SystemA thus it makes PUT to SystemA
SystemA updates relevant data
SystemB finishes create action
SystemA receives 200 response
But the problem is, that SystemA is waiting for end of POST action and is not answering to PUT from SystemB. Result is that SystemA is TimedOut and then PUT is processed correctly.
What could be the best and elegant solution? Should I move the POST action to the background job? Should I create new Thread for it?
edit:
PUT is made via ActiveResorce and changes attribute of object in SystemA

Rails: HTTP Get request from Callback Method (in model)

I want to create a callback in my User model. after a user is created, a callback is initiated to run get_followers to get that users twitter followers (via full contact API).
This is all a bit new to me...
Is this the correct approach putting the request in a callback or should it be in the controller somewhere? And then how do I make the request to the endpoint in rails, and where should I be processing the data that is returned?
EDIT... Is something like this okay?
User.rb
require 'open-uri'
require 'json'
class Customer < ActiveRecord::Base
after_create :get_twitter
private
def get_twitter
source = "url-to-parse.com"
#data = JSON.parse(JSON.load(source))
end
A few things to consider:
The callback will run for every Customer that is created, not just those created in the controller. That may or may not be desirable, depending on your specific needs. For example, you will need to handle this in your tests by mocking out the external API call.
Errors could occur in the callback if the service is down, or if a bad response is returned. You have to decide how to handle those errors.
You should consider having the code in the callback run in a background process rather than in the web request, if it is not required to run immediately. That way errors in the callback will not produce a 500 page, and will improve performance since the response can be returned without waiting for the callback to complete. In such a case the rest of the application must be able to handle a user for whom the callback has not yet completed.

Using Webhooks with Rails

I am unfamiliar with Webhooks but I feel like they are the right thing for my app.
I have the following documentation for FluidSurveys webhook
I understand how I can make the webhook through a POST request to their API, but I don't know how can I tell where the webhook is actually going to send the response.
Can I pass any subscription url I want? e.g. https://www.myapp.com/test and is that where webhook will send the data? Also, after the webhook is created I'm not sure how to ensure my Rails app will receive the response that is initiated.
I assume a controller method that corresponds with the url I provide to the webhook.
If I'm correct on the controller handling the webhook, what would that look like?
Any guidance is appreciated.
Webhooks hook into your app via a callback URL you provide. This is just an action in one of your controllers that responds to POST requests and handles the webhook request. Every time something changes to the remote service, the remote service makes a request to the callback URL you provided, hence triggering the action code.
I'll exemplify with the survey created event. You start by defining a callback action for this event, where you handle the request coming from the webhook. As stated here the webhook responds with the following body:
survey_creator_name=&survey_name=MADE+A+NEW+SURVEY&survey_creator_email=timothy#example.com&survey_url=http%3A%2F%2Fexample.com%2Fsurveys%2Fbob%2Fmade-a-new-survey%2F``
Let's leave the headers for now, they don't contain important information. The available body parameters (survey_creator_name, survey_name etc.) will reflect all details regarding the new survey available on the remote service. So let's write a callback action that handles this request:
class HooksController
def survey_created_callback
# If the body contains the survey_name parameter...
if params[:survery_name].present?
# Create a new Survey object based on the received parameters...
survey = Survey.new(:name => params[:survey_name]
survey.url = params[:survey_url]
survey.creator_email = params[:survey_creator_email]
survey.save!
end
# The webhook doesn't require a response but let's make sure
# we don't send anything
render :nothing => true
end
end
Let's add the route for this (in config/routes.rb):
scope '/hooks', :controller => :hooks do
post :survey_created_callback
end
This will enable the POST /hooks/survey_created_callback route.
Now you'll need to subscribe this callback URL to the Webhooks API. First you'll want to know which hooks are available to you. You do this by placing a GET request at /api/v2/webhooks/. In the response you'll find the event name, survey and collector parameters.
Finally, you subscribe to one of the previously listed hooks by placing a request to the POST /api/v2/webhooks/subscribe/ URL with the following contents:
{
"subscription_url": "http://your-absolute-url.com/hooks/survey_created_callback",
"event": "[EVENT NAME FROM THE HOOKS LIST]",
"survey": "[SURVEY FROM THE HOOKS LIST]",
"collector": "[COLLECTOR FROM THE HOOKS LIST]"
}
The response to this will be a code 201 if the hook was created successfully, or code 409, if a webhook for the same callback URL already exists. Or something else, if this went bad :)
You can now test the hook, by creating a survey on the remote service and then watch it getting replicated in your Rails app.
Hope this helps...

vcr does not know how to handle this request

Hi I am trying to test google auth with cucumber using vcr with a tag.
Everything goes fine till token expires. I think when it expires this happens
But I have a file with this content
http_interactions:
- request:
method: post
uri: https://accounts.google.com/o/oauth2/token
body:
If I allow vcr to record new requests the content of this cassette changes. I don't understand why, if the method and uri do not change POST to https://accounts.google.com/o/oauth2/token.
I changed tag to record new episodes and now test is passing... I am clueless.
I run the test again and now I am having this when POST to token url is being done:
Completed 500 Internal Server Error in 449ms
Psych::BadAlias (Unknown alias: 70317249293120):
Maybe you have some parameters inside the post, which are different for every request? If so, you can tell VCR to ignore this parameters by adding match_requests_on: [:method, VCR.request_matchers.uri_without_params("your_param")] to your VCR configuration.
In depth analyse your request, and find out which parameters are changing. You can tell VCR also to match on other criterias, have a look here https://www.relishapp.com/vcr/vcr/v/2-4-0/docs/request-matching
Ok, here's a solution...
The problem comes, as I said in the comment, from refreshing the token. When using oauth you have a token, which may be expired (or not). If you run the test and the token is fresh, that request isn't called. But if the token has expired it has to refresh it, and thus vcr throws an error.
To solve that, what I did is add the refresh token url to the ignored requests of vcr:
VCR.configure do |c|
c.cassette_library_dir = 'fixtures/vcr_cassettes'
c.hook_into :webmock # or :fakeweb
c.ignore_request {|request| request.uri == 'https://accounts.google.com/o/oauth2/token' }
end
It's not the best solution, since sometimes the token gets refreshed in the tests... but it's the best solution I could find...
I was getting the same issue with the same URL. For me, the problem was that my code was attempting to make the same call to https://accounts.google.com/o/oauth2/token more than once.
One of the potential solutions given in the VCR error message tells you the solution:
The cassette contains an HTTP interaction that matches this request, but it has already been played back. If you wish to allow a single HTTP interaction to be played back multiple times, set the :allow_playback_repeats cassette option
In my case, adding this option fixed the problem, as it tells VCR to revert back to its 1.x functionality of not re-recording duplicate requests, but simply playing back the result of a previously recorded duplicate request.
I am using Cucumber, so my solution was to add the following to my features/support/vcr.rb:
VCR.cucumber_tags do |t|
t.tag '#vcr', use_scenario_name: true
t.tag '#new_episodes', record: :new_episodes
t.tag '#allow_playback_repeats', use_scenario_name: true, allow_playback_repeats: true, record: :new_episodes
end
Notice the #allow_playback_repeats tag. I simply tagged my scenario with this tag, and everything worked properly thereafter:
#allow_playback_repeats
Scenario: Uploading a video initiates an upload to YouTube
Note that it doesn't work if you specify both #vcr and #allow_playback_repeats.
If you're using RSpec, you'll need to adapt the solution accordingly, but, it should be as simple as:
it "does something", :vcr => { allow_playback_repeats: true } do
...
end
I met the same problem, and finally found the there is a parameter changed every time.
you my solution is: copy and paste the mock parameter and real parameter together, and compare with them , and also make sure your next unit test would generate new parameter.

Resources