Finding missing records from db - ruby-on-rails

I am trying to validate my configuration. So I have a piece of code like :
ConfigurationAttribute.where(key: [
'a', 'b', 'c'
])
If someone forgets to set key a, on the configuration or b, I want to be able to find the missing ones. Now I realize the record doesn't actually exists in the db, so there is nothing to find and instantiate the ConfigurationAttribute record from.
How would you solve a problem like this?
I can check if the count of attributes is equal to 3, that will make sure if all keys are set or not. But then again if I was troubleshooting this error, I would be frustrated because I don't know which one is missing and I would have to go and look one by one who is missing.

You could pluck the keys from that query, and compare it to the expected set:
required_keys = ['a', 'b', 'c']
actual_keys = ConfigurationAttribute.where(key: required_keys).pluck(:key)
if actual_keys != required_keys
# This could be a model validation, or whatever. But for example:
raise "Whoops! You configuration contains the keys: #{actual_keys}. Should contain: #{required_keys}"
end
The exact implementation details may vary slightly -- for example, maybe there can be multiple ConfigurationAttributes for the same key? Maybe there cannot be any ConfigurationAttributes for different keys? Maybe the required_keys varies depending on some condition (in which case, that could be a method call rather than a variable)? ...
... In which case, you may wish to modify that query, or the if statement, or add an additional validation, or whatever.

Related

Having different count per key in jsonb

I have values in a table called Translation, that contains for every values per example:
=> {"fr"=>"Jaune", "de"=>"", "en"=>"", "bg"=>"", "hr"=>"", "es"=>"", "hu"=>"", "it"=>"", "lt"=>"", "lv"=>"", "nl"=>"", "pl"=>"", "pt"=>"", "ro"=>"", "cs"=>""}
and I'm looking to get the the number of the translation for each language:
I'm trying :
Translation.where("values->>'fr' IS NOT NULL").count
but it giving me 0, which is not correct, do anyone knows how to do it correctly?
The problem that you have is that the keys that don't have values, still exist in the json, so "is not null" will return all of them because the key exist. you have two options here, you can remove the empty keys from the database, so not null will work, or, change it to see if the key is empty
You can do it like this
Translation.where("values->>'fr' <> ''").count
and it will work with the structure that you have right now.

neo4j cypher - is 'created_at' on relationships magic?

I have a query that looks something like this:
MATCH(u:USER) where u.id in {a_list}
MATCH(e:WHALE) # this is a singleton
CREATE (e)-[h:HARPOON]->(u)
SET h.a = 1, h.b = 2, h.created_at = {created_at}
So u can be multiple users. e is a singleton. Basically we're going to relate the whale to every user.
My problem is that it works fine... if I remove created_at from the query. If I leave it in, not all users are related to the whale. In fact, if I simply rename the parameter name from created_at to xcreated_at it works fine.
Is there something special about created_at?
created_at isn't special, as far as I know. It might depend on your driver, though. In the ruby neo4j gem, for instance, created_at is special, but not for any raw Cypher queries that you run.
Additionally, are you removing the parameter both from the query and from your parameter hash/map? That might cause some weirdness.
Lastly, this was probably dropped because you were making an example, but just created_at = {created_at} won't do anything. You need to specify the object which the property is being set on. I assume it's the relationship in this case so you'd want: h.created_at = {created_at}

how to use dynamic variable for symbols in ruby where statements

I dont how to accomplish this problem.
I faced with this problem 3 times and each time I put it in my todo list but even tho I tried to find a solution I couldnt.
For examples,
I m trying to create a query with dynamic variables of this example;
User.search(first_name_start: 'K')
there are 3 arguments in this example;
1)first_name - My model attribute
2)start - Query type (start/end/cont )
3)'3' - value
I was able to create dynamic ActiveRecord using static symbols but how am I suppose to make dynamic input
Thanks in advance
EDIT: ADDITIONAL INFORMATION
let me show you a some kind of pseudo-code
varArray.each_with_index |x,index|
queryString=varArray[i]+"_"+filterArray=[i] #lets say varArray[i], this will be first_name, an actual model attribute/a column in my db
#and filterArray like /start/end/with a filter type
#and finally valArray a string value like 'geo' or 'paul'
User.where(queryString valArray[i]).result
I tried to use send(variable) but that didnt help me either, so i dont how should i proceed,
This is one of a few cases where new fancy Ruby 1.9 syntax for defining hashes doesn't cut it. You have to use the traditional hashrocket (=>) that allows you to specify not only symbols, but any arbitrary values as hash keys:
column = "#{first_name}_size_#{query_type}".to_sym
User.where( column => value )
AFAIK, ActiveRecord is able to accept strings instead of symbols as column names, so you don't even need to call to_sym.

merge json and remove duplicates ruby rails

