extjs nested json store rails - ruby-on-rails

i am working with Ext JS & Rails as backend..i am having myysql database that has parent-child relationship i.e. 1-to-many relationship...I want a "single" JSON store that can be used to load "GRID" data with parent & child records..
Also is there any way to bind both - the form as well as the grid to the same store but having different jsonreaders? i.e. form's datareader would read the string with root: 'customers' and grid will read the string with root :'products'?
The JSON looks like this :
{
"customers": [{
"amt": 8000,
"custnm": "rashmi",
"id": 2,
"purdt": "2011-04-27",
"products": [{
"amt": 40,
"customer_id": 2,
"id": 3,
"prodnm": "oil",
"qty": 1,
"rate": 40
}]
}, {
"amt": 300000,
"custnm": "bhumika",
"id": 3,
"purdt": "2011-04-14",
"products": [{
"amt": 40,
"customer_id": 3,
"id": 1,
"prodnm": "soap",
"qty": 20000,
"rate": 20
}, {
"amt": 150,
"customer_id": 3,
"id": 2,
"prodnm": "shampoo",
"qty": 3000,
"rate": 50
}, {
"amt": null,
"customer_id": 3,
"id": 14,
"prodnm": "aa",
"qty": 2,
"rate": null
}]
}, {
"amt": 15000,
"custnm": "Shruti",
"id": 13,
"purdt": "2011-04-08",
"products": []
}, {
"amt": 200000,
"custnm": "Jayesh",
"id": 14,
"purdt": "2011-03-31",
"products": []
}, {
"amt": 220000,
"custnm": "SHRUTI",
"id": 15,
"purdt": "2011-04-06",
"products": []
}, {
"amt": 10000,
"custnm": "RASHMI",
"id": 24,
"purdt": "2011-04-06",
"products": []
}],
"results": 6
}

