ruby-aaws Get specific Album - ruby

I am trying to get a specific music cd from Amazon using ruby-aaws.
il = ItemSearch.new( 'Music', { 'Artist' => artist_title,
'Title' => album_name } )
rg = ResponseGroup.new( 'Large' )
req = Request.new(AMAZON_KEY_ID, AMAZON_ASSOCIATES_ID, 'de')
resp = req.search( il, rg, 5)
But this fails. It only seems to work when I search for artist or title, not both at the same time. What am I making wrong? If I construct the url by hand, it works prefectly, but I really don't want to parse the xml manually myself.

I've had a bit of a look at the code of ruby-aaws. It looks like you should be able to set $DEBUG to true before calling any of the ruby-aaws methods/classes and see what URLs are being requested. If there are any discrepancies between your handcrafted URL and the one being generated by ruby-aaws, this might give you some clues.

I just tried this use-case with the latest version of ruby-aaws and it works just fine.
I used the following for the ItemSearch (with the same code you posted initially):
il = ItemSearch.new( 'Music', { 'Artist'=>'The Smiths', 'Title'=>'Hatful' })
and got good results back as I would expect. Please try again and see if perhaps the latest ruby-aaws has ironed out a wrinkle which was stopping you.

Related

JXA: get containers of an element

Using JavaScript for automation in macOS, it's straightforward to get the elements of a container. But I can't figure out how to get the containers of an element.
In the Photos documentation, for example, an Album "contains mediaItems"; and a MediaItem is "contained by albums".
This works:
Application('Photos').albums[0].mediaItems()
This is what I want to write, but does not work:
Application('Photos').mediaItems[0].albums()
(resulting error:
Error: Can't get object. (-1728)
)
I've also tried to do something with the whose method, but I'm not quite sure how to write it:
Application('Photos').albums.whose({ /* what to put here? */ })
(Obviously I'd rather use the more direct route, if it exists, but if the proper way to do what I want is via whose, okay.)
I don’t think there’s a direct answer to this question. What you’re basically looking for, if I read you correctly, is, how can I use JXA to query a container based on its elements. That is, you want the answer to how to perform this AppleScript query in JavaScript:
tell application "Photos"
--get an arbitrary photo
set firstPhoto to the first media item
--get the albums that contain that photo
get the name of every album whose id of media items contains id of firstPhoto
end tell
This means going multiple levels deep, something like:
//this does not work
var firstPhoto = Application('Photos').mediaItems[0]();
var containingAlbums = Application('Photos').albums.whose({mediaItems: {_contains: firstPhoto}});
But according to the error this script generates, the albums object doesn’t even have a property called “mediaItems”.
Tantalizingly, if you were to run the following script you would see the ids of each of the albums that contains your photo:
//get a photo
var firstPhoto = Application('Photos').mediaItems[0]();
var firstPhotoId = firstPhoto.id();
albumQuery = Application('Photos').albums.mediaItems.where({id: {_equals: firstPhotoId}});
containingAlbums = []
for (var possibleAlbum of albumQuery[0]()) {
if (possibleAlbum != null) {
containingAlbums.push(possibleAlbum);
}
}
containingAlbums;
I see, for example,:
[Application("Photos").albums.byId("RLf9PUOxSLunpY5vFLLR6A").mediaItems.byId("68IM5jaiRDqIJhcKVBXo%w"),
Application("Photos").albums.byId("7QpA6wQrSEeIPyhu8xHlOw").mediaItems.byId("68IM5jaiRDqIJhcKVBXo%w"),
Application("Photos").albums.byId("SX8PbxO9S+a4%w4FvHH%Og").mediaItems.byId("68IM5jaiRDqIJhcKVBXo%w")]
But if I change the push line to containingAlbums.push(possibleAlbum.properties()); I see no property that will get the album name or even id back in any of the entries.
I asked a similar question about getting people from the same city in Contacts. The only solution I’ve been able to find is to get your media item and then loop through all albums.
//get an arbitrary photo
var firstPhoto = Application('Photos').mediaItems[0]();
var firstPhotoId = firstPhoto.id();
//loop through all albums and compile list of those that contain this photo
var containingAlbums = []
for (var possibleAlbum of Application('Photos').albums()) {
if (possibleAlbum.mediaItems.whose({id: {_equals: firstPhotoId}}).length) {
containingAlbums.push(possibleAlbum.name());
}
}
containingAlbums;
This is obviously not a satisfactory answer. I’m providing it in the hope that it may help you hack up a solution, and that someone will put up a better answer to prove me wrong.
In general, JXA support is spotty enough that if you don’t need one of its features that AppleScript doesn’t have, such as the ability to chain queries programmatically, it’s better to build the solution in AppleScript.

Youtube API V3 Insert Comment Issue

I'm essentially using the sample code provided by the docs here but I'm getting an error that reads ArgumentError - unknown keyword: snippet. Does anyone else have this problem as well? I'm not sure if this is a valid bug but intuitively the sample code they provide should work right?
properties = {
'snippet.parentId': '123',
'snippet.textOriginal': message
}
resource = create_resource(properties)
response = service.insert_comment('snippet', resource)
Upon digging through the actual library, I discovered that the way to pass in the snippet part is as follows:
snippet = Google::Apis::YoutubeV3::CommentSnippet.new(parent_id: parent_id, text_original: message)
comment = Google::Apis::YoutubeV3::Comment.new(snippet: snippet)
response = service.insert_comment('snippet', comment)
Hope this saves someone from a huge headache of having to chase through their docs

how to set search parameter in google-api-ruby-client

in order to retrieve the contents of a folder I have to use the following url
https://www.googleapis.com/drive/v2/files?q='root'
so I thought it should be working by passing an additional parameter
#client.execute(
:api_method => #drive.files.list ,
:parameters =>{q=> "title='root'" })
But this does not work
An error occurred: {"errors"=>[{"domain"=>"global", "reason"=>"invalid", "message"=>"Invalid Value", "locationType"=>"parameter", "location"=>"q"}], "code"=>400, "message"=>"Invalid Value"}
This is pretty obvious when I see the request uri
https://www.googleapis.com/drive/v2/files?q=title%253D%27levelA%27
My first attempt was to user URI.encode "title='root'" which does not work neither.
I really dont know how I could keep the single quotes ?
Best,
Philip
p.s.: a link to the mentioned gem http://rubydoc.info/github/google/google-api-ruby-client/frames
ok, now I found a working solution, even though it is a very cumbersome one.
search = CGI.escape("q='root'")
u.query = search
u= Addressable::URI.parse "https://www.googleapis.com/drive/v2/files"
req=Google::APIClient::Request.new(:uri=> u)
client.execute req
I hope this helps someone..

