Permit arbitrary number of integers with strong_params - ruby-on-rails

I'm thinking perhaps an array is the way to go, but I'm not sure how to only allow arrays of integers. Here's what I'm starting with:
def put_params
params.require(:project).permit(technologies: [])[:technologies]
end
I want to be able to accept an arbitrary number of technology IDs securely.

As long as the technologies param is passed as an array, you just need to use
def put_params
params.require(:project).permit(:technologies)
end
The fundamental part, here, is how you pass the parameter. You need to make sure the parameter is passed as Array. You can read more in the official documentation.
The params hash is not limited to one-dimensional keys and values. It can contain arrays and (nested) hashes. To send an array of values, append an empty pair of square brackets "[]" to the key name:
GET /clients?ids[]=1&ids[]=2&ids[]=3
The actual URL in this example will be encoded as "/clients?ids%5b%5d=1&ids%5b%5d=2&ids%5b%5d=3" as "[" and "]" are not allowed in URLs. Most of the time you don't have to worry about this because the browser will take care of it for you, and Rails will decode it back when it receives it, but if you ever find yourself having to send those requests to the server manually you have to keep this in mind.
The value of params[:ids] will now be ["1", "2", "3"]. Note that parameter values are always strings; Rails makes no attempt to guess or cast the type.

Related

What are buckets in terms of hash functions?

Looking at the book Mining of Massive Datasets, section 1.3.2 has an overview of Hash Functions. Without a computer science background, this is quite new to me; Ruby was my first language, where a hash seems to be equivalent to Dictionary<object, object>. And I had never considered how this kind of datastructure is put together.
The book mentions hash functions, as a means of implementing these dictionary data structures. This paragraph:
First, a hash function h takes a hash-key value as an argument and produces
a bucket number as a result. The bucket number is an integer, normally in the
range 0 to B − 1, where B is the number of buckets. Hash-keys can be of any
type. There is an intuitive property of hash functions that they “randomize”
hash-keys
What exactly are buckets in terms of a hash function? it sounds like buckets are array-like structures, and that the hash function is some kind of algorithm / array-like-structure search that produces the same bucket number every time? What is inside this metaphorical bucket?
I've always read that javascript objects/ruby hashes/ etc don't guarantee order. In practice I've found that keys' order doesn't change (actually, I think using an older version of Mozilla's Rhino interpreter that the JS object order DID change, but I can't be sure...).
Does that mean that hashes (Ruby) / objects (JS) ARE NOT resolved by these hash functions?
Does the word hashing take on different meanings depending on the level at which you are working with computers? i.e. it would seem that a Ruby hash is not the same as a C++ hash...
When you hash a value, any useful hash function generally has a smaller range than the domain. This means that out of a large list of input values (for example all possible combinations of letters) it will output any of a smaller list of values (a number capped at a certain length). This means that more than one input value can map to the same output value.
When this is the case, the output values are refered to as buckets.
Consider the function f(x) = x mod 2
This generates the following outputs;
1 => 1
2 => 0
3 => 1
4 => 0
In this case there are two buckets (1 and 0), with a bunch of input values that fall into each.
A good hash function will fill all of these 'buckets' equally, and so enable faster searching etc. If you take the mod of any number, you get the bucket to look into, and thus have to search through less results than if you just searched initially, since each bucket has less results in it than the whole set of inputs. In the ideal situation, the hash is fast to calculate and there is only one result in each bucket, this enables lookups to take only as long as applying the hash function takes.
This is a simplified example of course but hopefully you get the idea?
The concept of a hash function is always the same. It's a function that calculates some number to represent an object. The properties of this number should be:
it's relatively cheap to compute
it's as different as possible for all objects.
Let's give a really artificial example to show what I mean with this and why/how hashes are usually used.
Take all natural numbers. Now let's assume it's expensive to check if 2 numbers are equal.
Let's also define a relatively cheap hash function as follows:
hash = number % 10
The idea is simple, just take the last digit of the number as the hash. In the explanation you got, this means we put all numbers ending in 1 into an imaginary 1-bucket, all numbers ending in 2 in the 2-bucket etc...
Those buckets don't really exists as data structure. They just make it easy to reason about the hash function.
Now that we have this cheap hash function we can use it to reduce the cost of other things. For example, we want to create a new datastructure to enable cheap searching of numbers. Let's call this datastructure a hashmap.
Here we actually put all the numbers with hash=1 together in a list/set/..., we put the numbers with hash=5 into their own list/set ... etc.
And if we then want to lookup some number, we first calculate it's hash value. Then we check the list/set corresponding to this hash, and then compare only "similar" numbers to find our exact number we want. This means we only had to do a cheap hash calculation and then have to check 1/10th of the numbers with the expensive equality check.
Note here that we use the hash function to define a new datastructure. The hash itself isn't a datastructure.
Consider a phone book.
Imagine that you wanted to look for Donald Duck in a phone book.
It would be very inefficient to have to look every page, and every entry on that page. So rather than doing that, we do the following thing:
We create an index
We create a way to obtain an index key from a name
For a phone book, the index goes from A-Z, and the function used to get the index key, is just getting first letter from the Surname.
In this case, the hashing function takes Donald Duck and gives you D.
Then you take D and go to the index where all the people with Surnames starting with D are.
That would be a very oversimplified way to put it.
Let me explain in simple terms. Buckets come into picture while handling collisions using chaining technique ( Open hashing or Closed addressing)
Here, each array entry shall correspond to a bucket and each array entry (if nonempty) will be having a pointer to the head of the linked list. (The bucket is implemented as a linked list).
The hash function shall be used by hash table to calculate an index into an array of buckets, from which the desired value can be found.
That is, while checking whether an element is in the hash table, the key is first hashed to find the correct bucket to look into. Then, the corresponding linked list is traversed to locate the desired element.
Similarly while any element addition or deletion, hashing is used to find the appropriate bucket. Then, the bucket is checked for presence/absence of required element, and accordingly it is added/removed from the bucket by traversing corresponding linked list.

