Falcor - Is there a way to iterate a map - falcor

So far I have found that we can iterate on arrays using {from: x, to: y}. Is there a way to iterate on a map?
For example, I have the following map:
companyMap: {
61: {
name: 'Apple'
},
66: {
name: 'Microsoft'
},
70: {
name: 'Uber'
}
}
Is there a way to iterate on this map? Or at least get all the keys?

To iterate over a map, you need to first establish a practical (not theoretical) maximum for the number of keys you're going to have.
You can't make a call for an unbounded amount of data in Falcor, by design. If there is no practical maximum, it may be best to reconsider how you page through the data in the first place.
For example, if you set the practical maximum at 70 keys, you'll need to make the following request:
this.model.get(`companyMap[0..70]['name']`);
For those keys that do not exist in the dataset, there will be nothing returned.

You can ask for an arbitrary number of keys. For example the following path set:
["companyMap", [61, 66, 70], "name"]
returns the names from the 3 companies.

Related

Is it possible to use a custom equality operator with Ruby's Set?

I need to diff collections of child objects between 2 parents. Each is about 30,000 objects, and have about a dozen various attributes. Ruby's Set class provides a fast method to subtract one collection from the other, and get the difference. I had been doing this with JSON data, and the whole thing only took a couple seconds.
Now I'm using ActiveRecord to get the datasets. Of course, once the children are unmarshalled from the database, they include attributes :id, :created_at, and :updated_at. Unfortunately, this automatically ruins the comparisons in the diff, because these fields will always be different, and cause the comparison to fail.
Out of the set of attributes, I really only care about :label and :data. That is, I want to compare the objects with the same label between the 2 sets, and see if their data is different.
I can add a custom equivalency operator in my class:
def ==(other)
self.label == other.label && self.data == other.data
end
This works between comparisons of single objects. They are considered equal if (just) their labels and data match. However, this override does not seem to be getting used in this operation, for purposes of determining equivalency:
#diff = (#left.to_set - #right.to_set)
I was hoping that Set would use the object's class' overridden == operator, but this doesn't seem to be the case. My diffs are just all of the one side or the other, depending on the order of the difference. Is there any way to make this happen? (I already also tried overriding .eql?.)
Since this is too long for a comment, here's the SQL implementation of the idea.
WITH
t1 AS (SELECT * FROM tunings WHERE calibration_id = 7960),
t2 AS (SELECT * FROM tunings WHERE calibration_id = 7965)
SELECT t1.label, t1."data", t2."data" FROM t1 FULL OUTER JOIN t2 ON t1.label = t2.label
WHERE t1."data" != t2."data" OR t1."data" IS NULL OR t2."data" IS NULL
Another speed problem I hadn't even brought up yet was that I have to LOOK UP the "right" value, from the corresponding set, when I display the differences in the view, and THAT takes ANOTHER 10 seconds. This is all done in one step.
Because of the CTE's, I'm guessing that I won't be able to put this into ActiveRecord semantics, and I'll just have to pass the raw SQL with seeded values, but I would love to be proven wrong.
Also, I'm still academically interested in original question.
According to Ruby Set class: equality of sets, you need to override both Object#eql? and Object#hash
Here's how you can do it in general Ruby, without having to redefine your classes' identity.
first = [{ id: 1, label: "foo", data: "foo"},
{ id: 2, label: "bar", data: "bar"},
{ id: 3, label: "baz", data: "baz"}]
second = [{ id: 1, label: "foo", data: "foo"},
{ id: 2, label: "baz", data: "baz"},
{ id: 3, label: "quux", data: "quux"}]
first_groups = first.group_by { |e| e.values_at(:label, :data) }
second_groups = second.group_by { |e| e.values_at(:label, :data) }
first_minus_second_keys = first_groups.keys.to_set - second_groups.keys.to_set
first_minus_second = first_minus_second_keys.flat_map { |k| first_groups[k] }
(This is for lists of hashes; for AR classes you'd replace e.values(:label, :data) with [e.label, e.data])
That said, I agree with the Tin Man: it would be way more performant to do this at the database level.

Ordering items by sizename when it's not alphabetically logic?

In my app, the admin may add sizes to his products in this order.
Variant.create(size_name: "L")
Variant.create(size_name: "S")
Variant.create(size_name: "XXL")
Variant.create(size_name: "XL")
Sizes could also be (30,24, 33, 31, 29)
In my product view, the select tag display in the order it has been created.
I would like to sort from the smallest size to the biggest (S, M, L ...).
With the numerically sizes,I can order from the smallest to the biggest it's Okay
How I am supped to make sure that both sizes (the numerically and the alphabetically) could be sorted from the smallest to the biggest?
There are many ways to solve this, but at the core of any solution you need to define the order manually (or use a third party library which has already written this manual ordering for you?).
For example, you could somewhere define e.g.
SIZE_NAMES = %w[XS S M L XL XXL]
and then elsewhere in the code, use something like:
variants.sort_by { |variant| SIZE_NAMES.index(variant.size) }
For a more "advanced" solution, you could instead consider defining each size as a custom object rather than a regular String. Take a look at the Comparable module, and the <=> ("spaceship") operator.
By utilising this, you could potentially implement it in such a way that e.g. variants.sort will automatically compare variants by their "converted" size, and order them as you expect.
If you wish to do sorting on db side then you have two options:
Predefined sort like so:
Variant.order(
"CASE size_name
WHEN 'S' THEN 1
WHEN 'L' THEN 2
WHEN 'XL' THEN 3
WHEN 'XXL' THEN 4
ELSE 10
END, size, id"
)
You might want to move it to scope so in case you need to add another size_name there is only one place to change
With active record enums:
enum size_name: { s: 0, l: 1, xl: 2, xxl: 3 }
That way, you can still assign the field by the string/symbol, but the underlying data will actually be an integer, so you can just use order(:size_name, :size) to sort by size_name and size.
Also this way you can add index to speed up ordering

How can I return the highest "valued" element -- per "name" -- in an Array?

I've read a lot of posts about finding the highest-valued objects in arrays using max and max_by, but my situation is another level deeper, and I can't find any references on how to do it.
I have an experimental Rails app in which I am attempting to convert a legacy .NET/SQL application. The (simplified) model looks like Overlay -> Calibration <- Parameter. In a single data set, I will have, say, 20K Calibrations, but about 3,000-4,000 of these are versioned duplicates by Parameter name, and I need only the highest-versioned Parameter by each name. Further complicating matters is that the version lives on the Overlay. (I know this seems crazy, but this models our reality.)
In pure SQL, we add the following to a query to create a virtual table:
n = ROW_NUMBER() OVER (PARTITION BY Parameters.Designation ORDER BY Overlays.Version DESC)
And then select the entries where n = 1.
I can order the array like this:
ordered_calibrations = mainline_calibrations.sort do |e, f|
[f.parameter.Designation, f.overlay.Version] <=> [e.parameter.Designation, e.overlay.Version] || 1
end
I get this kind of result:
C_SCR_trc_NH3SensCln_SCRT1_Thd 160
C_SCR_trc_NH3SensCln_SCRT1_Thd 87
C_SCR_trc_NH3Sen_DewPtHiThd_Tbl 310
C_SCR_trc_NH3Sen_DewPtHiThd_Tbl 160
C_SCR_trc_NH3Sen_DewPtHiThd_Tbl 87
So I'm wondering if there is a way, using Ruby's Enumerable built-in methods, to loop over the sorted array, and only return the highest-versioned elements per name. HUGE bonus points if I could feed an integer to this method's block, and only return the highest-versioned elements UP TO that version number ("160" would return just the second and fourth entries, above).
The alternative to this is that I could somehow implement the ROW_NUMBER() OVER in ActiveRecord, but that seems much more difficult to try. And, of course, I could write code to deal with this, but I'm quite certain it would be orders of magnitude slower than figuring out the right Enumerable function, if it exists.
(Also, to be clear, it's trivial to do .find_by_sql() and create the same result set as in the legacy application -- it's even fast -- but I'm trying to drag all the related objects along for the ride, which you really can't do with that method.)
I'm not convinced that doing this in the database isn't a better option, but since I'm unfamiliar with SQL Server I'll give you a Ruby answer.
I'm assuming that when you say "Parameter name" you're talking about the Parameters.Designation column, since that's the one in your examples.
One straightforward way you can do this is with Enumerable#slice_when, which is available in Ruby 2.2+. slice_when is good when you want to slice an array "between" values that are different in some way. For example:
[ { id: 1, name: "foo" }, { id: 2, name: "foo" }, { id: 3, name: "bar" } ]
.slice_when {|a,b| a[:name] != b[:name] }
# => [ [ { id: 1, name: "foo" }, { id: 2, name: "foo" } ],
# [ { id: 3, name: "bar" } ]
# ]
You've already sorted your collection, so to slice it you just need to do this:
calibrations_by_designation = ordered_calibrations.slice_when do |a, b|
a.parameter.Designation != b.parameter.Designation
end
Now calibrations_by_designation is an array of arrays, each of which is sorted from greatest Overlay.Version to least. The final step, then, is to get the first element in each of those arrays:
highest_version_calibrations = calibrations_by_designation.map(&:first)

Ruby on Rails Active Record Query (.each, .collect, .map ...?)

This is one example of one entry in my database:
Market id: 1, name: "Independence Park (Independently Run Farmers Market...", address: "3945 N. Springfield Ave., Chicago, IL", zipcode: "60618", created_at: "2013-01-01 21:22:24", updated_at: "2013-01-01 21:22:24"
All I want to do is list the 43 zipcodes from all the entries in my database. Why don't these queries work?
Market.all.each { |m| m.zipcode }
Market.all.zipcode
m = Market.all
m.each{ |m| m.zipcode }
Thanks!
If all you want is an array of zip codes, I would suggest to try this:
Market.pluck(:zipcode)
The other answers have pointed out the correct way to do what you want, but haven't explained why your other attempts didn't work (which is technically the question you asked).
The reason attempts 1 and 3 don't work is that each doesn't return anything, it's only use is to loop through a set of records and perform an action on them (such as updating them or using some data to call an external service). Replacing each with map would fix them, as map uses the return value of the block to return an array of values. This has a disadvantage in that map is an Array method, so all of your records will have to be loaded into memory before the values can be found.
Attempt 2 doesn't work as you're trying to call a field name on an ActiveRecord::Relation (all), so you'll end up raising a NoMethodError.
The neatest solution, and one that has already been pointed out, is to use pluck, which not only returns all the values for the requested fields, but does so at the database query level, so you call should be more efficient.
You could also do the following, it returns an array of zipcodes:
Market.all.map(&:zipcode)
Use Benchmark to determine which is better.

groovy simple way to find hole in list?

I'm using the grails findAllBy() method to return a list of Position(s). Position has an integer field called location, which ranges from 1 to 15. I need to find the lowest location in the position list that is free.
For example, if there are positions at locations 1,2 and 4, then the algorithm should return 3. If locations 1 - 4 were filled, it would return 5.
Is there some simple groovy list/map functions to get the right number?
Thanks
If your list of positions were (limited to a mx of 5 for brevity):
def list = [ 1, 2, 4, 5 ]
And you know that you have a maximum of 5 of them, you can do:
(1..5).minus(list).min()
Which would give you 3
Just another option, because I originally thought he wanted to know the first unused slot in a list, say you had this:
def list = ['a', 'b', null, 'd', 'e', null, 'g']
You could easily find the first empty slot in the array by doing this:
def firstOpen = list.findIndexOf{ !it } // or it == null if you need to avoid groovy truth
Tim's way works, and is good for small ranges. If you've got the items sorted by location already, you can do it in O(n) by leveraging findResult
def firstMissing = 0
println list.findResult { (it.location != ++firstMissing) ? firstMissing : null }
prints 3.
If they're not sorted, you can either modify your db query to sort them, or add sort{it.location} in there.

Resources