Persist hash to corresponding db-table - ruby-on-rails

I have a hash:
my_hash = {
blue: 2,
red: 3,
purple: 4,
}
I have a Model with corresponding db-table:
____________________
| id | color | count |
----------------------
| | | |
----------------------
I want to put my hash in the table like this:
____________________
| id | color | count |
----------------------
| 1 | blue | 2 |
| 2 | red | 3 |
| 3 | purple| 4 |
----------------------
So my question is, How can I write code that persists the hash to the corresponding db-table?

This can easily be done as below,
my_hash.each { |k,v| Model.create(color: k, count: v) }

Related

Cypher query aggregate sum of values

I have a Cypher query that shows the following output:
+----------------
| usid | count |
+----------------
| "000" | 1 |
| "000" | 0 |
| "000" | 0 |
| "001" | 1 |
| "001" | 1 |
| "001" | 0 |
| "002" | 2 |
| "002" | 2 |
| "002" | 0 |
| "003" | 4 |
| "003" | 2 |
| "003" | 2 |
| "004" | 4 |
| "004" | 4 |
| "004" | 4 |
+----------------
How can I get the below result with the condition SUM(count) <= 9.
+----------------
| usid | count |
+----------------
| "000" | 1 |
| "001" | 2 |
| "002" | 4 |
| "003" | 8 |
+----------------
Note: I have used the below query to get the 1st table data.
MATCH (us:USER)
WITH us
WHERE us.count <= 4
RETURN us.id as usid, us.count as count;
I don't know how you get your original data, so I will just use a WITH clause and assume the data is there:
// original data
WITH usid, count
// aggregate and filter
WITH usid, sum(count) as new_count
WHERE new_count <= 9
RETURN usid, new_count
Based on the updated question, the new query would look like:
MATCH (us:USER)
WHERE us.count <= 4
WITH us.id as usid, sum(us.count) as count
WHERE new_count <= 9
RETURN usid, count
˙˙˙

Conditionally CONCAT based on helper column data using ARRAYFORMULA in Google Sheets

I have 2 columns of names (Name 1, Name 2) which I would like to concat into a single column.
[CURRENT DATA SET] [FORMULA - CONCAT]
| A | B | | D |
| Name1 | Name2 | | Name1_Name2 |
| Name3 | Name4 | | Name3_Name4 |
| Name5 | Name6 | | Name5_Name6 |
This portion is working using my ARRAYFORMULA:
=ARRAYFORMULA(
IF(
ISBLANK(B4:B),
CONCAT(A4:A,B4:B),
CONCAT(A4:A,("_"&B4:B))
)
)
Here is the issue: Sometimes I need the CONCAT formula to put column B first, then Colum A (Example Name2_Name1).
Objective: The CONCAT formula needs to be conditional based on a helper column containing the list of valid name options.
Logic:
If helper column matches CONCAT, CONCAT ColumnA_ColumnB.
If helper column does not match CONCAT, ColumnB_ColumnA.
If still does not match, leave blank.
Expected Results using a helper column
[CURRENT DATA SET] [Helper Column] [EXPECTED RESULTS]
| A | B | | C | | D |
| Name1 | Name2 | | Name1_Name2 | | Name1_Name2 |
| Name3 | Name4 | | Name6_Name5 | | Name3_Name4 |
| Name5 | Name6 | | Name3_Name4 | | Name6_Name5 |
| Name7 | | | Name5 | | |
| Name5 | | | Name8 | | Name5 |
Is it possible to create an arrayformula to achieve these expected results?
Here is my Google Sheet: Click Here
See if this works for you:
=ArrayFormula(IFERROR(IFERROR(VLOOKUP(A4:A&IF(LEN(B4:B), "_"&B4:B,), D4:D, 1, 0), VLOOKUP(IF(LEN(B4:B), B4:B&"_",)&A4:A, D4:D, 1, 0))))

Query values from single column and fill columns, both based on multiple criteria

