4 ms·
I've been wanting something like this for Ruby for some time now. Since it's dynamically typed and ridiculously easy to monkey-patch, Ruby is a much harder chal
by egonschiele 14y ago
I've been wanting something like this for Ruby for some time now. Since it's dynamically typed and ridiculously easy to monkey-patch, Ruby is a much harder challenge than C++. The two best efforts I
have found are Diamondback Ruby (http://www.cs.umd.edu/projects/PL/druby/ http://www.cs.umd.edu/projects/PL/druby/) and Laser (http://carboni.ca/projects/p/laser http://carboni.ca/projects/p/laser)...but they mostly try to add static type-checking to Ruby code. After
looking at these I implemented a contracts library for Ruby (https://github.com/egonSchiele/contracts.ruby https://github.com/egonSchiele/contracts.ruby) to get myself some better dynamic checking. The next step is to use the annotations
for the contracts library to do better static code analysis. One thing I'm working on is generating tests automatically based on the contract annotations. But I've got a long way to go : ( If anyone
knows about other projects that are working on static analysis for Ruby I'd be very interested in hearing about them!
- pjungwir 14y agoLooked at your Contracts library for Ruby. I was just thinking yesterday about starting a project like this! Some thoughts: - I like that the contracts are right there in the code and not in a separate file. - The actual Contract methods only run once upon loading each class, so they don't cause a performance hit. I'd like a way to make them all noops (so they don't add any instrumentation) when running in "production". - My thought is that if you can define pre- and post-conditions as you're doing, then you can cut out a lot of the checks in your tests, so that as long as the tests exercise the code, you can rely on the post-conditions to do quite a bit of the validation. Plus you're validating outputs all over the place constantly, so you'd probably catch edge cases you never even expected. - I'm disappointed that your system seems to offer little more than type checking (unless I'm mistaken). I'd like something that gives me true pre- and post-conditions: basically passing a block of Ruby code for each one, with common idioms abbreviated so I don't need to write a whole block if the conditions are simple. Good luck on the project!
- egonschiele 14y agoGreat thoughts! > I'd like a way to make them all noops Sure! There's a default failure callback that gets called when a contract fails. You can just clear this callback in prod: if ENV == PRODUCTION class Contract def self.failure_callback(data) # blank end end end > I'm disappointed that your system seems to offer little more than type checking Nay! You can write your own contracts to do anything you want. So yes, lambdas are allowed in contracts: Contract lambda { |x| x.is_valid_email? } => Bool def save_email(email) # save an email end > with common idioms abbreviated I provide some common idioms already, but you can make your own abbreviations: ValidEmail = lambda { |x| x.is_valid_email? } Contract ValidEmail => Bool def save_email(email) Let me know if you have any other questions :)
- pjungwir 14y agoThanks for the clarifications!
- raesene2 14y agoA couple that I know of which are based on the security side of things are Brakeman (https://github.com/presidentbeef/brakeman https://github.com/presidentbeef/brakeman) and Scanny (https://github.com/openSUSE/scanny https://github.com/openSUSE/scanny) on the open source side. On the commercial side I know Checkmarx covers rails (http://www.checkmarx.com/ http://www.checkmarx.com/), amongst other languages
- egonschiele 14y agoWow, these are really cool. Thanks!