The new Ext JS 4 has Model associations which will solve the problem (http://docs.sencha.com/ext-js/4-0/guide/data)
// each User hasMany Orders
Ext.define('User', {
extend: 'Ext.data.Model',
fields: ['id', 'name', 'email'],
proxy : {
type: 'rest',
url : '/users',
reader: 'json'
},
hasMany: 'Orders'
});
// each Order belongsTo a User, and hasMany OrderItems
Ext.define('Order', {
extend: 'Ext.data.Model',
fields: ['id', 'user_id', 'status'],
belongsTo: 'User',
hasMany: 'OrderItems'
});
// each OrderItem belongsTo an Order
Ext.define('OrderItem', {
extend: 'Ext.data.Model',
fields: ['id', 'order_id', 'name', 'description', 'price', 'quantity'],
belongsTo: 'Order'
});
Calling user.orders() returns a Store configured with the Orders model, because the User model defined an association of hasMany: 'Orders'.
User.load(123, {
success: function(user) {
//we can iterate over the orders easily using the Associations API
user.orders().each(function(order) {
console.log(order.get('status'));
//we can even iterate over each Order's OrderItems:
order.orderItems().each(function(orderItem) {
console.log(orderItem.get('title'));
});
});
}
});

You can use override the default rendering method. Define a renderer method for the column.
renderer: function(value, metaData, record, rowIndex, colIndex, store) {
// you can use record.get method to access the data you require
return the_retrived_data;
}
You need to use mapping property to map the fields of your json store to the nested json. For example, if you need to access product name you can have:
{name: 'productname', mapping: 'products.prodnm'}
You can also use the array notation instead of the dot operator. ex: "products['prodnm']".

Related

How to print a JSON-structure from User models hierarchy

I am building an Rails 5 app and in this app I got a User model. Each user can have exactly one manager (using the attribute manager_id).
I want to print a JSON-structure (using Rabl) that shows how the User models are related. Meaning I want to print out how is manager to each user.
User 1 (manager_id is null)
|
User 2 (manager_id is 1)
User 3 (manager_id is 1)
|
User 4 (manager_id is 3)
This is what I want the UI to look like (this is already working I just need the JSON-structure to support it).
These is how the finished structure must look like.
datasource =
'name': 'Peter Fettingview'
'title': 'CEO'
'children': [
{
'name': 'Mike Palmer'
'title': 'CIO'
}
{
'name': 'Maria Persson'
'title': 'CTO'
'children': [
{
'name': 'James Hatton'
'title': 'Customer success'
}
{
'name': 'Lars Andersson'
'title': 'Customer success'
}
]
}
{
'name': 'Jan Roslund'
'title': 'Economy'
}
{
'name': 'Annika Holm'
'title': 'Sales'
}
]
This is what I got right now
attributes :id, :fullname
node :children do |n|
n.children.map { |c| partial("admin/users/index", :object => c) }
end
This is the output
[{
"id": 1,
"fullname": "Peter Fettingview",
"children": [{
"id": 2,
"fullname": "Richard Pooler"
},
{
"id": 1,
"fullname": "Mike Palmer"
}
]
},
{
"id": 2,
"fullname": "Richard Pooler",
"children": [{
"id": 3,
"fullname": "Mike Palmer"
}]
},
{
"id": 3,
"fullname": "Mike Palmer",
"children": []
}
]
How can I print out such a JSON-tree using the User models?
I have had to use tree data structures (i.e. self-referential models) before. I would consider using the Ancestry gem. It allows you to do things like enumerate descendants and paths bath to the root, making traversing your data structure significantly easier.

Get specific json data rails

I have this json data (actual data is a lot longer, that's why I need only 2)
[
{
"id": 1,
"user_id": 1,
"event_id": 1,
"creator_id": 1,
"event_name": "Poker",
"cruise_ship_name": "Royal Cruise",
},
{
"id": 2,
"user_id": 1,
"event_id": 2,
"creator_id": 1,
"event_name": "Ballroom",
"cruise_ship_name": "Celebrity Infinity",
},
{
"id": 3,
"user_id": 1,
"event_id": 3,
"creator_id": 1,
"event_name": "Tennis",
"cruise_ship_name": "Mediterranean",
}
]
I want to combine all data and get only specific fields (event_name and cruise_ship_name)
So in my final json format
it will be:
[
{
"event_name": "Mexican Fiesta",
"cruise_ship_name": "Celebrity Infinity",
}
]
I have been looking at this example:
#object.to_json {:include => [ :assocation_a, :assocation_b ]}
but not sure what :association_a and :association_b are.
Suppose you have an array of hashes:
events = [
{
"id": 1,
"user_id": 1,
"event_id": 1,
"creator_id": 1,
"event_name": "Poker",
"cruise_ship_name": "Royal Cruise",
},
...
]
You can iterate through each value in your hash, only keeping values of interest:
events.each do |event_hash|
event_hash.keep_if { |key, _| [:event_name, :cruise_ship_name].include?(key) }
end
puts events
The to_json method accept parameters which allow you include specific attributes:
#object.to_json(only: [:event_name, :cruise_ship_name])
The include: :assocation_a option to object, allowing the object association in the assocation_a model to be converted to JSON as well.

Cypher results return certain structure

I'm trying to return a certain structure.
Here is my query:
MATCH (tracker:tracker { active: true }) OPTIONAL MATCH (tracker { active: true })--(timer:timer) RETURN { tracker:tracker, timers:COLLECT(timer) } as trackers
Here is what I am returning so far:
{
"results": [{
"columns": ["trackers"],
"data": [{
"row": [{
"tracker": {
"title": "a",
"id": "04e3fddc-5aef-4c3a-9aeb-62a9fb15bd75",
"active": true
},
"timers": []
}]
}]
}],
"errors": []
}
I would like the timers to be nested under the "tracker" with the tracker's properties, like this:
{
"results": [{
"columns": ["trackers"],
"data": [{
"row": [{
"tracker": {
"title": "a",
"id": "04e3fddc-5aef-4c3a-9aeb-62a9fb15bd75",
"active": true,
"timers": []
}]
}]
}],
"errors": []
}
Try this:
MATCH (tr:tracker {active: true})
OPTIONAL MATCH (tr)--(ti:timer)
WITH {
title: tr.title,
id: tr.id,
active: tr.active,
timers: COLLECT(ti)
} as trackers
RETURN trackers

Parsing and then reading specific values of JSON / HTTParty::Response

I want to be able to retrieve the tier and division from this code, however when using the response object from HTTParty and doing res[0]["#{id}"]["tier"] it comes up with "cannot implicitly convert string to integer", which means it expects an integer, but I don't know where
This is the response I get (I'm doing it in a loop which is why I'm putting in the ID with "#{id}")
{"37714607": [
{
"queue": "RANKED_SOLO_5x5",
"name": "Diana's Patriots",
"entries": [{
"leaguePoints": 32,
"isFreshBlood": false,
"isHotStreak": false,
"division": "IV",
"isInactive": false,
"isVeteran": false,
"losses": 65,
"playerOrTeamName": "Wicked7000",
"playerOrTeamId": "37714607",
"wins": 59
}],
"tier": "GOLD"
},
{
"queue": "RANKED_TEAM_5x5",
"name": "Nasus's Justicars",
"entries": [{
"leaguePoints": 81,
"isFreshBlood": false,
"isHotStreak": false,
"division": "V",
"isInactive": false,
"isVeteran": false,
"losses": 73,
"playerOrTeamName": "Pink Fedoras",
"playerOrTeamId": "TEAM-5ffedf90-45ba-11e4-9e4b-c81f66db8bc5",
"wins": 73
}],
"tier": "SILVER"
},
{
"queue": "RANKED_TEAM_3x3",
"name": "Cassiopeia's Marksmen",
"entries": [{
"leaguePoints": 0,
"isFreshBlood": false,
"isHotStreak": true,
"division": "I",
"isInactive": false,
"isVeteran": false,
"losses": 3,
"playerOrTeamName": "The Booty Brothers",
"playerOrTeamId": "TEAM-53a65b60-ff2d-11e4-9e51-c81f66dba0e7",
"wins": 7
}],
"tier": "BRONZE"
}
]}
As your json something like below
{"37714607": [
{
"queue": "RANKED_SOLO_5x5",
"name": "Diana's Patriots",
"entries": [{
"leaguePoints": 32,
"isFreshBlood": false,
"isHotStreak": false,
"division": "IV",
"isInactive": false,
"isVeteran": false,
"losses": 65,
"playerOrTeamName": "Wicked7000",
"playerOrTeamId": "37714607",
"wins": 59
}],
"tier": "GOLD"
},
so it will first id = "37714607" then an array start([) the array contains hashes so first hash has "tier" key
so it should be
tiers = []
res["#{id}"].each do |result| #id = 37714607
tiers << result["tier"]
end
Seems like you need to do res[id.to_s][0]["tier"] instead – first take the root key, then first element (you did it vice versa).

Elasticsearch Facet List doesn't Match Results

Problem
When I filter by a particular facet, that specific field's facets are correctly filtered in the result but the other facet fields remain the same. Best way to explain this is with the query and the response.
Query
{
query: {
match_all: {}
},
filter: {
and: [{
term: {
"address.state": "oregon"
}
}]
},
facets: {
"address.city": {
terms: {
field: "address.city"
},
facet_filter: {}
},
"address.state": {
terms: {
field: "address.state"
},
facet_filter: {
and: [{
term: {
"address.state": "oregon"
}
}]
}
},
"address.country": {
terms: {
field: "address.country"
},
facet_filter: {}
}
}
}
Result
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "races",
"_type": "race",
"_id": "6",
"_score": 1,
"_source": {
"id": 6,
"name": "Eugene Marathon",
"description": "...",
"created_at": "2015-05-24T19:41:45.043Z",
"updated_at": "2015-05-24T19:41:45.046Z",
"address": {
"race_id": 6,
"id": 7,
"line1": null,
"line2": null,
"city": "Eugene",
"state": "oregon",
"country": "united_states",
"zip": null,
"user_id": null,
"created_at": "2015-05-24T19:41:45.044Z",
"updated_at": "2015-05-24T19:41:45.044Z"
},
"race_years": []
}
}
]
},
"facets": {
"address.city": {
"_type": "terms",
"missing": 0,
"total": 7,
"other": 0,
"terms": [
{
"term": "long beach",
"count": 1
},
{
"term": "lincoln",
"count": 1
},
{
"term": "las vegas",
"count": 1
},
{
"term": "jackson",
"count": 1
},
{
"term": "eugene",
"count": 1
},
{
"term": "duluth",
"count": 1
},
{
"term": "denver",
"count": 1
}
]
},
"address.state": {
"_type": "terms",
"missing": 0,
"total": 1,
"other": 0,
"terms": [
{
"term": "oregon",
"count": 1
}
]
},
"address.country": {
"_type": "terms",
"missing": 0,
"total": 7,
"other": 0,
"terms": [
{
"term": "united_states",
"count": 7
}
]
}
}
}
So as you can see it returns all the address.city facets even though the only result is located in Eugene. It is also returning a count of 7 on the united_states. Why would it be returning all of these extra facets and with incorrect counts? My ruby mapping is found below.
Ruby Mapping
settings index: {
number_of_shards: 1,
analysis: {
analyzer: {
facet_analyzer: {
type: 'custom',
tokenizer: 'keyword',
filter: ['lowercase', 'trim']
}
}
}
} do
mapping do
indexes :name, type: 'string', analyzer: 'english', boost: 10
indexes :description, type: 'string', analyzer: 'english'
indexes :address do
indexes :city, type: 'string', analyzer: 'facet_analyzer'
indexes :state, type: 'string'
indexes :country, type: 'string'
end
end
end
This is the normal behavior of facets when ran against a filter. From the official documentation:
There’s one important distinction to keep in mind. While search
queries restrict both the returned documents and facet counts, search
filters restrict only returned documents — but not facet counts.
In your case, your query matches all documents (i.e. match_all) so the facet counts are counted against all documents, too.
Change your query to this and your facet counts will change (in this case you don't need the facet_filter anymore):
{
query: {
term: {
"address.state": "oregon"
}
},
facets: {
"address.city": {
terms: {
field: "address.city"
}
},
"address.state": {
terms: {
field: "address.state"
}
},
"address.country": {
terms: {
field: "address.country"
}
}
}
}
Another thing worth noting is that facets are deprecated and have been replaced by the much more powerful aggregations.

Resources