How to print validation error outside of field constructor in Play framework 2

How can I show a validation error for a form field outside of a field constructor in Play framework 2? Here is what I tried:
#eventForm.("name").error.message
And I get this error:
value message is not a member of Option[play.api.data.FormError]
I'm confused because in the api docs it says message is a member of FormError. Also this works fine for global errors:
#eventForm.globalError.message
You can get a better grasp of it checking Form's sourcecode here
Form defines an apply method:
def apply(key: String): Field = Field(
this,
key,
constraints.get(key).getOrElse(Nil),
formats.get(key),
errors.collect { case e if e.key == key => e },
data.get(key))
That, as said in the doc, returns any field, even if it doesn't exist. And a Field has an errors member which returns a Seq[FormError]:
So, you could do something like that (for the Seq[FormError]):
eventForm("name").errors.foreach { error =>
<div>#error.message</div>
}
Or (for the Option[FormError])
eventForm("name").error.map { error =>
<div>#error.message</div>
}
Or, you could use Form errors:
def errors(key: String): Seq[FormError] = errors.filter(_.key == key)
And get all errors of a given key. Like this (for the Seq[FormError]):
eventForm.errors("name").foreach { error =>
<div>#error.message</div>
}
Or (for the Option[FormError])
eventForm.error("name").map { error =>
<div>#error.message</div>
}
If you want more details, check the source code. It's well written and well commented.
Cheers!
EDIT:
As biesior commented: to show human readable pretty messages with different languages you have to check how play works I18N out here
To be thorough you're probably going to have to deal with I18N. It's not hard at all to get it all working.
After reading the documentation you may still find yourself a bit consufed. I'll give you a little push. Add a messages file to your conf folder and you can copy its content from here. That way you'll have more control over the default messages. Now, in your view, you should be able to do something like that:
eventForm.errors("name").foreach { error =>
<div>#Messages(error.message, error.args: _*)</div>
}
For instance, if error.message were error.invalid it would show the message previously defined in the conf/messages file Invalid value. args define some arguments that your error message may handle. For instance, if you were handling an error.min, an arg could be the minimum value required. In your message you just have to follow the {n} pattern, where n is the order of your argument.
Of course, you're able to define your own messages like that:
error.futureBirthday=Are you sure you're born in the future? Oowww hay, we got ourselves a time traveler!
And in your controller you could check your form like that (just one line of code to show you the feeling of it)
"year" -> number.verifying("error.furtureBirthday", number <= 2012) // 2012 being the current year
If you want to play around with languages, just follow the documentation.
Cheers, again!
As you said yourself, message is a member of FormError, but you have an Option[FormError]. You could use
eventForm("name").error.map(_.message).getOrElse("")
That gives you the message, if there is an error, and "" if there isn't.

