67 karma · joined February 11, 2009
Having either in a gem is rare, but sensible if the gem wants to include a client to interact with the service it provides.
Point being, although hash functions might work most of the time, their general construction does not make them safe for this purpose. You can't say something is 'mostly secure' because it works 'most of the time'. The times is doesn't work will affect someone, and for them the system is not secure at all.
Plus, implementations with weird edge cases make for horrible debugging, especially when it comes to security.
Better to have resistance as baked into your crypto as you can, rather than relying on a firewall further up the stack. If the data itself is resilient, no implementation will be able to defeat it efficiently.
This is just one of the easier ways. It's effective and easy to code.
Making something you're intending to ship to strangers (or to yourself writing future projects with your tools) forces you to write good documentation (if you want anyone to use it), which in turn forces you to hone your API design skills. If you're having trouble writing the docs for something, you probably haven't adequately solved the problem yet.
I'm not claiming to have done a great job at this on all my projects, but it's a learning process and occasionally my projects find a user base, which keeps me busy, provides new challenges when they find bugs, and if your code's any good it boosts your reputation as a nice side effect.
http://github.com/jcoglan/heist http://fargo.jcoglan.com
If it weren't for Lisp it would never have been so easy for total noobs like me to get into language hacking.
They also require the user to explicitly start a fiber. This means when you're not in a fiber you can use a faster stackless engine because you don't need to track the state of the current continuation.
In the last year we've seen tremendous growth in our user base and with our commercial partnerships, including integrations with YouTube and Yahoo! Search. We just launched our first major label integration with EMI and are working on plenty more. There's a lot of work to do scaling our team and our technology stack, making it a really exciting time to join us.
If you, or someone you know, is an experienced and fast-learning developer into TDD and scalable web services we'd love to hear from you. We have a great team that's a joy to work with (you may have met a few of us at Ruby events), and we have a lot of challenging projects on our roadmap.
If you're interested, check out our jobs page at http://www.songkick.com/info/jobs and get in touch with our COO Pete Smith at pete@songkick.com
So basically it's a toy, but one that I hope others can learn something from.
When you copy an object, all you do is copy its set of instance variables, which are just references to other objects. For an array, the instance variables are its set of indexes, which again are just references. Copying an array just means making a new list of references, but the objects they point to remain unmodified and uncopied.
Consider:
<pre> array = ["foo"] copy = array.dup </pre>
array and copy are independently mutable - modifying the index in one does not affect the indexes in the other - but they still both contain references to the single string "foo". Thus:
<pre> copy.first.gsub! /foo/, "bar" </pre>
modifies the string referenced by copy, which is the same string referenced by array. So array becomes ["bar"].
If you want a true deep copy, do something like this:
<pre> def deep_copy(object) case object when Array object.map { |item| deep_copy(item) } when Hash object.inject({}) do |hash, (key,value)| hash[deep_copy(key)] = deep_copy(value) hash end # handle other data structures if need be else object.respond_to?(:dup) ? object.dup : object end end </pre>