I have the following json
Suppose my selection in mobile then this fields will be generated
{"Style":"convertible","Year":"2010","Color":"green"}
{"Style":"convertible","Year":"2010","Color":"red"}
And if my selection is bike then this field will be generatd
{"model":"2012","mileage":"20kmph","Color":"red"}
How do i achieve the above result.
Edit-1
I have the form in which some of the fields with be auto generated based on category selection. I have converted the auto generated fields to json and stored in database as single column.
Image url
I don't know how to explain can you understand what I am looking for. Check out my screenshots for better understanding
I'm assuming (for some crazy reason) that you will be using Ruby to do this.
But first, your expected output is wrong because you can't have a hash with duplicate keys:
{"Color": "green", "Color": "red"}
...is impossible. Same goes for the "Year" keys. Think of keys within a hash as Highlanders. THERE CAN ONLY BE ONE (of the same name). Therefore, your actual expected output would be:
{"Style":"convertible", "Year":"2012", "Color":"red", "name":"test"}
Or whatever. Anyway...
Step 1: Convert JSON to a Ruby Hash
require 'json'
converted = JSON.parse '[{"Style":"convertible","Year":"2010","Color":"green"},
{"Style":"convertible","Year":"2010","Color":"red"},
{"name":"test","Year":"2012","Color":"red"}]'
Step 2: Merge them
merged = {}
converted.each { |c| merged.merge! c }
Now the merged variable should look like the above actual expected output.
The only problem left is deciding which duplicate keys override which other duplicate keys. What matters here is the order in which you merge the hashes. The ones merged last overrides any existing duplicate key/values. Hope that helps.

Why is Foo.first returning the last record?

I have 2 records in Foo, with id's 1 and 2. Both created in that order. Bare in mind, in Postgres, records have no inherent order.
In Rails console. Foo.first and Foo.last returns the last record. I was under the impression that Foo.first would return the first record.
Here's the catch. The SQL queries look like:
SELECT "foos".* FROM "foos" LIMIT 1
SELECT "foos".* FROM "foos" ORDER BY "foos"."id" DESC LIMIT 1
The second query (Foo.last) has an ORDER BY DESC. So why doesn't AR have an ORDER BY ASC for .first? Whats the logic behind this? Seems a bit "inconsistent".
I can easily solve this by doing: Foo.order('id ASC').first instead. But looking for an explanation.
There isn't any logic to it, if there was any sense to first (or last for that matter), then it would raise an exception if you neglected to specify an explicit order either as an argument to first or as part of the current scope chain. Neither first nor last make any sense whatsoever in the context of a relational database unless there is an explicit ordering specified.
My guess is that whoever wrote first assumed that order by whatever_the_pk_is was implicit if there was no explicit order by. Then they probably did some experiments to empirically verify their assumption and it just happened to work as they expected with the particular tables and databases that they checked with (mini-rant: this is why you never ever assume unspecified behavior; if a particular behavior isn't explicitly specified, don't assume it even if the current implementation behaves that way or if empirical evidence suggests that it behaves that way).
If you trace through a simple M.first, you'll find that it does this:
limit(1).to_a[0]
No explicit ordering so you get whatever random ordering the database feels like using, that could be order by pk or it could be the table's block order on disk. If you trace through M.last, you'll get to find_last:
def find_last
#...
reverse_order.limit(1).to_a[0]
#...
end
And reverse_order:
def reverse_order
relation = clone
relation.reverse_order_value = !relation.reverse_order_value
relation
end
The #reverse_order_value instance variable isn't initialized so it will start out as nil and a ! will turn it into a true. And if you poke around for how #reverse_order_value is used, you'll get to reverse_sql_order:
def reverse_sql_order(order_query)
order_query = ["#{quoted_table_name}.#{quoted_primary_key} ASC"] if order_query.empty?
#...
and there's the author's invalid assumption about ordering laid bare for all to see. That line should probably be:
raise 'Specify an order you foolish person!' if order_query.empty?
I'd recommend that you always use .order(...).limit(1).first instead of first or last so that everything is nice and explicit; of course, if you wanted last you'd reverse the .order condition. Or you could always say .first(:order => :whatever) and .last(:order => :whatever) to again make everything explicit.
For the Rails version 4+, if you don't define any order, it will be sorted by primary key.
# Find the first record (or first N records if a parameter is supplied).
# If no order is defined it will order by primary key.
#
# Person.first # returns the first object fetched by SELECT * FROM people
# Person.where(["user_name = ?", user_name]).first
# Person.where(["user_name = :u", { u: user_name }]).first
# Person.order("created_on DESC").offset(5).first
# Person.first(3) # returns the first three objects fetched by SELECT * FROM people LIMIT 3
def first(limit = nil)
if limit
if order_values.empty? && primary_key
order(arel_table[primary_key].asc).limit(limit).to_a
else
limit(limit).to_a
end
else
find_first
end
end
Source: https://github.com/rails/rails/blob/4-0-stable/activerecord/lib/active_record/relation/finder_methods.rb#L75-L82

Resources