How do I delete an embedded doc from Mongoid?

I'm having some issues deleting my document using Mongoid...
The code actually does delete the gallery, but I get a browser error which looks like:
Mongoid::Errors::DocumentNotFound at /admin/galleries/delete/4e897ce07df6d15a5e000001
The suspect code is below:
def self.removeGalleryFor(user_session_id, gallery_id)
person = Person.any_in(session_ids: [user_session_id])
return false if person.count != 1
return false if person[0].userContent.nil?
return false if person[0].userContent.galleries.empty?
gallery = person[0].userContent.galleries.find(gallery_id) #ERROR is on this line
gallery.delete if !gallery.nil?
end
My Person class embeds one userContent which embeds many galleries.
Strangely enough I've got a couple of tests around this which work fine...
I'm really not sure what's happening - my gallery seems to be found fine, and is even deleted from Mongo.
Any ideas?
find throws an error if it can't find a document with the given id. Instead of checking presence of given gallery and returning nil if it doesn't exist, you directly ask mongodb while querying to remove any such gallery.
def self.remove_gallery_for(user_session_id, gallery_id)
user_session_id = BSON::ObjectId.from_string(user_session_id) if user_session_id.is_a?(String)
gallery_id = BSON::ObjectId.from_string(gallery_id) if gallery_id.is_a?(String)
# dropping to mongo collection object wrapped by mongoid,
# as I don't know how to do it using mongoid's convenience methods
last_error = Person.collection.update(
# only remove gallery for user matching user_session_id
{"session_ids" => user_session_id},
# remove gallery if there exists any
{"$pull" => {:userContent.galleries => {:gallery_id => gallery_id}}},
# [optional] check if successfully removed the gallery
:safe => true
)
return last_error["err"].nil?
end
This way you do not load the Person, you don't even get the data from monogdb to application server. Just get the gallery removed if it exists.
But you should prefer #fl00r's answer if you need to fire callbacks and switch to destroy instead of delete
def self.removeGalleryFor(user_session_id, gallery_id)
# person = Person.where(session_ids: user_session_id).first
person = Person.any_in(session_ids: [user_session_id])
if person && person.userContent && person.userContent.galleries.any?
gallery = person.userContent.galleries.where(id: gallery_id).first
gallery.delete if gallery
end
end
ps:
In Ruby usually under_score naming rather then CamelCase is used
Kudos to Rubish for pointing me to a solution that at least passes my tests - for some reason fl00r's code didn't work - it looks like it should, but doesn't for some reason...
Person.collection.update(
{"session_ids" => user_session_id},
{"$pull" => {'userContent.galleries' => {:_id => gallery_id}}},
:safe => true
)
=> this code will pass my tests, but then once it's running in sinatra it doesn't work.... so frustrating!
have posted this code with tests on github https://github.com/LouisSayers/bugFixes/tree/master/mongoDelete

Resources