Related
I am still trying to create an app where the user could transform his name or a word with chemical elements (like breaking bad logo).
The user will enter a word in a text field and when he'll submit it will return him the word with the corresponding chemical symbols if they match, or it will display the "raw" letters if they don't match.
ex: If no symbol matches I am keepking the initial entry so it could be: hello => He ll O (bold char represent the existing chemical symbols)
I know this could be done in js, but the challenge is ROR (btw I don't know any js...)
In an earlier question I had just a hash like:
symbols =
{"cr" => "Cr",
"sb" => "Sb",
"ag" => "Ag",
"ar" => "Ar",
"as" => "As",
"at" => "At",
"n" => "N",
"ba" => "Ba",
"bk" => "Bk"}
and I was using name.downcase.gsub!(Regexp.union(symbols.keys), symbols)to transform the user entry. Actually I need more datas... that's why I chosen the json file.
Like on this picture i will need to use:
"number"
"small"
"molar"
(and the "name" will appear in a caption below)
I have organized a .json file with all the symbols I may need in the app and stored it in my config/periodic_table.json (pasted just a sample cause it's very long).
1°) If a user enter "hello" how do I loop to search for the "he" hash and print the "name","number", "small" and the "molar"
2°) I will use the json as a database (I will use heroku to deploy) so do I have anything to transform for using json and pg together?
[ "symbols"
{
"h": {
"name": "Hydrogen",
"number": 1,
"small": "H",
"molar": 1.00794
},
"he": {
"name": "Helium",
"number": 2,
"small": "He",
"molar": 4.002602
},
"b": {
"name": "Boron",
"number": 5,
"small": "B",
"molar": 10.811
},
"c": {
"name": "Carbon",
"number": 6,
"small": "C",
"molar": 12.0107
},
"n": {
"name": "Nitrogen",
"number": 7,
"small": "N",
"molar": 14.0067
}
}
]
I will need to loop first with the symbols that contain 3 chars, then 2 then 1... shall i change anythin in the json, like an harray for the hashes that contains 3 chars, another for 2 chars , and for 1char?
Correct Json Format
[{
"symbols":{
"h":{
"name": "Hydrogen",
"number": 1,
"small": "H",
"molar": 1.0079
},
"he":{
"name": "Helium",
"number": 2,
"small": "He",
"molar": 4.002602
},
"b": {
"name": "Boron",
"number": 5,
"small": "B",
"molar": 10.811
},
"c": {
"name": "Carbon",
"number": 6,
"small": "C",
"molar": 12.0107
},
"n": {
"name": "Nitrogen",
"number": 7,
"small": "N",
"molar": 14.0067
}
}
}]
What I'm looking for is, if inserted text contains chars and integer and if these not in List chars return false
Example List:
List = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
And the function should have 1 value like :
check(Text) ->
List = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"],
if the inserting text like is :
check("you should have 10 point to do this")
should return true cuz every thing in text exists within List
and if the inserting text like is :
check("you should + have ....")
should return false cuz " + " & " . " not exists within List.
Note that your first check example passes a string containing whitespace, which is not in List, so I'm assuming you want to handle that.
Here's one way to solve this:
check(Text) ->
List = "1234567890abcdefghijklmnopqrstuvwxyz \t\n.",
lists:all(fun(C) -> lists:member(C, List) end, Text).
First, note that here, List is not a list of strings, as you originally specified, but a list of characters. I've added the space, tab, newline, and period characters to List as well.
The second line of check/1 walks through the list Text character by character. For each character C we check that it's a member of List. If that test returns true for all characters, then lists:all/2 returns true, otherwise it returns false.
Here is how I iterate through my Json "data":
[myObject removeAllObjects];
NSDictionary *dic = jsonData[#"data"];
for (NSArray *ar in dic) {
[myObject addObject:ar];
}
Here is NSLog for myObject:
myObject: (
23,
22,
21
)
How can I iterate through all "data" (in 21,22,23 etc.) to add info about companies in to myObject array?
My Json structure:
{
"data": {
"21": {
"id": "21",
"company_id": "17",
"company_name": "Company 1",
"logo_url": "http://www.company.com/1.png",
"status": "2",
"allow_name": "N",
"allow_address": "N",
"allow_email": "N",
"allow_phone": "N",
"allow_birthday": "N",
"allow_gender": "N",
"created": false
},
"22": {
"id": "22",
"company_id": "5",
"company_name": "Company 2",
"logo_url": "http://www.company.com/2.png",
"status": "2",
"allow_name": "N",
"allow_address": "N",
"allow_email": "N",
"allow_phone": "N",
"allow_birthday": "N",
"allow_gender": "N",
"created": false
}
},
"success": 1
}
You should append the following sytax in your dictionary.
[valueForKey:#"company_name"]
Check the following tutorial: http://iosdevtips.co/post/80598241763/valueforkey-nsarray
NSMutableArray *aryData = [NSMutableArray new];
for (int i=0; i<myObject.count; i++) {
[aryData addObject:myObject[i]];
}
I've been trying for a few days now to get the Breeze 1.4.9 to work with a rails back end in a different manner than the Breeze Ruby SPA sample. I would rather send bulk save changes instead of trying to send RESTful calls to the server on every entity change. To that end, I've written a rails controller/model methods that will parse out all the different entities in a Breeze SaveChanges POST and act accordingly. Everything works great except that the response to SaveChanges POST doesn't seem to satisfy all the checks for Breeze and EntityManager.hasChanges() is still true even after the response is processed successfully.
Here's a typical cycle:
Breeze requests my hand crafted metadata and parses it fine:
{
"metadataVersion": "1.0.5",
"namingConvention": "rubyNamingConvention",
"localQueryComparisonOptions": "caseInsensitiveSQL",
"dataServices": [
{
"serviceName": "breeze\/Breeze\/",
"hasServerMetadata": true,
"jsonResultsAdapter": "webApi_default",
"useJsonp": false
}
],
"structuralTypes": [
{
"shortName": "VarianceReason",
"namespace": "Icon",
"autoGeneratedKeyType": "Identity",
"defaultResourceName": "VarianceReasons",
"dataProperties": [
{
"name": "id",
"dataType": "Int32",
"isNullable": false,
"defaultValue": 0,
"isPartOfKey": true,
"validators": [
{
"name": "required"
},
{
"name": "int32"
}
]
},
{
"name": "name",
"dataType": "String",
"isNullable": false,
"defaultValue": "",
"maxLength": 256,
"validators": [
{
"name": "required"
},
{
"maxLength": 256,
"name": "maxLength"
}
]
},
{
"name": "createdAt",
"dataType": "DateTime",
"isNullable": false,
"defaultValue": "1900-01-01T08:00:00.000Z",
"validators": [
{
"name": "required"
},
{
"name": "date"
}
]
},
{
"name": "updatedAt",
"dataType": "DateTime",
"isNullable": false,
"defaultValue": "1900-01-01T08:00:00.000Z",
"validators": [
{
"name": "required"
},
{
"name": "date"
}
]
}
]
}
],
"resourceEntityTypeMap": {
"VarianceReasons": "VarianceReason:#Icon"
}
}
I make an entity change in Breeze and it POSTs the below to rails when I call em.SaveChanges():
{
"entities":[
{
"id":-1,
"name":"anyuthingasd",
"created_at":"1900-01-01T08:00:00.000Z",
"updated_at":"1900-01-01T08:00:00.000Z",
"entityAspect":{
"entityTypeName":"VarianceReason:#Icon",
"defaultResourceName":"VarianceReasons",
"entityState":"Added",
"originalValuesMap":{
},
"autoGeneratedKey":{
"propertyName":"id",
"autoGeneratedKeyType":"Identity"
}
}
}
],
"saveOptions":{
}
}
Rails then responds with:
{
"KeyMappings":[
{
"EntityTypeName":"VarianceReason:#Icon",
"TempValue":-1,
"RealValue":16
}
],
"Entities":[
{
"id":16,
"name":"anyuthingasd",
"created_at":"2014-05-02T14:21:24.221Z",
"updated_at":"2014-05-02T14:21:24.221Z",
"Entity":null
}
]
}
Breeze then merges in the new id key mapping but doesn't clear the cache, so next time I make another entity change it still has the first change which has already persisted to the server and the new change. Can anyone tell me what I'm not responding with from the rails side that makes Breeze EntityManager not satisfied? I'm trying to trace through the 15k lines of code but can't say I'm a JS ninja.
We really do need to show folks how to build a data service adapter for whatever service they've got.
In this case, it appears you chose to implement something like the SaveChanges method in C# on the Web API. In other words, you've chosen to emulate the out-of-the-box Breeze protocol. That's cool! And non-trivial too so kudos to you.
I think what's missing from the entity JSON in your save response is the EntityType name. Breeze can't find the corresponding cached entities without knowing their types and thus cannot update their change-states.
Again, because you've decided to use the default Web API data service adapter, you'll want to return a response that adapter expects. That adapter defines a "jsonResultsAdapter" that expects each JSON entity data object to have a $type property specifying the full type name (namespace.typename).
In your example, I think you'd want to return
...
"Entities":[
{
"$type": "Icon.VarianceReason",
"id":16,
"name":"anyuthingasd",
"created_at":"2014-05-02T14:21:24.221Z",
"updated_at":"2014-05-02T14:21:24.221Z",
}
]
How about an example?
I suspect that you may not have easy access to a server with Web API that can show you what a save response looks like with the default adapter. Therefore, I've pasted below a Todo app's saveChanges request and response for a change-set that includes a new, a modified, and a deleted TodoItem.
The Request
Below is the payload of the POST request to the "SaveChanges" endpoint. It is probably way more verbose than you need (more verbose than I'd need). Just to pick one example, the "autoGeneratedKey" is of no interest to the server whatsoever.
I'm just showing you what the default data service adapter sends. Someday you'll write your own to do it the way you want it. For now I suppose there is no harm in sending too much crappola ... as long as you're happy to ignore it on the Rails end :-)
{
"entities": [
{
"Id": 5,
"Description": "Cheese",
"CreatedAt": "2012-08-22T09:05:00.000Z",
"IsDone": true,
"IsArchived": false,
"entityAspect": {
"entityTypeName": "TodoItem:#Todo.Models",
"defaultResourceName": "Todos",
"entityState": "Deleted",
"originalValuesMap": {
},
"autoGeneratedKey": {
"propertyName": "Id",
"autoGeneratedKeyType": "Identity"
}
}
},
{
"Id": 6,
"Description": "Modified Todo",
"CreatedAt": "2012-08-22T09:06:00.000Z",
"IsDone": false,
"IsArchived": false,
"entityAspect": {
"entityTypeName": "TodoItem:#Todo.Models",
"defaultResourceName": "Todos",
"entityState": "Modified",
"originalValuesMap": {
"Description": "Wine"
},
"autoGeneratedKey": {
"propertyName": "Id",
"autoGeneratedKeyType": "Identity"
}
}
},
{
"Id": -1,
"Description": "New Todo",
"CreatedAt": "2014-05-02T17:34:00.904Z",
"IsDone": false,
"IsArchived": false,
"entityAspect": {
"entityTypeName": "TodoItem:#Todo.Models",
"defaultResourceName": "Todos",
"entityState": "Added",
"originalValuesMap": {
},
"autoGeneratedKey": {
"propertyName": "Id",
"autoGeneratedKeyType": "Identity"
}
}
}
],
"saveOptions": {
}
}
The Response
The $id property is a node counter. It's useful when you have repeated entities so you don't have to worry about cycles or repeated entity data in your payload (an object with a $ref property is the placeholder for the repeated entity). You can ignore $id if you don't need this feature (and you rarely would need it in a save result).
Notice that the $type is in the .NET "CSDL" type format "namespace.typename", not the Breeze type format "typename:#namespace". This is an artifact of the data service adapter's jsonResultsAdapter ... which you can change to better suit your Rails implementation. None of this is cast in stone. I'm just reporting what these adapters do as delivered.
You can ignore the assembly name (", Todo-Angular") in the $type value; Breeze doesn't care about it.
Notice that the deleted "Cheese" entity was returned with all of its contents. I bet you don't have to do that. You could get away with returning a stripped down version that simply lets the client know Rails got the message:
{
"$id": "2",
"$type": "Todo.Models.TodoItem, Todo-Angular",
"Id": 5
},
And now ... the complete JSON response body:
{
"$id": "1",
"$type": "Breeze.ContextProvider.SaveResult, Breeze.ContextProvider",
"Entities": [
{
"$id": "2",
"$type": "Todo.Models.TodoItem, Todo-Angular",
"Id": 5,
"Description": "Cheese",
"CreatedAt": "2012-08-22T09:05:00.000Z",
"IsDone": true,
"IsArchived": false
},
{
"$id": "3",
"$type": "Todo.Models.TodoItem, Todo-Angular",
"Id": 6,
"Description": "Modified Todo",
"CreatedAt": "2012-08-22T09:06:00.000Z",
"IsDone": false,
"IsArchived": false
},
{
"$id": "4",
"$type": "Todo.Models.TodoItem, Todo-Angular",
"Id": 7,
"Description": "New Todo",
"CreatedAt": "2014-05-02T17:34:00.904Z",
"IsDone": false,
"IsArchived": false
}
],
"KeyMappings": [
{
"$id": "5",
"$type": "Breeze.ContextProvider.KeyMapping, Breeze.ContextProvider",
"EntityTypeName": "Todo.Models.TodoItem",
"TempValue": -1,
"RealValue": 7
}
],
"Errors": null
}
I have a breeze controller that adds an entity during the save changes that the client did not submit.
protected override bool BeforeSaveEntity(EntityInfo entityInfo)
{
if (entityInfo.Entity.GetType() == typeof(User))
{
if (entityInfo.EntityState == EntityState.Added)
{
User user = entityInfo.Entity as User;
OrganizationUser orgUser = new OrganizationUser()
{
Enabled = true,
OrganizationId = User.OrgId,
User = user
};
user.OrganizationUsers.Add(orgUser);
}
return true;
}
throw new InvalidOperationException("You can not use this service to modify an entity of type: " + entityInfo.Entity.GetType().Name);
}
When the response is returned the client side breeze manager sets the state of the server side added object as 'Added'. The OrganizationUser object above ends up with an Added state on the client. It then gets submitted in the next SaveChanges. Is this a bug?
Here is the response from the first save:
{
"$id": "1",
"$type": "Breeze.WebApi.SaveResult, Breeze.WebApi",
"Entities": [{
"$id": "2",
"$type": "LeonardoMD.Server.Api.Security.Admin.User, LeonardoMD.Server",
"Id": 9176,
"Email": "SearchProviderA#leonardoMD.com",
"FirstName": "SearchProviderA",
"LastName": "SearchProviderA",
"OrganizationUsers": [{
"$id": "3",
"$type": "LeonardoMD.Server.Api.Security.Admin.OrganizationUser, LeonardoMD.Server",
"UserId": 9176,
"User": { "$ref": "2" },
"OrganizationId": 421,
"Enabled": true
}]
}],
"KeyMappings": [{
"$id": "4",
"$type": "Breeze.WebApi.KeyMapping, Breeze.WebApi",
"EntityTypeName": "LeonardoMD.Server.Api.Security.Admin.User",
"TempValue": -1,
"RealValue": 9176
}]
}
Here is the submission of the second save:
{
"entities": [{
"Id": -2,
"CreateDate": null,
"CreateUserId": null,
"ModifyDate": null,
"ModifyUserId": null,
"Email": "SearchProviderB#leonardoMD.com",
"FirstName": "SearchProviderB",
"LastName": "SearchProviderB",
"BirthDate": null,
"GenderId": null,
"AddressLine1": null,
"AddressLine2": null,
"City": null,
"State": null,
"StateId": null,
"PostalCode": null,
"CountryId": null,
"DayPhone": null,
"DayPhoneExtension": null,
"Password": null,
"SecretQuestion": null,
"SecretAnswer": null,
"Enabled": null,
"AcceptTermsDate": null,
"entityAspect": {
"entityTypeName": "User:#LeonardoMD.Server.Api.Security.Admin",
"defaultResourceName": "Users",
"entityState": "Added",
"originalValuesMap": {},
"autoGeneratedKey": {
"propertyName": "Id",
"autoGeneratedKeyType": "Identity"
}
}
},
{
"UserId": 9176,
"OrganizationId": 421,
"Enabled": true,
"entityAspect": {
"entityTypeName": "OrganizationUser:#LeonardoMD.Server.Api.Security.Admin",
"defaultResourceName": "OrganizationUsers",
"entityState": "Added",
"originalValuesMap": {},
"autoGeneratedKey": null
}
}],
"saveOptions": {}
}
Notice the second entity is the entity returned in the response of the previous save changes. It's entityState is set to Added.
I have a work-around but its fragile and would need to be written special to every circumstance where the server returns a new entity after a save. Is there a way to set Breeze to acceptChanges on all new entities returned from the server as the the response to a saveChanges call?
manager.saveChanges()
.then(function (saveResult) {
$.each(saveResult.entities, function (i, entity) {
if (entity.organizationUsers && entity.organizationUsers().length > 0)
$.each(entity.organizationUsers(), function (index, orgUser) {
orgUser.entityAspect.acceptChanges();
});
entity.entityAspect.acceptChanges();
});
dfd.resolve();
})
.fail(function (error) { _this.handleError(context, promise, error); });
We were able to reproduce the problem and it is a bug. (The entity added on server should have returned to the client as an Unchanged entity)
We are working on a fix.
===EDIT===
The BeforeSaveEntity method is called once for each entity to be saved and should only manipulate the entity in question. You can find more about this at http://www.breezejs.com/documentation/custom-efcontextprovider.
If you want to create more entities to be saved in the server, you should do so in the BeforeSaveEntities method, where you can also add them to the saveMap dictionary to ensure they are saved in the DB.
i.e.
protected override Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(Dictionary<Type, List<EntityInfo>> saveMap) {
Dictionary<Type, List<EntityInfo>> saveMapAdditions = new Dictionary<Type, List<EntityInfo>>();
var prod = this.CreateEntityInfo(product, EntityState.Added);
// add data to the entity
saveMapAdditions[typeof(Product)].Add(prod);
return base.BeforeSaveEntities(saveMap);
}
As of Breeze 1.3.5, available now, this has been fixed. and thanks for the repro...