I am trying to query solely the IDs of clients that meet specific criteria from a source tab to an output tab and fill 2 columns with static values and 2 columns with dynamic values, based on criteria.
In the source tab I have:
+-----------------------+------+
| Status | ID |
+-----------------------+------+
| Retired/Deceased | 2a33 |
+-----------------------+------+
| Liquidation | 1sTR |
+-----------------------+------+
| Dissolved | 3B76 |
+-----------------------+------+
| Released from company | 463z |
+-----------------------+------+
| Active | 557g |
+-----------------------+------+
| In progress | zz34 |
+-----------------------+------+
| Demo | cc56 |
+-----------------------+------+
Please note, that there are 7 criteria values and I need the output for only 4 of them. Meaning that I need 4 values, based on which there will be binary fill of dynamic columns. The other 3 values are obsolete.
From these 4 values, if I have eg. Criteria 1, then I will have one fill of the 2 dynamic columns, if not (for the other 3 values) I will have other fill values.
So I guess simply going with a binary solution for the selection of the specific values is not applicable.
In the output tab logic:
+--------------------------------------------------------------------------------+
| Output tab |
+--------------------------------------------------------------------------------+
| ID | Status | Reason | Comment | Detail |
+----+--------+--------+----------------------------+----------------------------+
| A1 | Static | Static | If criteria = criteria 1, | If criteria = criteria 1, |
| | | | then null, | then value 1, |
| | | | else criteria value | else value 2 |
+----+--------+--------+----------------------------+----------------------------+
| B1 | Static | Static | If criteria = criteria 1, | If criteria = criteria 1, |
| | | | then null, | then value 1, |
| | | | else criteria value | else value 2 |
+----+--------+--------+----------------------------+----------------------------+
| C1 | Static | Static | If criteria = criteria 1, | If criteria = criteria 1, |
| | | | then null, else | then value 1, |
| | | | criteria value | else value 2 |
+----+--------+--------+----------------------------+----------------------------+
| D1 | Static | Static | If criteria = criteria 1, | If criteria = criteria 1, |
| | | | then null, | then value 1, |
| | | | else criteria value | else value 2 |
+----+--------+--------+----------------------------+----------------------------+
| E1 | Static | Static | If criteria = criteria 1, | If criteria = criteria 1, |
| | | | then null, | then value 1, |
| | | | else criteria value | else value 2 |
+----+--------+--------+----------------------------+----------------------------+
| F1 | Static | Static | If criteria = criteria 1, | If criteria = criteria 1, |
| | | | then null, | then value 1, |
| | | | else criteria value | else value 2 |
+----+--------+--------+----------------------------+----------------------------+
| G1 | Static | Static | If criteria = criteria 1, | If criteria = criteria 1, |
| | | | then null, | then value 1, |
| | | | else criteria value | else value 2 |
+----+--------+--------+----------------------------+----------------------------+
Dummy output tab:
+-----------------------+------+-------------------+-------------+------------------+---------------------------------+
| Status | ID | Status | Reason | Comment | Detail |
+-----------------------+------+-------------------+-------------+------------------+---------------------------------+
| Retired/Deceased | 2a33 | Unable to proceed | Unspecified | Retired/Deceased | Retired/No longer in business |
+-----------------------+------+-------------------+-------------+------------------+---------------------------------+
| Liquidation | 1sTR | Unable to proceed | Unspecified | Liquidation | Retired/No longer in business |
+-----------------------+------+-------------------+-------------+------------------+---------------------------------+
| Dissolved | 3B76 | Unable to proceed | Unspecified | Dissolved | Retired/No longer in business |
+-----------------------+------+-------------------+-------------+------------------+---------------------------------+
| Released from company | 463z | Unable to proceed | Unspecified | (null) | No longer works for the company |
+-----------------------+------+-------------------+-------------+------------------+---------------------------------+
The column 'Status' is not required. I added it just for reference and readability.
Apologies, but I have corporate security restrictions for sharing links to Google Sheets.
The part that I struggle most with is that in column 4 (the first one from the dynamic ones) needs to return the value of the criteria from column 2 from the source tab.
So far I have worked my way around the first part of the query, where I QUERY the IDs based on multiple criteria, labelled and filled the static values columns.
=QUERY(Data!$A$3:$BN,
"SELECT B, 'Unable to proceed', 'Unspecified'
WHERE A = 'Retired/Deceased'
OR A = ''Liquidation'
OR A = 'Dissolved'
OR A = 'Released from company'
AND A IS NOT NULL
LABEL 'Unable to proceed' 'Unspecified' , 'Status' 'Reason'", 1)
However, I am struggling with the dynamic columns, based on multiple criteria.
I looked up ARRAYFORMULA with IFERROR and VLOOKUP in a nested QUERY, but was not able to work my way around it.
Also, I am quite interested in how this would work if there were more than 2 options of values to fill columns 3 and 4 in the output tab.
As far as I know, the way to work around 2 values based on criteria is to nest an IFERROR function to make it binary. But what if there were more than 2 values to fill the arrays with?
based on status:
=QUERY({QUERY(Data!$A$1:$B,
"SELECT B, 'Unable to proceed', 'Unspecified'
WHERE A = 'Retired/Deceased'
OR A = 'Liquidation'
OR A = 'Dissolved'
OR A = 'Released from company'
AND A IS NOT NULL
LABEL 'Unable to proceed''Status', 'Unspecified''Reason'", 1),
QUERY(ARRAYFORMULA(IFERROR(VLOOKUP(
QUERY(Data!$A$2:$B,
"SELECT A
WHERE A = 'Retired/Deceased'
OR A = 'Liquidation'
OR A = 'Dissolved'
OR A = 'Released from company'
AND A IS NOT NULL", 0),
{"Retired/Deceased", "Retired/Deceased", "Retired/No longer in business";
"Liquidation", "Liquidation", "Retired/No longer in business";
"Dissolved", "Dissolved", "Retired/No longer in business";
"Released from company", "", "No longer works for the company"}, {2, 3}, 0), )),
"LABEL Col1 'Comment', Col2 'Detail'", 0)}, , 0)
based on ID:
=QUERY({QUERY(Data!$A$1:$B,
"SELECT B, 'Unable to proceed', 'Unspecified'
WHERE A = 'Retired/Deceased'
OR A = 'Liquidation'
OR A = 'Dissolved'
OR A = 'Released from company'
AND A IS NOT NULL
LABEL 'Unable to proceed''Status', 'Unspecified''Reason'", 1),
QUERY(ARRAYFORMULA(IFERROR(VLOOKUP(
QUERY(Data!$A$2:$B,
"SELECT B
WHERE A = 'Retired/Deceased'
OR A = 'Liquidation'
OR A = 'Dissolved'
OR A = 'Released from company'
AND A IS NOT NULL", 0),
{"2a33", "Retired/Deceased", "Retired/No longer in business";
"1sTR", "Liquidation", "Retired/No longer in business";
"3B76", "Dissolved", "Retired/No longer in business";
"463z", "", "No longer works for the company"}, {2, 3}, 0), )),
"LABEL Col1'Comment', Col2'Detail'", 0)}, , 0)

Finding root of a tree in a directed graph

I have a tree structure like node(1)->node(2)->node(3). I have name as an property used to retrieve a node.
Given a node say node(3), i wanna retrieve node(1).
Query tried :
MATCH (p:Node)-[:HAS*]->(c:Node) WHERE c.name = "node 3" RETURN p LIMIT 5
But, not able to get node 1.
Your query will not only return "node 1", but it should at least include one path containing it. It's possible to filter the paths to only get the one traversing all the way to the root, however:
MATCH (c:Node {name: "node 3"})<-[:HAS*0..]-(p:Node)
// The root does not have any incoming relationship
WHERE NOT (p)<-[:HAS]-()
RETURN p
Note the use of the 0 length, which matches all cases, including the one where the start node is the root.
Fun fact: even if you have an index on Node:name, it won't be used (unless you're using Neo4j 3.1, where it seems to be fixed since 3.1 Beta2 at least) and you have to explicitly specify it.
MATCH (c:Node {name: "node 3"})<-[:HAS*0..]-(p:Node)
USING INDEX c:Node(name)
WHERE NOT (p)<-[:HAS]-()
RETURN p
Using PROFILE on the first query (with a numerical id property instead of name):
+-----------------------+----------------+------+---------+-------------------------+----------------------+
| Operator | Estimated Rows | Rows | DB Hits | Variables | Other |
+-----------------------+----------------+------+---------+-------------------------+----------------------+
| +ProduceResults | 0 | 1 | 0 | p | p |
| | +----------------+------+---------+-------------------------+----------------------+
| +AntiSemiApply | 0 | 1 | 0 | anon[23], c -- p | |
| |\ +----------------+------+---------+-------------------------+----------------------+
| | +Expand(All) | 1 | 0 | 3 | anon[58], anon[67] -- p | (p)<-[:HAS]-() |
| | | +----------------+------+---------+-------------------------+----------------------+
| | +Argument | 1 | 3 | 0 | p | |
| | +----------------+------+---------+-------------------------+----------------------+
| +Filter | 1 | 3 | 3 | anon[23], c, p | p:Node |
| | +----------------+------+---------+-------------------------+----------------------+
| +VarLengthExpand(All) | 1 | 3 | 5 | anon[23], p -- c | (c)<-[:HAS*]-(p) |
| | +----------------+------+---------+-------------------------+----------------------+
| +Filter | 1 | 1 | 3 | c | c.id == { AUTOINT0} |
| | +----------------+------+---------+-------------------------+----------------------+
| +NodeByLabelScan | 3 | 3 | 4 | c | :Node |
+-----------------------+----------------+------+---------+-------------------------+----------------------+
Total database accesses: 18
and on the second one:
+-----------------------+----------------+------+---------+-------------------------+------------------+
| Operator | Estimated Rows | Rows | DB Hits | Variables | Other |
+-----------------------+----------------+------+---------+-------------------------+------------------+
| +ProduceResults | 0 | 1 | 0 | p | p |
| | +----------------+------+---------+-------------------------+------------------+
| +AntiSemiApply | 0 | 1 | 0 | anon[23], c -- p | |
| |\ +----------------+------+---------+-------------------------+------------------+
| | +Expand(All) | 1 | 0 | 3 | anon[81], anon[90] -- p | (p)<-[:HAS]-() |
| | | +----------------+------+---------+-------------------------+------------------+
| | +Argument | 1 | 3 | 0 | p | |
| | +----------------+------+---------+-------------------------+------------------+
| +Filter | 1 | 3 | 3 | anon[23], c, p | p:Node |
| | +----------------+------+---------+-------------------------+------------------+
| +VarLengthExpand(All) | 1 | 3 | 5 | anon[23], p -- c | (c)<-[:HAS*]-(p) |
| | +----------------+------+---------+-------------------------+------------------+
| +NodeUniqueIndexSeek | 1 | 1 | 2 | c | :Node(id) |
+-----------------------+----------------+------+---------+-------------------------+------------------+
Total database accesses: 13

Ruby parsing Array (Special Case)

I am executing a query and getting the following data from the database in an array (MySql2 type object):
+-----------+---------------+---------------+------+------+---------------+
| build | platform_type | category_name | pass | fail | indeterminate |
+-----------+---------------+---------------+------+------+---------------+
| 10.0.1.50 | 8k | UMTS | 10 | 2 | 5 |
| 10.0.1.50 | 8k | UMTS | 10 | 2 | 5 |
| 10.0.1.50 | 8k | IP | 10 | 2 | 5 |
| 10.0.1.50 | 8k | IP | 14 | 1 | 3 |
| 10.0.1.50 | 9k | IP | 14 | 1 | 3 |
| 10.0.1.50 | 9k | IP | 12 | 1 | 1 |
| 10.0.1.50 | 9k | UMTS | 12 | 1 | 1 |
| 10.0.1.50 | 9k | UMTS | 12 | 1 | 1 |
| 10.0.1.50 | 9k | UMTS | 12 | 1 | 1 |
| 10.0.1.50 | 9k | Stability | 9 | 4 | 0 |
| 10.0.1.50 | 9k | Stability | 15 | 1 | 0 |
I want to display it on my UI in a table, something like this :
+-----------+---------------+---------------+------+------+---------------+
| build | platform_type | category_name | pass | fail | indeterminate |
+-----------+---------------+---------------+------+------+---------------+
| | | UMTS | 20 | 4 | 10 |
| | 8k |---------------------------------------------|
| | | IP | 24 | 3 | 8 |
| |---------------|---------------------------------------------|
| 10.0.1.50 | | IP | 26 | 2 | 4 |
| | |---------------------------------------------|
| | 9k | UMTS | 36 | 3 | 3 |
| | |---------------------------------------------|
| | | Stability | 24 | 5 | 0 |
---------------------------------------------------------------------------
I did try using hash to find unique platform types for the build. But as I am very new to ruby, I am having trouble using the hash properly. I would appreciate if someone can help me parse the data.
Assuming you have an array of arrays:
#data = sql_results.group_by(&:first).map do |b, bl|   
[b, bl.group_by(&:second).map{|p, pl| [p, pl.map{|r| r[2..-1]}] }.sort_by(&:first)]
end.sort_by(&:first)
Here is how to break down the logic.
group the rows by first column. This will return a hash with key as the first column name and value as an array of rows.
group each build list by 2nd column(platform type). Each group should contain the array of col values from 3 to the last col.
sort the platform lists by platform type
sort the build lists by build name
The resultant structure would like this:
[
[
"10.0.1.50", [
[
"8k", [
["UMTS", 20, 4, 10],
["IP", 24, 3, 8]
]
],
[
"9k", [
["IP", 26, 2, 4],
["UMTS", 36, 3, 3],
["UMTS", 24, 5, 0]
]
]
]
]
]
You can use this in your view layout example:
%table
%tr
- %w(build platform_type category_name pass fail indeterminate).each do |name|
%th=name
- #data.each do |build, build_list|
%tr
%td=build
%td{:colspan=4}
%table
- build_list.each do |build, platform_list|
%tr
%td=build
%td{:colspan=3}
%table
- platform_list.each do |row|
%tr
- row.each do |attr|
%td=attr
If you use an AR model here is what you do:
class Build < ActiveRecord::Base
def self.builds_by_platform
reply = Hash.new{|h, k| h[k] = Hash.new{|h, k| h[k] = []}}
Build.order("build ASC, platform_type ASC").find_each do |row|
reply[row.build][row.platform_type] << row
end
reply.map{|b, bh| [b, bh.sort_by(&:first)}.sort_by(&:first)
end
end
In your controller you can access the normalized variable as:
#report _list = Build.builds_by_platform
You can use the #report _list variable for rendering the table.

Resources