How to convert hash values into appropriate data types for SQL queries

The problem I am having is the values in a hash may not be the right data type in order to be successful in a where clause (as one example).
For example, there are filter parameters that may be passed on the URL: some may be strings, some numbers, some boolean. The final hash would be something like filter_parms: {id: "1", active: "true", name: "John"} and so on. The problem should be obvious: everything is treated as a string. I am trying to find a way to automatically coerce the values into becoming the correct data types (e.g. "1" => 1, "true" => true) in a nice, elegant way without looping through and creating a coding mess.
The end goal is to be able to use the hash in something like this: Person.where(filter_parms). This works fine for the String fields, but not for boolean and int.
I have tried using sanitize_sql_for_conditions, but its output matches the input data types exactly without making any modifications.
I imagine there is something obvious that I am missing. Thanks for your help.
You can do things to normalize your data like this:
def normalize(value)
case (value)
when 'true'
true
when 'false'
false
when 'null','nil'
nil
when /\A-?\d+\z/
value.to_i
when /\A-?\d+\.\d+\z/
value.to_f
else
value
end
end
There's risks here in interpreting the values incorrectly, like if a field could contain the string literal "true" and you want that preserved this will mangle it, and likewise, phone numbers of the form 8889991111 will be coerced into numbers that might not fit in 32-bit forms, so that could be a problem for some systems.
The reason there's no automatic way is because converting it like this isn't hard, plus a lot of the conversion is highly contextual.

convert hash value into string in objective c

I have a hash value and I want to convert it into string formate but I do not know how to do that.
Here is the hash value
7616db6c232292d2e56a2de9da49ea810d5bb80d53c10e7b07d9521dc88b3177
Hashing technique is a one way algorithm. So that is not possible, sorry.
You can't. A hash is a one-way function. Plus, two strings could theoretically generate the same hash.
BUT. If you had a large enough, pre-computed list of as many hashes as you could generate for each unique string, you could potentially convert your hash back into a string. Although it would require thousands of GB in entries and a lot of time to compute each and every hash. So it practically isn't possible.

converting a string into a mathematical operation (ex: "+2.days")

I need to be able add days or hours to a previously created Item.
The system can add or subtract a set number of hours or days based on attributes stored in the db, :operator (add/subtract), :unit_of_time(hours/days), and :number.
I'd like to be able to do something like:
Date.today+2.days
where "+" is the :operator, "2" is the :number, and "days" is the :unit_of_time but I'm unsure of how to get the interpolated string of attributes to become the actual operator "+2.days". Any ideas?
(I've poured through the ruby documentation, but to no avail. Currently, I'm just manually creating of the possible options (4) in nested if/else blocks... yeah it's gross.)
You could use eval, e.g.:
eval("Date.today+2.days")
...and then simply use string interpolation to put in the variables. Note, however, that you should only do this if you can be very certain that the values in your database are always what you want them to be; under no circumstances should users be able to change them, otherwise you'll have a major security issue which compromises your entire system.
Using more lengthy methods like the if statement you suggested (or a case statement) require you to write more code, but they are much more secure.
All ruby objects have a send method which can be used to run a method by name with parameters. Using send as well as converting strings to ints (.to_i) should suffice.
Date.today.send '+', '1'.to_i.send('months') # This works
Date.today.send operator, number.to_i.send(unit) # Generalized form
Ruby is beautiful!

Create Tinyurl style hash

does anyone know of an algorithm that generates hashes that look like tinyurl hashes from a string (url)
I think the requirements would be
case sensitive
short
numbers and alphabets only
anything else?
I don't think tinyurl hashes the strings; they have a database ID (1, 2, 3) which is coverted to base 36 (0-9A-Z): http://en.wikipedia.org/wiki/Base_36
Hashes don't guarantee that collisions won't occur (assuming that you have more items to hash than there are possible values of the hash), rather, a good hash algorithm will make it so that collisions don't occur often.
This is important for URL generation because the total number of URLs that exist is greater than the values that can be stored in a fixed string hash.
Rather, I believe you see a counter that is incremented and uses a number system with a large base (like 62 for example, for digits 0-9, characters a-z and A-Z) to represent the value of the counter which is unique.

Resources