Ok, so over the last week or so I have been getting to grips with making api calls and then having the response returned as JSON and then outputting the parts I want to my view (getting there i think, albeit slowly). The next part of my learning curve is to take this data and save it to a model so that i can use it elsewhere in my app.
What i want to achieve is after the api request has been made and the results are displayed I want to click a button that will then post the data to my model
In this example I am getting data for books via its ISBN number from the itunes api
here is an example of the data returned
{
"resultCount":1,
"results": [
{"kind":"ebook", "artistId":545975179, "artistName":"Gareth Halfacree", "price":9.99,
"description":"<p><b>Make the most out of the world’s first truly compact computer<\/b><\/p><p>It's the size of a credit card, it can be charged like a smartphone, it runs on open-source Linux, and it holds the promise of bringing programming and playing to millions at low cost. And now you can learn how to use this amazing computer from its co-creator, Eben Upton, in <i>Raspberry Pi User Guide<\/i>. Cowritten with Gareth Halfacree, this guide gets you up and running on Raspberry Pi, whether you're an educator, hacker, hobbyist, or kid. Learn how to connect your Pi to other hardware, install software, write basic programs, and set it up to run robots, multimedia centers, and more.<\/p><ul><li>Gets you up and running on Raspberry Pi, a high-tech computer the size of a credit card <\/li><li>Helps educators teach students how to program <\/li><li>Covers connecting Raspberry Pi to other hardware, such as monitors and keyboards, how to install software, and how to configure Raspberry Pi <\/li><li>Shows you how to set up Raspberry Pi as a simple productivity computer, write basic programs in Python, connect to servos and sensors, and drive a robot or multimedia center <\/li><\/ul><p>Adults, kids, and devoted hardware hackers, now that you've got a Raspberry Pi, get the very most out of it with <i>Raspberry Pi User Guide<\/i>.<\/p>", "genreIds":["10017", "38", "9027"], "releaseDate":"2012-08-30T07:00:00Z", "currency":"USD", "genres":["Computers", "Books", "Computers & Internet"], "trackId":559783692, "trackName":"Raspberry Pi User Guide", "artistIds":[545975179], "artworkUrl60":"http://a2.mzstatic.com/us/r30/Publication/v4/ba/a8/2c/baa82ce0-2ac7-7026-04da-6f74bc97b403/9781118464496.60x60-50.jpg", "artistViewUrl":"https://itunes.apple.com/us/artist/gareth-halfacree/id545975179?mt=11&uo=4", "trackCensoredName":"Raspberry Pi User Guide", "formattedPrice":"$9.99", "artworkUrl100":"http://a4.mzstatic.com/us/r30/Publication/v4/ba/a8/2c/baa82ce0-2ac7-7026-04da-6f74bc97b403/9781118464496.100x100-75.jpg", "trackViewUrl":"https://itunes.apple.com/us/book/raspberry-pi-user-guide/id559783692?mt=11&uo=4", "averageUserRating":2.5, "userRatingCount":5}]
}
I would like to save the artistName, Description, an image (would i need paperclip for this?) and the trackName
Can anyone offer some advice on how i go about this, obviously I create a model and setup the table columns (I understand that the column names can be anything?) but after this Im a little lost
If anyone could proviede an Example that would be great as I could then follow the process and understand what is going on
Any help appreciated
One option would be to create a before_filter on your controller, you can list the controller actions that you want it performed for, ie. your API calls.
Within the method called from the before filter you can save the details of the request to a model. This would avoid the need for manually saving the information.
The image based on your example response has a URL to the image so you could just save that to your model assuming you are confident the image URL will not change. Should you want to save the image itself, yes I would recommend something like paperclip or carrierwave.
If you don't want to do it this way then an alternative, and in my opinion less tidy way would be to post the JSON back with a button to a controller action that does what I mentioned above.
EDIT: So to save to you model, for example called ApiCall you could create a new db entry each time your controller action is hit. Say your controller action is called get_info and it is passed the params that enables you to build the JSON response that you have described. You could do something like below.
json_response = JSON.parse(your_response_object)
ApiCall.create(:artist_name => json_response["results"]["artistName"])
You could obviously include any/all the information you had. Alternatively you could store the whole response as a YAML string in one db attribute and parse the information when retrieving it, up to you.
yaml = your_response_object.to_yaml
ApiCall.create(:payload => yaml)
Related
My goal is to write a validation class for Rails that is capable of using an OCR recognised text from a business card and is able to detect string snippets and assign them to the correct attributes. I know this cannot be probably 100% perfect but I want to get as close as possible. Here is my approach so far:
I scan business cards via jquery's navigator.mediaDevices
I send the scanned image to a third party API Service, called OCRSpace (a gem is available here: https://github.com/suyesh/ocr_space)
I then get a unformatted array of recognised text snippets back, for example:
result = [['John Doe'], ['+49 160 123456'], ['Mainstr. 45a'], ['12345 Berlin'], ['CEO'], ['johndoe#business-website.de'], ['www.business-website.de']]
I then iterate through the array and do some checks, for example
Using the people library (https://github.com/mericson/people)
to split the name in firstname and lastname (additionally the title
or middlenames) Using the phonelib library
(https://github.com/daddyz/phonelib) to look up a valid phone number
and format it in an international string
Doing a basic regex check on the email address and store it
What I miss now is:
How can I find out what the name-string would possibly be? Right now I let the user choose it (in my example he defines "John Doe" as the name and then the library does the rest). I'm sure I would run into conflicts when using a regex as strings like "Main Street" would then also be recognized as a name?
How do I regex a combination of ZIP-Code and City name? I'm not a regex expert, do you know any good sources that would help? Couldn't find any so far except some regex-checkers in general.
In general: Do you like my approach or is this way too complicated? And do you know some best-practices that look better?
Don't consider this a full answer, but it was too much to make it a comment.
Your way of working seems Ok but I wouldn't use the OCR Service since there are other ways , Tesseract is the best known.
If you do and all the results are comparible presented it seems not too difficult since every piece of info has it's own characteristics.
You can identify the name part because it won't have numbers in it, the rest does, also you can expect to contain it "Mr." or "Mrs." or the such and not "Str.", "street" and so on. You could also use Google Maps to check for correct adresses, there are Ruby gems but have no experience with them.
Your people gem could also help.
You could guess all of this, present the results in you webpage and let the user confirm or adjust.
You could also RegExpr the post-city combination by looking fo a number and string combination in either order but you could also use a gem like ZipCodes to help.
I'm sorry, don't have the time now to test some Regular Expressions now and I don't publish code without testing.
Hope this was some help, success !
I am learning iOS development. Currently, I started my hobby project which is a weather foracast app. I have found a open REST API, I can send request to get weather data for a city.
The REST API needs me to send request with city id instead of city name & it provides me a 20MB json file which contains city objects with fields city_id, city_name, longitude, latitude. I know I should create a City class to have those fields.
My app is supposed to allow user to input the city name, then, my app make request with the corresponding city id. My question is a about the best practice for this:
Since I need all city ids, should I download the 20MB json file & embed it to my app? Does that mean my app size would be larger than 20MB ? Any better practice to handle this?
If I have to put the 20MB json file in my project, what is the best way to parse the content to a list of City programmatically?
If user input one city name, I feel if I scan all the cities in the json file, it is inefficient, what could be the efficient way to find the city id for the city name (without scanning all the 20MB json)?
==== THE OPEN REST API ===
You do not need to include the JSON in your app. In fact, I highly recommend against doing so. This is according to the documentation:
Description:
You can call by city name or city name and country code. API responds with a list of results that match a searching word.
API call:
api.openweathermap.org/data/2.5/weather?q={city name}
api.openweathermap.org/data/2.5/weather?q={city name},{country code}
Parameters:
q city name and country code divided by comma, use ISO 3166 country codes
Examples of API calls:
api.openweathermap.org/data/2.5/weather?q=London
api.openweathermap.org/data/2.5/weather?q=London,uk
Given this information, you can send a request to the API like the example given: api.openweathermap.org/data/2.5/weather?q=London
The response should include the necessary data to make a subsequent call for the weather forecast.
No need to include 20MB of noise in your app bundle.
I'd create an array of City objects and parse the data into each City object (assuming you need all of them. If not, you'll have to find a way to parse out the ones youd on't want.) As long as you're not writing these to storage it shouldn't increase your app size, it may take a bit to download and parse depending on the methods you use, but that's all part of the fun of optimizing.
There are many JSON parsing iOS libraries, I have the most experience using RestKit to make network requests, and that includes a JSON to Objective-C Object parser built right in, it's super easy. Basically, do some research on JSON parser libraries and pick the one that best suits your needs. You shouldn't need to parse it yourself.
I'd create an NSDictionary with the city_name as your keys, and the city_id as your values. Then to retrieve the city_id simply call [dictionary objectForKey:enteredCity] (replacing with your actual variable names, of course)
I believe that they are asking you to bundle and not burden their server with requests for the 20mb file that doesn't seem to change much.
I would make a script that you run on your dev machine that turns this into a sqlite db (or some other serialized format). Don't bundle the JSON and parse at runtime --- turn it into something queryable at runtime.
What is the best way to handle QR code's Information, As QR code can have any information, For now, I want to handle only
1 URL and redirect to safari browser--> its fine
2 vCard and open contact book with contact values, But I'm seeing that VCARDS keys name are not unique(not sure if I'm Having improper QR codes). And also, QR value is a string to how to detect which value is for which key of address book?
e.g:
"BEGIN:VCARD
FN:Ashwin kanjariya
TEL:+999-999-9999
EMAIL:you#we.com
URL:http://www.youandme.com
N:kanjariya;ashwin
ADR:any address
ROLE:software developer
VERSION:3.0
END:VCARD"
So, I'm Not sure for VCARD all keys are universal or not? What is the best way to handle it?
I appreciate your any kind of suggest that can help me to figure out VCARD parsing.
Is CFDataCreate with ABPersonCreatePeopleInSourceWithVCardRepresentation best way to go with?(I have support for below IOS 9 as well)
like
let vCardnsdata = CFDataCreate(nil, UnsafePointer<UInt8>(vCard.bytes), vCard.length)
let addressbookDefaultSrc = ABAddressBookCopyDefaultSource(addressBook)
let vCardPeople = ABPersonCreatePeopleInSourceWithVCardRepresentation(defaultSource.takeUnretainedValue(), vCardData).takeRetainedValue() as NSArray
VCARD has several versions with slightly different implementations, keys don't have to be unique, a person can have multiple home or work phone numbers for example, but you should be able to tell what is a phone number and just accept as many as your customer believes is reasonable for their use case.
An extensive list of what you may find in VCARD's is here: https://en.wikipedia.org/wiki/VCard
If you want to make sure that all the data is stored, then you may have to implement lists, or in database terms, store items in different tables so that one to many relationships can be maintained for several items.
When designing a system to store information about people, you may also want to observe some of the Falsehoods Programmers Believe About Names
This is YouTube's 500 page. Can anyone help decode this information?
<p>500 Internal Server Error<p>
Sorry, something went wrong.
<p>A team of highly trained monkeys has been dispatched to deal with this situation.<p>
If you see them, show them this information:
AB38WENgKfeJmWntJ8Y0Ckbfab0Fl4qsDIZv_fMhQIwCCsncG2kQVxdnam35
TrYeV6KqrEUJ4wyRq_JW8uFD_Tqp-jEO82tkDfwmnZwZUeIf1xBdHS_bYDi7
6Qh09C567MH_nUR0v93TVBYYKv9tHiJpRfbxMwXTUidN9m9q3sRoDI559_Uw
FVzGhjH5-Rd1GPLDrEkjcIaN_C3xZW80hy0VbJM3UI5EKohX35gZNK2aNi_8
Toi9z3L8lzpFTvz5GyHygFFBFEJpoRRJSu3CbH5S2OxXEVo4HgaaBTV7Dx_1
Zs1HZvPqhPIvXg9ifd4KZJiUJDFS8grPLE7bypFsRamyZw-OCVyUHsGQKBwu
77pTtRwpF3hOxYLxM4KnAyiY1N6yrASSWyaeumRDENAoEEe8i8MRxzifqHuR
leatvNMiwsg1pbSl7IIiaKljZaD9UkRms4Kvz1uYUNk4AwXnJ9-Wq44ufMPl
syiHp_LwaeqyuxXykJMl-SA9p05VrJc4kCETUW3Ybp0yTYvVrqggo56A0ofC
OiyAmifQA9pdYVGeumrQtbFlFyDyG9VKNpzn5lqutxFZPsS8xjiILfF3bETD
H4aUb5fT4iERFsEL7S-ClsXiA4yAJdAcNH-OhGg9ipAaIxRRTOR5P1MYx6s6
-OrqgpT5VEaEx2hMpS1afaMd2_F21sxvcz2d8sCpEceHHSfsntTth6talYeD
4l63aUTbbCKV1lHxKWxdUjACFKRobeAvIpcJPcdHSN3CNQI-LlIWIx9jeyBU
tDcL6S6GpRG_Z2of9fmw0LHpVU5hKlQ3lCPd4pVP6J02yrsBi0S9OLoE9jmM
T2FfCvU1sWUCsrZu4-UPflXMyRnFK8aN8DYiwWWE8OvnLQ-LIaRDhjp29u9a
LT6Lh4KxEmWF5XeZTwrzJxtuDLVomxVD5mpwFvK0YSoaz9dnPGXb0Fm2txSL
BvGssSrWBJ4FeR6eEEkd_UkQ-aUnPv2W-POox17n54wzTwLugYjslRenMzmk
I4_jlXcx9NpKmUg7Pa0qJuaElt-ZymPv6h0cXRUlyZtS0iT9-CQOHWLYMi3I
kKrYa6bKUCAj058JEderSnbXqGEMvwBeZ_xgJpAjJiSgMOxJPokhbS6ezIv4
1JNr_dvQyvu4vh-YQNZ37fNTqQcoDZtYflBsJjuGrJlmIcqBYufB9g6nUaOE
xPAKjPdvZ_z1Rn_8sWVf8NHNBBKGe5lgDgBxypsV0kIwVa9QOlehivOaieBI
tmqHNdQIfdob0XUTEBPSeLj9hmw3Bqplc3gqUfFhIvpHml6dOTbjBhfkq0TE
5yCRHL2VSe2Xt9_i8SPQA2yCtJVO8HP6pnohmxqlBWSTE8Xj87PI6quX7f9i
0W6PdtkMYaGJsd_Ly_4Ag-KmGNHN585tF9eC5HeQ8Gz-vHZWOUiM4OQAG9UA
31ENOAjHtYb--ketbUcdX_FdjGiPtI_GxYeBqEShICotcd-S-E3bEGO-77M2
CuUUdB1AUYVDZR81XejVG5kSWsrz-p1qZ-6sSpSHCp114C6PheQPCwRHEr_1
AS-DkZfIuZ-w8XAo6pHIwvnv0dORSo-hPFgw1rw2VE4aKsgeMc7ZoPUxby1d
Zr-o-0X4ZMgxoQHw_Ub27rTTHxS5Czt_vgBPq7k5OK5dm6b7JCs6Dbn2dsIA
AakPL26t4smr8IiPAnqNC2sn7vxSiAe9mTJ670eNc6C9dCSGwqzqSURiLHmT
kFyLhNSOdipttECmSSA1qh_E0K4LUhiOq7MFDEzg9CLD8kuJrqpEGgltYpD-
8lk7KEpyjMqbWFs-qeD8uJpsVfY2ac1C67OmyGzkERVoC245-YXuNCP8KUZH
LGzRm9jXwUP_piDETX0N5xj34VOCfUTffT1WlWHmB9WRPhwjIsYYy_kgR-uT
kIEDQ23NVUEGgDoryl-ymysIfwifjq-lPB3e85dz1PajNxawsCrKNeR_4hhq
zE_E4ete1EgXeAYoeH4UIgrPGXDD-KfoNoB6viNs0GzNU9czD9Avr-tDtARO
HBLSLIVRYq8caMA-jvpplTOMoDdmUMUWytf4Y_F5tKTpNtLPaAe1py1IgZBl
lfAGY9L_k5slelh_9gUBEkURxS2oMGf2gdSeDdRBxKKx5tF1b-cuMLK6JYZJ
vbGFYSsSENOkHrHEo9NdTwTi7NON9ZgRJgh7OaENK4TFCXrhKc4C6cyJs-V_
HZ0Q-B8XDyjL0qudg_0rJbjTNpNZajT_1WGsnhsTTAgMCGtTsj1T8vNx2LuX
lPQV30nUKpukdCP3zuiE9_aeJQ-nzf3dMQ-KnZU5APmGcIP_u2be6blieMWH
qVax1asKmuIjslh49ceM6lRt3Ia2bHUB8b1TMSjU4I79KPqc3clDnD8quNnU
cRkgfJ_8LCEoH7jml_2TNV0fLuH_9IOXF3jKjhT9K5f-e5N06GmPQLzdqzeQ
MnEtHuDcf4IizyKnB5GUXoNfQxbScQEzztQ_nHMYfF-E8KqoxxlK-Z0wfEDv
dJpL3mcNfFu_vz-_LJ0oI4dE0-vthsxbpTxVQkdI0E5XSi4nYfLqhXompk4j
gpxcHBjsXVbWcnelWhhQP15gCApj6Gz_ddRtk_uxiyiqZ44oUUDcl1KeWMTf
yhKDj7jgGNzTOkUsXZRPb9M77-ZYPuL2wR68E3b9PC_mS6HBHiUxQ7pXvkwS
Bi2CoFgd9SqBXk2O5I_BPaEoA8Aorazw4OvDrmTQrCk4OkGPKRukE4Ci2RMq
TZIYbBz-v3QxmOKHJoMXPNOfj93TRWpmlAd6iHCH6BVlSdfgfjdbHeD0b0ct
qXC_-S5fr1XFBuaZwaUTrBPxU-3IxWLp-dx7wpKcFykqKnByYpkzR3twKEXc
z--CZV79Qk3ZTMY9ATia4HbyhoAqY_hV9GKAHQdU_C-9qwYt0rliNUcizlBc
RHcwzoMyx30ciwbE8e9QsEH_AMa3E2ezuhjTqQlAG33_Gy5Bwe7fj6zNR0ud
jjpcNVf-wprWHEYxMcKwjCQvEHBtv6TnCHkgi_AOtPzzm3aYkMc_ysdNAnI7
DE_T9S5Mkcs6VdT2DWgUN_UC-oAw27xej0aTIn0GckXPDcLBgvrUhUPU3FRn
lW65syvFvxFmBOiCAEHD1q6Is1XhIf8vE6y0FMdNEWSMUW5rQG8f3KP_pjqG
XlUHnGrQPQysylrczHOj4E3WTT918xg2vrXVraDJbCYnJpaWp8m94iqZw2gJ
I_0UWOAZJMCYWz5jYf2DanCOBaGeZIO-UsWorP6YV3yHehirZ_Lc6KtaUorb
bm_BnnCqGVZypL4k6cDy-4GyO2GNohXzN-VWqbAIUQIat9w6RsDpzpS2DIap
96aMBDg24D73RhFTEgCSunPpbbGrDVU3GFkuTGFFBQWNfAU_F22XtoPr_ZB0
1zZPrBVXrEhebvrzp0Z31_sIT8zLop_oaSRvykbyJKKxucARfPee-d0xlgWN
WwKKtl49WVMhhu0OfDScH3knAVdv0LDAyt1fo3WF8jxdp7J9Hn3OWF3rcn0p
zw0gt6YV_6FRy_UbZmpLBvEhZQKUfKuxp6LK-SfHOilT29ERg9LJZhnyluTV
HELRtkJIcHzvphXupCIaIgZispYxHNSmAfze2cshWBYizGTBSKXWgrJeo7Q6
kEjim72yKaJ8JaLzMQFPxtQxhtvHRw94dCuXcajg3nE_r_9t7D8RicqF-CVV
tvp-rHMPhhizlgfixHWXrPB7reTtftT64pOSl5vUop8gTlbeW5Kg7WQAPNfp
zUH8YcAo0xDLJHA-FgTM4mYGih41rKaKKteWRFGU-fIyEzeO1s35tbGzlZ7R
btUG_fCpIbaJmucMZK9OzVBSfBgTBtFSesqKq6hIc8HctGcj5LPUfP9DRqqe
CrBi6bPjTlzrjaxJoU6oRq4ZtiBG38skOAaCUk61tpjilkq1fmWe2ByvLXhp
O2furZoiwNrizYmUmAW3ak3iSneScA64M-9apdZwhhEgpqyw5mUMYNT5SOOf
xZePlgXxhlL81t3KlofdbzT0w6tlbbT0NSbj9Q_zNkeZ8ar5aeMgTR-pJACg
baB20YVezziX-yboCF-uIptCTFNV
(Source: this post on HN)
The debug information contained in the (urlsafe-)base64 blob is likely encrypted.
Think about it from Google's perspective: You would want to display a stack trace, relevant headers of the http request and possibly some internal state of the user session to help a developer debug the situation. On the other hand all that information might contain sensitive information that you don't want the general public to see or that might endanger the user if he copy'n pastes it in a public support forum.
If I was to take a guess of the format I would imagine:
A public identifier of the key used for encryption (their servers could use different keys then)
The debug data encrypted using an authenticated encryption scheme
Additional data for error correction when OCR has to be used
For statistical analysis of the format it would be interesting to sample a lot of these error messages and see if some parts of the message are less random than you would expect from encrypted data (symmetrical encrypted data should follow a uniform distribution).
It looks like you are not the only one who is looking for some secret messages in YouTube error page. It seems that you can decode it using Base64.
Here is how:
http://www.cambus.net/decoding-youtube-http-error-500-message/
In a nutshell:
Sadly, contrary to my expectations, there doesn't seem to be any
hidden message… Screw you, highly trained monkeys!
I guess it is just another Easter Egg similar to 'Goats Teleported' performance counter Google Chrome had:
https://plus.google.com/+RobertPitt/posts/PrqAX3kVapn
But I guess unless you look like this, you can't be 100% sure.
It's entirely possible that this is random padding to avoid the "friendly" IE error pages that show if your error page does not contain more than 512 bytes of HTML. It would be base64 encoded if it were simply random bytes.
Imho this is all about customer care.
Actually there would be no need to send the error/debug message to the customer, because, I guess, it's already handled internally.
So:
why do we see this?
and why do they crypt it?
and is there really no hidden message for us?
Although the error might be handled and resolved internally, this does not necessarily satisfy a customer, who is not able to use the product. They pretty much do crypt by a good reason as this debug message might reveal more than a typical admin is used to.
And also there is no need to hide a message for us. Why? Because we NEVER stop until we find something.
I think:
internally the error is dealt with
external users might have something in hand to tell a technician if necessary and in return can get an approximation of ongoing problem
All in all nothing special about it and i think linking e.g. to the inf. monkey theorem is a bit overspectulated...
Error 500 means google has a problem which can not resolve. So when reporting a bug the most important thing is to prepare reproduction steps. So I tried to find an answer of the question "When this happens?"
I found this post in reddit: https://www.reddit.com/r/youtube/comments/40k858/is_youtube_giving_you_500_internal_server_errors/?utm_source=amp&utm_medium=comment_list
As resume:
It happens on desktops (www...), it works ok on mobile version (m...)
It happens for authenticated users. For anonymous users is working fine.
The problem is resolved after cookies are cleaned.
So I would give a direction: try to find the key in the session cookie. I hope my 2 cents will help.
I am trying to figure out the best way to call REST actions that perform multiple actions and multiple database updates from a single call.
In my data model, I have Diners and LunchBoxes, and Foods. LunchBoxes are just many-to-many relationships between Diners and Foods, but with a count attribute that says how many of that type of food the given Diner has.
I want to set up a call that indicates that the Diner has eaten one of their Foods, which increases the health of the Diner accordingly. Certain foods are more nutritious than others, and consequently increase the Diner's health by different amounts. The actions that constitute this would be:
Reduce the count attribute on the Diner's LunchBox for the given food by the correct amount
Increase the Diner's health accordingly
So two tables need to be updated here: Diner and Lunchbox, both within a single transaction.
Trying to use nouns, the best I could come up with was:
POST /diner/frank/meal
Where the XML describing a meal would be something like
<meal>
<food>
<id>apple</id>
</food>
<count>2</count>
</meal>
However, this strikes me as pretty contrived. POSTing a meal in REST should create a Meal resource. In this case not only are we not creating a Meal resource, but we are updating two other resources: Diner and LunchBox.
I suppose one approach is to have the client handle this in two separate calls - one to update the Diner, and one to update the LunchBox. However, this seems wrong because we have multiple clients (HTML, Flash, etc.) that all need to perform this action. If we ever update the business logic in the future that is used to consume foods then we would need to make that change on many clients instead of on a single server.
How have others approached this admittedly pretty basic problem?
First off, the updating of the diner and the lunchbox should absolutely be done in one request. Don't fall into the trap of trying to do transactions over a REST api.
Before we get to your specific question, lets lay the groundwork for how the client could interact with your service leading up to your question.
The client should always start at the root service url.
GET /DiningService
Content-Type: application/vnd.sample.diningservice+xml
200 OK
<DiningService>
<Link rel="diners" href="./diners"/>
<Link rel="lunchboxes" href="./lunchboxes"/>
<Link rel="foods" href="./foods"/>
</DiningService>
I don't know the way your users will interact with the client software, but lets assume that we first need to identify who is going to do the eating. We can retreive a list of diners from looking in the response for a link with the rel="diners" and follow that link.
GET /DiningService/diners
Content-Type: application/vnd.sample.diners+xml
200 OK
<Diners>
<Diner Name="Frank">
<Link rel="lunchbox" href="./Frank/lunchbox"/>
</Diner>
<Diner Name="Bob">
<Link rel="lunchbox" href="./Bob/lunchbox"/>
</Diner>
</Diners>
What comes back is a list of diners. I have chosen to create custom media types for simplicity, but you may be better off using something like Atom feeds for these lists.
The client needs to identify Frank as the diner and so now we want to access his lunchbox. The rules of our custom media type say that the url to Frank's lunch box
can be found in a link element with a rel="lunchbox".
We get that URL from the response document and follow it.
GET /DiningService/Frank/lunchbox
Content-Type: application/vnd.sample.lunchbox+xml
200 OK
<Lunchbox>
<Link rel="diner" href="/DiningService/Frank"/>
<Food Name="CheeseSandwich" NutritionPoints="10">
<Link rel="eat" Method="POST" href="/DiningService/Frank?food=/DiningService/Food/CheeseSandwich"/>
</Food>
<Food Name="CucumberSandwich" NutritionPoints="15">
<Link rel="eat" Method="POST" href="/DiningService/Frank?food=/DiningService/Food/CucumberSandwich"/>
</Food>
</Lunchbox>
What we get back is another custom media type defining the contents of a lunchbox and links describing what we can do with that lunch box. Once the client chooses the food to eat, we can identify the URL to follow by looking for a link with rel="eat" and following that URL. In this case it is a post.
POST /DiningService/Frank?food=/DiningService/Food/CucumberSandwich
Content-Type: None
200 OK
I didn't think too hard about what the best way of structuring that url is because if I change my mind next week and make it
<Link rel="eat" Method="POST" href="/DiningService/Frank/Mouth?food=/DiningService/Food?id=759"/>
or even
<Link rel="eat" Method="POST" href="/DiningService/Food/CheeseSandwich?eatenBy=Frank"/>
it really does not matter to the client because it will continue to look for a link with rel="eat" and will follow the URL. You choose whatever URL structure works easiest for the web framework you have chosen. The URL structure belongs to the server and you should be able to change it whenever and have little or no impact on the client.
If you take this approach you can stop stressing over coming up with the perfect URL. This artificial notion of a "RESTful URL" has done more to prevent people from learning REST than SOAP ever did!
If you look at meal as an action on Diner, rather than an resource itself, this makes a bit more sense. However, I would be tempted to change the name to a verb, such as eat. When modelling a REST system, some of the decisions you make will be arbitrary. From a theoretical point of view, this action can be on both the Diner and the LunchBox. I tend to model according to how my app is used, so what fits with the UI and what is easier to explain to a third party in documentation etc.
There is nothing in the REST model that dictates the underlying structure or precludes you from handling quite complex transactions inside an action. In this case I would simply have an action that handles all of the logic using a transaction as necessary.
The action would operate on a diner, taking a list of foods and quantities.
In rails you would now have something like
# routes.rb
map.resources :diner, :member => {:eat => :post}
#controller
def eat
#diner = Diner.find(params[:id])
#diner.eat(params[:foods])
respond_to ...
end
end
You will notice that I have actually pushed the logic into the model. I am assuming that the Diner model has an association with a LunchBox model. The eat method will increment the health and change the food amounts in the related LunchBox. This way you can encapsulate all of the logic quite neatly.
UPDATE
I think it is quite a common pattern to have Resources with some specific named operations. I often just add actions to my controller, but keep within the general framework of REST by exposing these actions using HTTP and the Rails conventions.
You can certainly model your system with Meal as a Resource, but I think this results in extra complexity for your requirements.
It is also possible to model you entire system with only operations that map to the standard HTTP methods, but for real-world systems it's cumbersome and clumsy. In this world view, you start walking down the path of coordinating multiple http actions to compose a higher-order API. Such a system is pretty much impossible to build with a half-decent UI, and if you are exposing an API to third-parties they're going to hate you.