<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0' version='2.0'><channel><atom:id>tag:blogger.com,1999:blog-7781964911499645745</atom:id><lastBuildDate>Tue, 01 May 2012 21:46:47 +0000</lastBuildDate><category>ruby</category><category>ruby-gcal</category><category>sl4a</category><category>csrf</category><category>postgres</category><category>admin</category><category>magic</category><category>browser testing</category><category>selenium</category><category>bug tracking</category><category>conference</category><category>open source</category><category>sql injection</category><category>module</category><category>fabric</category><category>git</category><category>python</category><category>browser</category><category>enterprise</category><category>rails</category><category>integration testing</category><category>owasp</category><category>forms</category><category>django python</category><category>xss</category><category>code</category><category>gcal</category><category>web application security</category><category>google calendar</category><category>database</category><category>linux</category><category>top 10</category><category>scripting</category><category>embedded</category><category>orlando</category><category>refactoring</category><category>camera</category><category>os</category><category>security</category><category>howto</category><category>programming</category><category>tutorial</category><category>deployment</category><category>basecamp</category><category>mojo</category><category>web2py</category><category>django</category><category>oracle</category><category>broadcast</category><category>magicruby</category><category>trac</category><category>ruby on rails</category><category>android</category><category>palm</category><category>unit testing</category><category>sinatra</category><category>ten</category><category>project management</category><category>redmine</category><category>jruby</category><category>ase</category><category>testing</category><category>ubuntu</category><category>issue tracking</category><category>model</category><category>redmine-lite</category><category>capistrano</category><title>leaps || bounds</title><description>Covering Ruby, Python, Linux, Android, web applications, and software engineering best practices.</description><link>http://leone.panopticdev.com/</link><managingEditor>noreply@blogger.com (Mike Leone)</managingEditor><generator>Blogger</generator><openSearch:totalResults>14</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7781964911499645745.post-7002433781490475097</guid><pubDate>Mon, 30 Apr 2012 00:19:00 +0000</pubDate><atom:updated>2012-04-29T17:21:04.360-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>unit testing</category><category domain='http://www.blogger.com/atom/ns#'>django</category><category domain='http://www.blogger.com/atom/ns#'>web2py</category><category domain='http://www.blogger.com/atom/ns#'>integration testing</category><category domain='http://www.blogger.com/atom/ns#'>python</category><category domain='http://www.blogger.com/atom/ns#'>testing</category><category domain='http://www.blogger.com/atom/ns#'>browser testing</category><category domain='http://www.blogger.com/atom/ns#'>selenium</category><category domain='http://www.blogger.com/atom/ns#'>browser</category><title>Integration Testing in Python</title><description>Hey folks! &amp;nbsp;Here's a presentation I did for the&amp;nbsp;&lt;a href="http://www.meetup.com/Royal-Python-Society-Providence/"&gt;Providence Royal Python Society&lt;/a&gt;&amp;nbsp;meetup this winter. &amp;nbsp;It covers some of the currently-available integration testing tools for Python, as well as my own project, &lt;a href="https://github.com/mleone/easy-integration"&gt;easy-integration&lt;/a&gt;.  &lt;br /&gt;&lt;div id="__ss_11822771" style="width: 425px;"&gt;&lt;strong style="display: block; margin: 12px 0 4px;"&gt;&lt;br /&gt;&lt;/strong&gt;&lt;strong style="display: block; margin: 12px 0 4px;"&gt;&lt;a href="http://www.slideshare.net/panopticdev/integration-testing-in-python" target="_blank" title="Integration Testing in Python"&gt;Integration Testing in Python&lt;/a&gt;&lt;/strong&gt; &lt;iframe frameborder="0" height="355" marginheight="0" marginwidth="0" scrolling="no" src="http://www.slideshare.net/slideshow/embed_code/11822771" width="425"&gt;&lt;/iframe&gt; &lt;br /&gt;&lt;div style="padding: 5px 0 12px;"&gt;View more &lt;a href="http://www.slideshare.net/" target="_blank"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/panopticdev" target="_blank"&gt;Panoptic Development, Inc.&lt;/a&gt; &lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7781964911499645745-7002433781490475097?l=leone.panopticdev.com' alt='' /&gt;&lt;/div&gt;</description><link>http://leone.panopticdev.com/2012/04/integration-testing-in-python.html</link><author>noreply@blogger.com (Mike Leone)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7781964911499645745.post-4871802393510020560</guid><pubDate>Thu, 20 Oct 2011 16:24:00 +0000</pubDate><atom:updated>2011-10-21T05:59:11.348-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>csrf</category><category domain='http://www.blogger.com/atom/ns#'>sql injection</category><category domain='http://www.blogger.com/atom/ns#'>django</category><category domain='http://www.blogger.com/atom/ns#'>top 10</category><category domain='http://www.blogger.com/atom/ns#'>xss</category><category domain='http://www.blogger.com/atom/ns#'>python</category><category domain='http://www.blogger.com/atom/ns#'>owasp</category><category domain='http://www.blogger.com/atom/ns#'>security</category><category domain='http://www.blogger.com/atom/ns#'>web application security</category><category domain='http://www.blogger.com/atom/ns#'>ten</category><title>Web App Security:  Django and the OWASP Top 10</title><description>&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-GBu1SKTHXzo/TqAzkPD52YI/AAAAAAAAAFA/BAvEUdqBFTg/s1600/seagal.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/-GBu1SKTHXzo/TqAzkPD52YI/AAAAAAAAAFA/BAvEUdqBFTg/s320/seagal.jpg" width="206" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Security threat: Neutralized.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;At my company, &lt;a href="http://panopticdev.com/"&gt;Panoptic Development&lt;/a&gt;, we've built several applications for the healthcare industry. &amp;nbsp;Since we often deal with sensitive patient medical data, web application security is a &lt;i&gt;huge&lt;/i&gt; concern. &amp;nbsp;Enter the &lt;b&gt;&lt;a href="https://www.owasp.org/index.php/Top_10_2010-Main"&gt;OWASP Top 10&lt;/a&gt;&lt;/b&gt;, a collection of best practices for web application security.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;b style="background-color: white;"&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;What's OWASP?&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: Arial, Helvetica, sans-serif;"&gt;From &lt;a href="http://en.wikipedia.org/wiki/OWASP"&gt;Wikipedia&lt;/a&gt;:&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="background-color: white; line-height: 20px;"&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;The&amp;nbsp;&lt;b&gt;Open Web Application Security Project&lt;/b&gt;&amp;nbsp;(OWASP) is an open-source application security project. The OWASP community includes corporations, educational organizations, and individuals from around the world. This community works to create freely-available articles, methodologies, documentation, tools, and technologies.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;b style="background-color: white;"&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;What's the Top 10?&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;From the &lt;a href="https://www.owasp.org/index.php/OWASP_Top_Ten_Project"&gt;OWASP Wiki&lt;/a&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;The OWASP Top Ten provides a powerful awareness document for web application security. The OWASP Top Ten represents a broad consensus about what the most critical web application security flaws are. Project members include a variety of security experts from around the world who have shared their expertise to produce this list. Versions of the 2007 were translated into English, French, Spanish, Japanese, Korean and Turkish and other languages. Translation efforts for the 2010 version are underway and they will be posted as they become available.&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="background-color: white;"&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"&gt;As you help us spread the word, please emphasize:&lt;/span&gt;&lt;br /&gt;&lt;ul style="line-height: 1.5em; list-style-type: square; margin-bottom: 0px; margin-left: 1.5em; margin-right: 0px; margin-top: 0.3em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;li style="margin-bottom: 0.1em;"&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"&gt;OWASP is reaching out to developers, not just the application security community&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul style="line-height: 1.5em; list-style-type: square; margin-bottom: 0px; margin-left: 1.5em; margin-right: 0px; margin-top: 0.3em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;li style="margin-bottom: 0.1em;"&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"&gt;The Top 10 is about managing risk, not just avoiding vulnerabilities&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul style="line-height: 1.5em; list-style-type: square; margin-bottom: 0px; margin-left: 1.5em; margin-right: 0px; margin-top: 0.3em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;li style="margin-bottom: 0.1em;"&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"&gt;To manage these risks, organizations need an application risk management program, not just awareness training, app testing, and remediation&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;b&gt;No Easy Answer&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;Make no mistake -&amp;nbsp;robust security is the result of consistent, ongoing code review, infrastructure expertise, and a broad knowledge of web programming, not a one-time checklist. &amp;nbsp;Still, when you're dealing with sensitive data, and especially when several organizations work on the same codebase, it's important to have mutually-accepted security standards.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: Arial, Helvetica, sans-serif;"&gt;&lt;b&gt;Django: &amp;nbsp;Frameworks to the Rescue&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: Arial, Helvetica, sans-serif;"&gt;Full-stack web development frameworks like Django are great for helping a team manage security concerns. &amp;nbsp;Let's investigate how Django's security features relate to the &lt;a href="https://www.owasp.org/index.php/Top_10_2010-Main"&gt;2010 OWASP Top 10&lt;/a&gt;. &amp;nbsp;If you need background information on the vulnerability types themselves, I included wikipedia links.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: Arial, Helvetica, sans-serif;"&gt;I should also stress that this isn't an exhaustive look into every possible security vulnerability; this just explores some of the most important ways that Django mitigates (or doesn't mitigate) major security concerns.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;ol&gt;&lt;li style="margin-left: 15px;"&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: Arial, Helvetica, sans-serif;"&gt;&lt;a href="http://en.wikipedia.org/wiki/Code_injection"&gt;&lt;b&gt;Code Injection&lt;/b&gt;&lt;/a&gt;: &amp;nbsp;For most Django applications, the primary code injection risk is &lt;a href="http://en.wikipedia.org/wiki/SQL_injection"&gt;SQL injection&lt;/a&gt;. &amp;nbsp;Django protects against SQL injection through its ORM abstraction layer, which automatically escapes input. &amp;nbsp;Note that it's possible to &lt;a href="https://docs.djangoproject.com/en/1.2/topics/db/sql/"&gt;perform raw sql queries with Django&lt;/a&gt;, any any such code should be manually audited for if it interacts with direct user input. &amp;nbsp;Though raw SQL is needed occasionally, especially for optimization, it's generally a &lt;a href="http://en.wikipedia.org/wiki/Code_smell"&gt;code smell&lt;/a&gt;&amp;nbsp;in a Django application.&lt;br /&gt;&lt;br /&gt;If your application interacts with any other backends, like LDAP, you'll want to investigate those third-party libraries separately. &amp;nbsp;Client-side javascript is also mitigated through its templating system; see #2 below.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="margin-left: 15px;"&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: Arial, Helvetica, sans-serif;"&gt;&lt;a href="http://en.wikipedia.org/wiki/Cross-site_scripting"&gt;&lt;b&gt;Cross-site scripting&lt;/b&gt;&lt;/a&gt;: &amp;nbsp;Generally, the most important way to mitigate XSS is to prevent unescaped user input from making it into your application's rendered HTML. Django’s templating system facilitates this by &lt;a href="https://docs.djangoproject.com/en/dev/topics/templates/#automatic-html-escaping"&gt;automatically excaping all variable values&lt;/a&gt;. &amp;nbsp;If you don't want to escape something on the front end, you have to explicitly tell Django &lt;i&gt;not&lt;/i&gt; to escape it. &amp;nbsp;In your code reviews, you can concentrate more on the few areas of your app where you &lt;i&gt;don't&lt;/i&gt;&amp;nbsp;escape user input.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="margin-left: 15px;"&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: Arial, Helvetica, sans-serif;"&gt;&lt;a href="http://en.wikipedia.org/wiki/Session_hijacking"&gt;&lt;b&gt;Session hijacking&lt;/b&gt;&lt;/a&gt;: &amp;nbsp;With the default Django SessionMiddleware, the framework doesn't allow any session data in the url. &amp;nbsp;Session IDs are also stored as hashes, mitigating brute force attacks. &lt;br /&gt;&lt;br /&gt;While you'll still want to ensure your code doesn't expose direct session data to the user in any way, Django makes it difficult to expose that information.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="margin-left: 15px;"&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: Arial, Helvetica, sans-serif;"&gt;&lt;a href="http://misc-security.com/blog/2009/07/insecure-direct-object-reference/"&gt;&lt;b&gt;Insecure direct object references&lt;/b&gt;&lt;/a&gt;: &amp;nbsp;Django has several mechanisms in place to mitigate IDORs. &amp;nbsp;It provides a special "slug" field if you don't want to pass object IDs around as parameters. &amp;nbsp;Django 1.2 also lets you explicitly name &lt;a href="https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.readonly_fields"&gt;read-only fields&lt;/a&gt;&amp;nbsp;in the admin, so you can prevent users from hacking together forms that alter protected &amp;nbsp;data. &lt;br /&gt;&lt;br /&gt;Note that you'll still want to manually audit your code to expose areas where users can access arbitrary object data, especially outside of the admin.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="margin-left: 15px;"&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: Arial, Helvetica, sans-serif;"&gt;&lt;a href="http://en.wikipedia.org/wiki/Cross-site_request_forgery"&gt;&lt;b&gt;Cross-site request forgery&lt;/b&gt;&lt;/a&gt;: &amp;nbsp;Django has &lt;a href="https://docs.djangoproject.com/en/dev/ref/contrib/csrf/"&gt;built-in CSRF protection&lt;/a&gt; middleware, so it would be extraordinarily difficult for an attacker to maliciously submit a form to your site using an authenticated user's credentials.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="margin-left: 15px;"&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: Arial, Helvetica, sans-serif;"&gt;&lt;a href="http://projects.webappsec.org/w/page/13246914/Application%20Misconfiguration"&gt;&lt;b&gt;Security misconfiguration&lt;/b&gt;&lt;/a&gt;: &amp;nbsp;This is one item that is largely outside the domain of the web framework itself; it's more about the application's deployment environment. &amp;nbsp;You need to keep up with Python security updates, Django security updates, and keep track of any third-party libraries you use for security updates. &amp;nbsp;You need to disable ports/services you don't use, and more. &amp;nbsp;With complex apps, this can be a huge job. &lt;br /&gt;&lt;br /&gt;Fortunately, there are great, frequently-updated blogs for both the &lt;a href="http://blog.python.org/"&gt;Python&lt;/a&gt; and &lt;a href="https://www.djangoproject.com/weblog/"&gt;Django&lt;/a&gt; core teams where you can keep track of security updates. &amp;nbsp;It's also easy to follow security announcement lists for your web server (e.g. &lt;a href="http://httpd.apache.org/lists.html#http-announce"&gt;apache&lt;/a&gt;, &lt;a href="http://mailman.nginx.org/mailman/listinfo"&gt;nginx&lt;/a&gt;) or operating system to keep track of security updates.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="margin-left: 15px;"&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: Arial, Helvetica, sans-serif;"&gt;&lt;a href="http://en.wikipedia.org/wiki/Symmetric_key_management"&gt;&lt;b&gt;Insecure cryptographic storage&lt;/b&gt;&lt;/a&gt;: &amp;nbsp;If the only secure information you're encrypting is user password data, you're all set if you use Django's &lt;a href="https://docs.djangoproject.com/en/dev/topics/auth/"&gt;built-in user authentication&lt;/a&gt;. &amp;nbsp;Django encrypts password data using SHA1 by default, but also supports MD5 and crypt out-of-the-box. &lt;br /&gt;&lt;br /&gt;If your application directly stores or manipulates any sensitive user data, you'll need to audit that code manually. &amp;nbsp;Fortunately, OWASP maintains a great&amp;nbsp;&lt;a href="https://www.owasp.org/index.php/Cryptographic_Storage_Cheat_Sheet"&gt;cryptographic storage cheat sheet&lt;/a&gt;&amp;nbsp;to help you along the way.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="margin-left: 15px;"&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: Arial, Helvetica, sans-serif;"&gt;&lt;a href="https://www.owasp.org/index.php/Top_10_2010-A8-Failure_to_Restrict_URL_Access"&gt;&lt;b&gt;Failure to restrict URL access&lt;/b&gt;&lt;/a&gt;: &amp;nbsp;Django has great built-in support for &lt;a href="https://docs.djangoproject.com/en/dev/topics/auth/#authentication-in-web-requests"&gt;restricting access&lt;/a&gt; to specific content. &amp;nbsp;Access is always controlled at the view level, before anything is rendered. &amp;nbsp;You're able to restrict access for &lt;a href="https://docs.djangoproject.com/en/dev/topics/auth/#the-login-required-decorator"&gt;specific actions&lt;/a&gt; or for &lt;a href="http://stackoverflow.com/questions/3214589/django-how-can-i-apply-the-login-required-decorator-to-my-entire-site-excludi"&gt;entire views&lt;/a&gt;. &amp;nbsp;Note that you'll still want to audit each url/action in your app to ensure that you're restricting access the way you intended. &amp;nbsp;It's easy to miss a @login_required decorator or forget to lock down an AJAX action.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="margin-left: 15px;"&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: Arial, Helvetica, sans-serif;"&gt;&lt;a href="http://en.wikipedia.org/wiki/Transport_Layer_Security"&gt;&lt;b&gt;Insufficient transport layer protection&lt;/b&gt;&lt;/a&gt;: &amp;nbsp;In many cases, strong transport layer protection means using SSL. &amp;nbsp;Though this falls outside the domain of Django itself, the framework does provide some help: &amp;nbsp;Django supports the &lt;a href="http://www.cse.msu.edu/~alexliu/publications/Cookie/cookie.pdf"&gt;secure cookie protocol&lt;/a&gt; (PDF link to research paper), and also allows developers to &lt;a href="https://docs.djangoproject.com/en/dev/topics/http/sessions/#session-cookie-secure"&gt;force the use of secure cookies&lt;/a&gt; over HTTPS.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="margin-left: 15px;"&gt;&lt;span class="Apple-style-span" style="background-color: white; font-family: Arial, Helvetica, sans-serif;"&gt;&lt;a href="http://projects.webappsec.org/w/page/13246981/URL%20Redirector%20Abuse"&gt;&lt;b&gt;Unvalidated redirects and forwards&lt;/b&gt;&lt;/a&gt;: &amp;nbsp;Because of Django's robust, built-in URL access restriction (see #7), it would be very hard for an attacker to take advantage of unvalidated redirects. &amp;nbsp;Again, since access is handled at the view level, you can't [easily] redirect users to a different url on your site without access control. &lt;br /&gt;&lt;br /&gt;Additionally, Django's built-in user authentication system doesn't allow off-site redirect links as url parameters. &amp;nbsp;Note that you'll still want to audit your code for any manual use of redirect links in URL parameters.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;Further reading:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;a href="https://www.owasp.org/index.php/Top_10_2010-Main"&gt;The full OWASP 2010 Top 10 list&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;a href="http://www.djangobook.com/en/2.0/"&gt;Django security documentaiton&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;a href="https://www.owasp.org/index.php?title=File:Django_%26_The_OWASP_Top_10.pptx"&gt;Slides: Django and OWASP 2007 Top 10&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7781964911499645745-4871802393510020560?l=leone.panopticdev.com' alt='' /&gt;&lt;/div&gt;</description><link>http://leone.panopticdev.com/2011/10/security-django-and-owasp-top-10.html</link><author>noreply@blogger.com (Mike Leone)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-GBu1SKTHXzo/TqAzkPD52YI/AAAAAAAAAFA/BAvEUdqBFTg/s72-c/seagal.jpg' height='72' width='72'/><thr:total>2</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7781964911499645745.post-185597874253513233</guid><pubDate>Mon, 04 Apr 2011 22:41:00 +0000</pubDate><atom:updated>2011-04-04T17:46:19.552-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>ruby</category><category domain='http://www.blogger.com/atom/ns#'>basecamp</category><category domain='http://www.blogger.com/atom/ns#'>redmine</category><category domain='http://www.blogger.com/atom/ns#'>ruby on rails</category><category domain='http://www.blogger.com/atom/ns#'>rails</category><category domain='http://www.blogger.com/atom/ns#'>trac</category><category domain='http://www.blogger.com/atom/ns#'>project management</category><category domain='http://www.blogger.com/atom/ns#'>redmine-lite</category><category domain='http://www.blogger.com/atom/ns#'>issue tracking</category><category domain='http://www.blogger.com/atom/ns#'>bug tracking</category><title>Redmine-lite Released</title><description>&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;I recently released redmine-lite,&amp;nbsp;an easy-to-install fork of Redmine 1.0.3-stable, a project management and issue-tracking tool.&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;Redmine-lite has smart conventions that help you set up your instance quickly and painlessly. &amp;nbsp;In fact, you can set it up and deploy it on your server in under five minutes. &amp;nbsp;Out of the box, it's set up to use the sqlite database, the thin web server, and Gmail for outgoing messages. &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;Redmine-lite is ideal for developers whose organizations require them to host issue-tracking software locally, but don't have much time to set up and administer a system. &amp;nbsp;Redmine-lite was the result of an enterprise client project. &amp;nbsp;At the time of writing, we're using this for a project with about 8 users, and it's currently tracking about 2-300 issues.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif; font-size: large;"&gt;Check out the &lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif; font-size: large;"&gt;&lt;b&gt;90 second&lt;/b&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif; font-size: large;"&gt; screencast!&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Dependencies: &amp;nbsp;&lt;a href="http://git-scm.com/"&gt;git&lt;/a&gt;,&amp;nbsp;&lt;a href="http://gembundler.com/"&gt;bundler&lt;/a&gt;,&amp;nbsp;&lt;a href="http://rvm.beginrescueend.com/"&gt;rvm&lt;/a&gt;.&lt;/span&gt; &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;embed allowfullscreen="true" allowscriptaccess="always" height="270" src="http://blip.tv/play/AYKw6gUA" type="application/x-shockwave-flash" width="320"&gt;&lt;/embed&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;Further reading:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;check out the &lt;a href="http://github.com/mleone/redmine-lite"&gt;github project&lt;/a&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;view&amp;nbsp;&lt;a href="http://www.slideshare.net/panopticdev/redminelite"&gt;slides from my presentation on redmine-lite&lt;/a&gt;&amp;nbsp;at RIRUG&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;a href="http://twitter.com/panopticdev"&gt;follow Panoptic Development on twitter&lt;/a&gt;.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7781964911499645745-185597874253513233?l=leone.panopticdev.com' alt='' /&gt;&lt;/div&gt;</description><link>http://leone.panopticdev.com/2011/04/redmine-lite-released.html</link><author>noreply@blogger.com (Mike Leone)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7781964911499645745.post-2056209110414011123</guid><pubDate>Wed, 16 Feb 2011 00:10:00 +0000</pubDate><atom:updated>2011-10-20T10:50:34.839-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>ruby</category><category domain='http://www.blogger.com/atom/ns#'>conference</category><category domain='http://www.blogger.com/atom/ns#'>jruby</category><category domain='http://www.blogger.com/atom/ns#'>rails</category><category domain='http://www.blogger.com/atom/ns#'>code</category><category domain='http://www.blogger.com/atom/ns#'>magic</category><category domain='http://www.blogger.com/atom/ns#'>magicruby</category><category domain='http://www.blogger.com/atom/ns#'>orlando</category><title>MagicRuby Roundup</title><description>Last week, I attended the MagicRuby conference in Orlando.&amp;nbsp; Aside from all the content in the talks, I learned three important things:&lt;br /&gt;&lt;ol&gt;&lt;li&gt; Rubyists are always trying something new and interesting.&lt;/li&gt;&lt;li&gt;Disney World is a great place to hold a conference.&lt;/li&gt;&lt;li&gt;Orlando has a fun and enthusiastic Ruby community! &lt;/li&gt;&lt;/ol&gt;I saw a lot of great talks at this conference.&amp;nbsp; I'm attempting to condense 30+ pages of notes into only the most important information.&amp;nbsp; I'll tell you (a) where to find slides/video, (b) who I think should check out each talk, and (c) what I think the most important points are.&lt;br /&gt;&lt;br /&gt;This doesn't include every talk, but it includes most of them.&lt;br /&gt;&lt;br /&gt;----------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Cultivating Cucumber&lt;/b&gt;&amp;nbsp; (&lt;a href="http://www.slideshare.net/leshill/cultivating-cucumber"&gt;Slides&lt;/a&gt;)&lt;br /&gt;&lt;i&gt;Les Hill, Hashrocket&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Who should check it out?&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Developers interested in improving TDD and BDD practices.&amp;nbsp;&amp;nbsp;&lt;/li&gt;&lt;li&gt;Developers unsure of whether to use Cucumber.&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Short take:&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Great summary of the features of cucumber:&amp;nbsp; Hooks, tags, steps, and more! &lt;/li&gt;&lt;li&gt;Good explanation of Cucmber's strengths (like the use of natural langage) and its weaknesses (like the need to maintain all those regexes)&lt;/li&gt;&lt;li&gt;Good discussion of best practices for organizing and refactoring cucumber suites.&lt;/li&gt;&lt;li&gt;I wish there was more discussion about the&amp;nbsp;&lt;i&gt;types of projects&lt;/i&gt;&amp;nbsp;where cucumber is most useful.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;----------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Geospacing Your Ruby&lt;/b&gt; (&lt;a href="http://blog.peteonrails.com/?p=253"&gt;Slides&lt;/a&gt;)&lt;br /&gt;&lt;i&gt;Peter Jackson, Intridea&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Who should check it out?&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Developers of spatially-enabled apps&lt;/li&gt;&lt;li&gt;Developers working in government, urban planning or environmental modeling.&lt;/li&gt;&lt;li&gt;Database Administrators (for those of you in the enterprise) &lt;/li&gt;&lt;li&gt;Geography/map buffs.&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Short take:&lt;/b&gt; &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Great overview of spatial terms, geometry, map types, etc.&lt;/li&gt;&lt;li&gt;Great overview of existing database and front-end tools for spatially-enabled apps.&lt;/li&gt;&lt;li&gt;Good suggestions for interesting spatial data to model and useful ways of displaying it.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;----------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Loving your Customers, Loving your Peers&lt;/b&gt; (No slides available)&lt;br /&gt;&lt;i&gt;Alan Johnson, Carsonified&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Who should check it out?&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Technical people who deal directly with customers&lt;/li&gt;&lt;li&gt;People who want to improve the reputation of the Ruby community&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Short take:&lt;/b&gt; &lt;br /&gt;&lt;ul&gt;&lt;li&gt;A "feel good" presentation, rife with humorous anecdotes and pop culture references.&lt;/li&gt;&lt;li&gt;A good reality check for developers who are quickly dismissive of non-ruby technologies, Microsoft, etc.&lt;/li&gt;&lt;li&gt;Lots of great suggestions on how to treat customers better, how to empathize with customers, and how to enjoy your job more.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;----------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Code is not Enough&lt;/b&gt; (No slides available)&lt;br /&gt;&lt;i&gt;Gregg Pollack / Caike Souza, EnvyLabs&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Who should check it out?&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Entrepreneurs&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Freelancers&lt;/li&gt;&lt;li&gt;Software development shop owners &lt;/li&gt;&lt;li&gt;Employees of small companies&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Short take:&lt;/b&gt; &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Good commentary on many important engineering management concepts:&amp;nbsp; Setting expectations, delegating tasks, etc.&lt;/li&gt;&lt;li&gt;A good discussion on software development as a craft vs an art.&lt;/li&gt;&lt;li&gt;Good suggestions for developers, like "don't be afraid to ask for help" and advice on how to "get in the zone" while programming.&lt;/li&gt;&lt;li&gt;Great advice on creating a culture of learning at your organization (especially the "book club" suggestion)&lt;/li&gt;&lt;li&gt;Good insight into effective networking and "making friends rather than sales" &lt;/li&gt;&lt;li&gt;Asserted that developing a product for another company is more difficult than developing and launching your own product (I don't necessarily agree)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;----------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Exceptional Ruby&lt;/b&gt; (&lt;a href="http://avdi.org/devblog/2011/02/05/thank-you-magic-ruby/"&gt;Slides and More&lt;/a&gt;)&lt;br /&gt;&lt;i&gt;Avdi Grimm&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Who should check it out?&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Just about any Ruby developer.&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Short take:&lt;/b&gt; &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Good review of exception syntax and handling in Ruby.&lt;/li&gt;&lt;li&gt;Great discussion on when to use exceptions in the first place ("exceptions are for exceptional situations") &lt;/li&gt;&lt;li&gt;Review of many design techniques for handling and managing exceptions&lt;/li&gt;&lt;li&gt;Reviewed some common software design pitfalls related to exceptions.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;----------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What happened to Desktop Development in Ruby&lt;/b&gt;? (&lt;a href="http://andymaleh.blogspot.com/2010/11/magicruby-whatever-happened-to-desktop.html"&gt;blog post&lt;/a&gt;)&lt;br /&gt;&lt;i&gt;Andy Maleh, Obtiva&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Who should check it out?&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Developers interested in desktop applications&lt;/li&gt;&lt;li&gt;Developers interested in the current state of desktop application programming in Ruby.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Short take:&lt;/b&gt; &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Great review of current desktop development frameworks:&amp;nbsp; shoes, wxWidgets, Limelight, Glimmer&lt;/li&gt;&lt;li&gt;Excelent insight into what's wrong and what's right with each framework.&lt;/li&gt;&lt;li&gt;Great perspective on what makes a well-designed desktop app framework.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;----------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Keynote&lt;/b&gt; (No Slides Available)&lt;br /&gt;&lt;i&gt;Dave Thomas, Pickaxe Author&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Who should check it out?&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Dave Thomas fans&lt;/li&gt;&lt;li&gt;Project managers and developers looking to improve software development methodologies.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Short take:&lt;/b&gt; &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Great review of what it really means to practice "agile" development.&lt;/li&gt;&lt;li&gt;Insightful&amp;nbsp; recursive algorithm for software development:&amp;nbsp; &lt;i&gt;Where do we want to be?&amp;nbsp; Where are we now?&amp;nbsp; How do we improve our position? Repeat.&lt;/i&gt;&amp;nbsp;&lt;/li&gt;&lt;li&gt;Good use of a one-wheel balancing robot as a metaphor for prioritizing and executing incremental software changes.&lt;/li&gt;&lt;li&gt;Advocated the "ten second audit" for developers:&amp;nbsp; &lt;i&gt;Why am I doing this?&amp;nbsp; Does it have to be done this way?&amp;nbsp; Does it have to be done at all?&lt;/i&gt;&lt;/li&gt;&lt;li&gt;Insightful, humorous commentary on overzealous cucumber evangelists and constantly-changing tools in the Ruby community.&lt;i&gt;&amp;nbsp;&lt;/i&gt; &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;----------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Crank up your Apps with Torquebox&lt;/b&gt; (&lt;a href="http://www.slideshare.net/jcrossley3/crank-up-your-apps-with-torquebox"&gt;Slides&lt;/a&gt; and &lt;a href="http://torquebox.org/news/2011/02/08/magic-ruby-preso/"&gt;Video&lt;/a&gt;)&lt;br /&gt;&lt;i&gt;Jim Crossley, Red Hat&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Who should check it out?&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Enterprise developers who want to work with Ruby but must develop in a Java ecosystem&lt;/li&gt;&lt;li&gt;Developers challenged with building scalable, distributed web applications.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Short take:&lt;/b&gt; &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Good overview of everything Torquebox:&amp;nbsp; Configuration, JBoss, messaging, queues, processors, services, scaling techniques, and more.&lt;/li&gt;&lt;li&gt;Good discussion of use-cases for Torquebox, its performance, and potential future changes.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;----------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;How I Lerned to Stop Worrying and Love the Cloud&lt;/b&gt; (&lt;a href="http://www.slideshare.net/geemus/fog-or-how-i-learned-to-stop-worrying-and-love-the-cloud"&gt;Slides&lt;/a&gt;)&lt;br /&gt;&lt;i&gt;Wesley Beary, Engine Yard&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Who should check it out?&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Developers currently using or interested in cloud-based infrastructure.&lt;/li&gt;&lt;li&gt;Anyone overwhelmed by the choice of cloud providers.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Short take:&lt;/b&gt; &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Great overview of Fog, a vendor-agnostic cloud interface that works with many popular providers, such as EC2 and Rackspace.&lt;/li&gt;&lt;li&gt;Discusses many good use-cases for Fog.&lt;/li&gt;&lt;li&gt;Helpful, tutorial-style explanation of how to use Fog to interface with a cloud provider.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;----------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Documentation is Freaking Awesome&lt;/b&gt; (&lt;a href="http://warpspire.com/talks/documentation/"&gt;Slides and More&lt;/a&gt;)&lt;br /&gt;&lt;i&gt;Kyle Neath, Github&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Who should check it out?&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Open-source authors.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Any developer who might, at some point in the future, hand off their project to someone else.&amp;nbsp; :)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Short take:&lt;/b&gt; &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Very straightforward, "common-sense" talk about why documentation will help your project.&lt;/li&gt;&lt;li&gt;Discussed many useful ways to improve documentation, covering everything from the README to RDoc to Yard to "Having an awesome web page."&lt;/li&gt;&lt;/ul&gt;----------&lt;br /&gt;&lt;br /&gt;Please let me know if there are any errors, of if you can point me to any slides that are currently missing!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7781964911499645745-2056209110414011123?l=leone.panopticdev.com' alt='' /&gt;&lt;/div&gt;</description><link>http://leone.panopticdev.com/2011/02/magic-ruby-roundup.html</link><author>noreply@blogger.com (Mike Leone)</author><thr:total>3</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7781964911499645745.post-6501478550331157769</guid><pubDate>Thu, 04 Nov 2010 15:54:00 +0000</pubDate><atom:updated>2011-10-20T10:51:03.706-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>ruby</category><category domain='http://www.blogger.com/atom/ns#'>open source</category><category domain='http://www.blogger.com/atom/ns#'>linux</category><category domain='http://www.blogger.com/atom/ns#'>rails</category><category domain='http://www.blogger.com/atom/ns#'>enterprise</category><category domain='http://www.blogger.com/atom/ns#'>database</category><category domain='http://www.blogger.com/atom/ns#'>oracle</category><title>Oracle on Rails:  Can Proprietary and Open-Source Play Nice Together?</title><description>We're starting a new enterprise Rails project at Panoptic Development (that's right, enterprise Rails), and we're using the Oracle database.  Yes, we all know that Rails plays best with other open-source databases like PostgreSQL, but sometimes development teams don't have the luxury of choosing the database.&lt;br /&gt;&lt;br /&gt;The upshot of all this?  We'll hopefully be contributing some articles and open-source code to help other developers work with the proprietary, enterprise behemoth that is the Oracle database.&lt;br /&gt;&lt;br /&gt;I've started with a &lt;a href="https://github.com/mleone/rails3_oracle_sample"&gt;quick fork&lt;/a&gt; of Raimonds Simanovskis' useful rails_3_oracle_sample application, adding some documentation that helped me get things started.&lt;br /&gt;&lt;br /&gt;Raimonds seems to be working harder than everyone else to integrate Oracle with Ruby on Rails, so check out his &lt;a href="http://blog.rayapps.com/"&gt;excellent blog&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Most Rails developers work in small, agile teams without a dedicated DBA, and that's often quite different from the workflow in large organizations using Oracle.  Here's one of Raimonds' presentations (from three years ago!) that helped get me into the Oracle mindset:&lt;br /&gt;&lt;br /&gt;&lt;div id="__ss_619018" style="width: 425px;"&gt;&lt;strong style="display: block; margin: 12px 0 4px;"&gt;&lt;a href="http://www.slideshare.net/rsim/using-ruby-on-rails-with-legacy-oracle-databases-presentation" title="Using Ruby on Rails with legacy Oracle databases"&gt;Using Ruby on Rails with legacy Oracle databases&lt;/a&gt;&lt;/strong&gt;&lt;object height="355" id="__sse619018" width="425"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=using-rails-with-legacy-oracle-db-1222386749548113-9&amp;stripped_title=using-ruby-on-rails-with-legacy-oracle-databases-presentation&amp;userName=rsim" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse619018" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=using-rails-with-legacy-oracle-db-1222386749548113-9&amp;stripped_title=using-ruby-on-rails-with-legacy-oracle-databases-presentation&amp;userName=rsim" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;div style="padding: 5px 0 12px;"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/rsim"&gt;rsim&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;Stay tuned for more updates.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7781964911499645745-6501478550331157769?l=leone.panopticdev.com' alt='' /&gt;&lt;/div&gt;</description><link>http://leone.panopticdev.com/2010/11/oracle-on-rails-can-proprietary-and.html</link><author>noreply@blogger.com (Mike Leone)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7781964911499645745.post-6577484160737856059</guid><pubDate>Wed, 01 Sep 2010 03:45:00 +0000</pubDate><atom:updated>2011-10-20T10:51:36.461-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>ruby</category><category domain='http://www.blogger.com/atom/ns#'>jruby</category><category domain='http://www.blogger.com/atom/ns#'>camera</category><category domain='http://www.blogger.com/atom/ns#'>howto</category><category domain='http://www.blogger.com/atom/ns#'>embedded</category><category domain='http://www.blogger.com/atom/ns#'>tutorial</category><category domain='http://www.blogger.com/atom/ns#'>ase</category><category domain='http://www.blogger.com/atom/ns#'>sinatra</category><category domain='http://www.blogger.com/atom/ns#'>android</category><category domain='http://www.blogger.com/atom/ns#'>sl4a</category><category domain='http://www.blogger.com/atom/ns#'>broadcast</category><title>Turn your Android Phone Into a Remote Spy Camera with Ruby in 15 Minutes</title><description>It's been a great year for Ruby on Android, but no one knows it.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_-vwq5MP3moA/TH2uLcbXA5I/AAAAAAAAAC0/cIiO4l5BXrQ/s1600/sinatra_snapshot.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="138" src="http://4.bp.blogspot.com/_-vwq5MP3moA/TH2uLcbXA5I/AAAAAAAAAC0/cIiO4l5BXrQ/s400/sinatra_snapshot.png" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Sinatra running on a Motorola Droid&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;div&gt;You can start writing Ruby apps for Android devices TODAY. &amp;nbsp;You don't need to install any SDK, you don't need to install some giant Eclipse IDE, and you certainly don't need to write any Java.&lt;br /&gt;&lt;br /&gt;Some of you may have heard of &lt;a href="http://ruboto.org/"&gt;Ruboto&lt;/a&gt;, but Damon Kohler and the team at &lt;a href="http://code.google.com/p/android-scripting/"&gt;android-scripting&lt;/a&gt;&amp;nbsp;have been quietly improving &lt;i&gt;SL4A&lt;/i&gt;&amp;nbsp;over the past year, adding tons of features and improving stability.&lt;br /&gt;&lt;blockquote&gt;&lt;div style="max-width: 65em;"&gt;&lt;span class="Apple-style-span" style="font-family: arial, sans-serif;"&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Scripting Layer for Android (SL4A, formerly known as Android Scripting Environment or ASE) brings scripting languages to Android by allowing you to edit and execute scripts and interactive interpreters directly on the Android device. These scripts have access to many of the APIs available to full-fledged Android applications, but with a greatly simplified interface that makes it easy to get things done... &amp;nbsp;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: arial, sans-serif;"&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Python, Perl, &lt;/span&gt;&lt;/i&gt;&lt;b&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;JRuby&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;, Lua, BeanShell, JavaScript, Tcl, and shell are currently supported, and we're planning to add more.&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;There's even&amp;nbsp;&lt;a href="http://code.google.com/p/android-scripting/wiki/SharingScripts"&gt;support for distributing &amp;nbsp;programs as APKs&lt;/a&gt;, so the implementation language and dependencies are totally transparent to users.&lt;br /&gt;&lt;br /&gt;We'd love to run some simple Ruby scripts on Android, but what about running a complete, albeit simple, application? &amp;nbsp;Will it work?&lt;br /&gt;&lt;br /&gt;Most Rubyists use Ruby to build web applications, so let's run with that. &amp;nbsp;Let's build a spy camera app, so I can figure out who's been stealing ink cartridges from our office. &amp;nbsp;The app should (a)&amp;nbsp;show me a snapshot of what the camera currently sees and (b)&amp;nbsp;update that snapshot on demand.&lt;br /&gt;&lt;br /&gt;We need a simple, lightweight ruby framework to use. Sinatra is very easy to use and should even be able to run on older Android devices.&lt;br /&gt;&lt;br /&gt;Similarly, we need a simple, lightweight, &lt;i&gt;pure ruby&amp;nbsp;&lt;/i&gt;web server. &amp;nbsp;WEBrick is pure ruby, part of the standard library, and &lt;i&gt;fast enough&lt;/i&gt;&amp;nbsp;to run on Android. &amp;nbsp;Works for me!&lt;br /&gt;&lt;br /&gt;First, let's work from our development machine (i.e. laptop). &amp;nbsp;No need to touch the phone just yet.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Start a New Sinatra Project&lt;/h2&gt;&lt;script src="http://pastie.org/1130655.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;But wait! &amp;nbsp;What about Sinatra itself? &amp;nbsp;We can't easily install rubygems on our Android phone, so we'll have to vendorize Sinatra and all dependencies and ship them with our application. &amp;nbsp;Since we'll be running JRuby on Android, we can't use any libraries that have native C extensions or are otherwise JRuby-incompatible.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Make Directories for Gems and Snapshots&lt;/h2&gt;&lt;script src="http://pastie.org/1130656.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Vendorize your Gems&lt;/h2&gt;&lt;script src="http://pastie.org/1130658.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;h2&gt;Create the App&lt;/h2&gt;Create a file called &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;spycamera.rb&lt;/span&gt; in the project directory.&lt;br /&gt;&lt;br /&gt;First, let's set some constants for the important directories in our application.  When running apps under SL4A, we need to be very explicit about directory paths.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://pastie.org/1130620.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Let's update our load path, so JRuby can find our vendorized gems.&lt;br /&gt;&lt;script src="http://pastie.org/1130638.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Next, we'll load Sinatra. &amp;nbsp;We'll have to explicitly load rack first,&amp;nbsp;to avoid uninitialized constant errors under SL4A.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://pastie.org/1130629.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Finally, we require the Android API interface, available under SL4A, and initialize an Android object. &amp;nbsp;This will allow us to make API calls, like one that tells the camera to take and store a picture.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://pastie.org/1130633.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now, let's create a very simple HTML template. &amp;nbsp;The template should just display the latest snapshot, which we'll be saving to public/latest.png. &amp;nbsp;If I click on that snapshot, it should take a new snapshot and refresh the page.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://pastie.org/1130651.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Finally, create a tiny Sinatra app that takes a picture, saves it, and renders the template.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://pastie.org/1130648.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Install (Deploy) The App&lt;/h2&gt;Now you can finally use your phone! &amp;nbsp;Grab that Android device and install SL4A (r1 APK available &lt;a href="http://code.google.com/p/android-scripting/downloads/detail?name=sl4a_r1.apk"&gt;here&lt;/a&gt;). &amp;nbsp;Run SL4A, go to the interpreters menu, and install JRuby.&lt;br /&gt;&lt;br /&gt;Once JRuby is installed, it's time to deploy your application to the phone.&lt;br /&gt;&lt;br /&gt;Connect your phone to your development machine via USB, and simply copy the contents of your app to SL4A's script directory on your phone. &amp;nbsp;There may be some sample ruby scripts left over from the SL4A install; you can delete them if you like.&lt;br /&gt;&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_-vwq5MP3moA/TH1Qbnx-9sI/AAAAAAAAACk/vXe8dLYlvJU/s1600/filecopy_screenshot.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="260" src="http://4.bp.blogspot.com/_-vwq5MP3moA/TH1Qbnx-9sI/AAAAAAAAACk/vXe8dLYlvJU/s400/filecopy_screenshot.png" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Copying the project contents onto the deivice.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;At this point, just run spycam.rb from SL4A and you're good to go!&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_-vwq5MP3moA/TH2whVT4fGI/AAAAAAAAAC8/-9HNyPIxZ6Q/s1600/sl4a_snapshot.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_-vwq5MP3moA/TH2whVT4fGI/AAAAAAAAAC8/-9HNyPIxZ6Q/s320/sl4a_snapshot.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Starting the Sinatra app from SL4A&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Place your newly-activated spy camera somewhere, hide in your office/cube, start your web browser, and navigate to http://ip.address.of.phone:4567. &amp;nbsp;You can do this from inside your local network via wifi, or, carrier permitting, over 3G.&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_-vwq5MP3moA/TH2zaxBFKUI/AAAAAAAAADE/iC1qEgcAN4A/s1600/Screenshot.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="250" src="http://4.bp.blogspot.com/_-vwq5MP3moA/TH2zaxBFKUI/AAAAAAAAADE/iC1qEgcAN4A/s400/Screenshot.png" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Happy spying!&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;b&gt;Further Reading&lt;/b&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;Check out&amp;nbsp;&lt;a href="http://github.com/mleone/broadcast"&gt;my open-source project, Broadcast&lt;/a&gt;,&amp;nbsp;on Github. &amp;nbsp;It's a more refined, general-purpose embedded web app for Android. &amp;nbsp;It allows for further remote monitoring and control, such as location tracking, remote text-to-speech, and remote file management over HTTP. &amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;The source code for the spycam app is available on github &lt;a href="http://github.com/mleone/spycam"&gt;here&lt;/a&gt;.&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;Check these out, too:&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/android-scripting/"&gt;SL4A Home Page&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://groups.google.com/group/android-scripting?pli=1"&gt;SL4A Mailing List&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.slideshare.net/panopticdev/broadcast-presentation"&gt;My Presentation on Broadcast and Ruby-on-Android at RIRUG&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7781964911499645745-6577484160737856059?l=leone.panopticdev.com' alt='' /&gt;&lt;/div&gt;</description><link>http://leone.panopticdev.com/2010/08/turn-your-android-phone-into-remote-spy.html</link><author>noreply@blogger.com (Mike Leone)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_-vwq5MP3moA/TH2uLcbXA5I/AAAAAAAAAC0/cIiO4l5BXrQ/s72-c/sinatra_snapshot.png' height='72' width='72'/><thr:total>26</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7781964911499645745.post-2815260207824719837</guid><pubDate>Tue, 24 Aug 2010 20:52:00 +0000</pubDate><atom:updated>2011-10-20T10:51:56.137-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>ruby</category><category domain='http://www.blogger.com/atom/ns#'>jruby</category><category domain='http://www.blogger.com/atom/ns#'>embedded</category><category domain='http://www.blogger.com/atom/ns#'>ase</category><category domain='http://www.blogger.com/atom/ns#'>sinatra</category><category domain='http://www.blogger.com/atom/ns#'>android</category><category domain='http://www.blogger.com/atom/ns#'>sl4a</category><category domain='http://www.blogger.com/atom/ns#'>broadcast</category><category domain='http://www.blogger.com/atom/ns#'>scripting</category><title>Broadcast Presentation at RIRUG</title><description>Slides are up from my August presentation at RIRUG.  I'm really excited about this software; more posts to follow shortly!&lt;br /&gt;&lt;br /&gt;&lt;div id="__ss_5021220" style="width: 425px;"&gt;&lt;strong style="display: block; margin: 12px 0 4px;"&gt;&lt;a href="http://www.slideshare.net/panopticdev/broadcast-presentation" title="Broadcast presentation"&gt;Broadcast presentation&lt;/a&gt;&lt;/strong&gt;&lt;object height="355" id="__sse5021220" width="425"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=broadcastpresentation-100820143704-phpapp01&amp;stripped_title=broadcast-presentation" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse5021220" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=broadcastpresentation-100820143704-phpapp01&amp;stripped_title=broadcast-presentation" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;div style="padding: 5px 0 12px;"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/panopticdev"&gt;Panoptic Development, Inc.&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7781964911499645745-2815260207824719837?l=leone.panopticdev.com' alt='' /&gt;&lt;/div&gt;</description><link>http://leone.panopticdev.com/2010/08/broadcast-presentation-at-rirug.html</link><author>noreply@blogger.com (Mike Leone)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7781964911499645745.post-5558175303880797666</guid><pubDate>Thu, 19 Aug 2010 06:18:00 +0000</pubDate><atom:updated>2011-10-20T10:59:37.702-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>ruby</category><category domain='http://www.blogger.com/atom/ns#'>deployment</category><category domain='http://www.blogger.com/atom/ns#'>git</category><category domain='http://www.blogger.com/atom/ns#'>rails</category><category domain='http://www.blogger.com/atom/ns#'>fabric</category><category domain='http://www.blogger.com/atom/ns#'>tutorial</category><category domain='http://www.blogger.com/atom/ns#'>python</category><category domain='http://www.blogger.com/atom/ns#'>django python</category><category domain='http://www.blogger.com/atom/ns#'>capistrano</category><title>Tutorial:  My Fabric Presentation from RIRUG</title><description>Slides are up from my presentation during the June meeting of the RI Ruby Users Group!&lt;br /&gt;&lt;br /&gt;&lt;div id="__ss_4604915" style="width: 425px;"&gt;&lt;strong style="display: block; margin: 12px 0 4px;"&gt;&lt;a href="http://www.slideshare.net/panopticdev/fabric-a-capistrano-alternative" title="Fabric:  A Capistrano Alternative"&gt;Fabric:  A Capistrano Alternative&lt;/a&gt;&lt;/strong&gt;&lt;object height="355" id="__sse4604915" width="425"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=capistranopresentation-100624105527-phpapp01&amp;stripped_title=fabric-a-capistrano-alternative" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse4604915" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=capistranopresentation-100624105527-phpapp01&amp;stripped_title=fabric-a-capistrano-alternative" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;div style="padding: 5px 0 12px;"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/panopticdev"&gt;Panoptic Development, Inc.&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7781964911499645745-5558175303880797666?l=leone.panopticdev.com' alt='' /&gt;&lt;/div&gt;</description><link>http://leone.panopticdev.com/2010/08/my-fabric-presentation-from-rirug.html</link><author>noreply@blogger.com (Mike Leone)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7781964911499645745.post-3006579065008834579</guid><pubDate>Sat, 27 Feb 2010 22:51:00 +0000</pubDate><atom:updated>2011-10-20T10:59:45.144-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>admin</category><category domain='http://www.blogger.com/atom/ns#'>forms</category><category domain='http://www.blogger.com/atom/ns#'>python</category><category domain='http://www.blogger.com/atom/ns#'>django python</category><category domain='http://www.blogger.com/atom/ns#'>code</category><category domain='http://www.blogger.com/atom/ns#'>programming</category><title>Custom Date Formats in the Django Admin</title><description>For better or for worse, subclassing Django components to add custom functionality is a common technique.&amp;nbsp; The workflow usually goes something like this:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Subclass a django component&lt;/li&gt;&lt;li&gt;Override a specific method&lt;/li&gt;&lt;li&gt;Set some custom configuration options in the method&lt;/li&gt;&lt;li&gt;Call super()&amp;nbsp;&lt;/li&gt;&lt;/ol&gt;For our Django 1.1 app, we needed to customize the behavior of a DateField so it would accept dates entered in the standard US format, MM-DD-YYYY, instead of the default behavior, YYYY-MM-DD.&amp;nbsp; We'll create a new field called USADateField.&lt;br /&gt;&lt;br /&gt;First, let's add a new module to our app, &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;fields.py&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;In &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;fields.py&lt;/span&gt;, subclass the Datefield form, adding the MM-DD-YYY format to the tuple of default formats:&lt;br /&gt;&lt;div style="color: #38761d;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;pre class="textmate-source"&gt;&lt;pre class="sunburst"&gt;&lt;b&gt;&lt;span class="meta meta_class meta_class_python" style="color: #38761d; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="storage storage_type storage_type_class storage_type_class_python"&gt;class&lt;/span&gt; &lt;span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_python"&gt;USADateFormField&lt;/span&gt;(&lt;span class="meta meta_class meta_class_inheritance meta_class_inheritance_python"&gt;&lt;span class="entity entity_other entity_other_inherited-class entity_other_inherited-class_python"&gt;forms.DateField&lt;/span&gt;&lt;/span&gt;):&lt;/span&gt;&lt;br /&gt;&lt;span class="meta meta_function meta_function_python" style="color: #38761d; font-family: 'Courier New', Courier, monospace;"&gt;    &lt;span class="storage storage_type storage_type_function storage_type_function_python"&gt;def&lt;/span&gt; &lt;span class="entity entity_name entity_name_function entity_name_function_python"&gt;&lt;span class="support support_function support_function_magic support_function_magic_python"&gt;__init__&lt;/span&gt;&lt;/span&gt;(&lt;span class="meta meta_function meta_function_parameters meta_function_parameters_python"&gt;&lt;span class="variable variable_parameter variable_parameter_function variable_parameter_function_python"&gt;self&lt;/span&gt;, *&lt;span class="variable variable_parameter variable_parameter_function variable_parameter_function_python"&gt;args&lt;/span&gt;, **&lt;span class="variable variable_parameter variable_parameter_function variable_parameter_function_python"&gt;kwargs&lt;/span&gt;&lt;/span&gt;):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #38761d; font-family: 'Courier New', Courier, monospace;"&gt;        &lt;/span&gt;&lt;span class="meta meta_function-call meta_function-call_python" style="color: #38761d; font-family: 'Courier New', Courier, monospace;"&gt;kwargs.update(&lt;span class="meta meta_function-call meta_function-call_arguments meta_function-call_arguments_python"&gt;&lt;span class="meta meta_structure meta_structure_dictionary meta_structure_dictionary_python"&gt;{&lt;span class="meta meta_structure meta_structure_dictionary meta_structure_dictionary_key meta_structure_dictionary_key_python"&gt;&lt;span class="string string_quoted string_quoted_single string_quoted_single_single-line string_quoted_single_single-line_python"&gt;'input_formats'&lt;/span&gt;&lt;/span&gt;: &lt;span class="meta meta_structure meta_structure_dictionary meta_structure_dictionary_value meta_structure_dictionary_value_python"&gt;(&lt;span class="string string_quoted string_quoted_double string_quoted_double_single-line string_quoted_double_single-line_python"&gt;"&lt;span class="constant constant_other constant_other_placeholder constant_other_placeholder_python"&gt;%m&lt;/span&gt;-&lt;span class="constant constant_other constant_other_placeholder constant_other_placeholder_python"&gt;%d&lt;/span&gt;-&lt;span class="constant constant_other constant_other_placeholder constant_other_placeholder_python"&gt;%Y&lt;/span&gt;"&lt;/span&gt;,)&lt;span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_python"&gt;+&lt;/span&gt;DEFAULT_DATE_INPUT_FORMATS&lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #38761d; font-family: 'Courier New', Courier, monospace;"&gt;        &lt;/span&gt;&lt;span class="meta meta_function-call meta_function-call_python" style="color: #38761d; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="support support_type support_type_python"&gt;super&lt;/span&gt;(&lt;span class="meta meta_function-call meta_function-call_arguments meta_function-call_arguments_python"&gt;USADateFormField, &lt;span class="variable variable_language variable_language_python"&gt;self&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;&lt;span style="color: #38761d; font-family: 'Courier New', Courier, monospace;"&gt;.&lt;/span&gt;&lt;span class="meta meta_function-call meta_function-call_python" style="color: #38761d; font-family: 'Courier New', Courier, monospace;"&gt;__init__(&lt;span class="meta meta_function-call meta_function-call_arguments meta_function-call_arguments_python"&gt;&lt;span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_python"&gt;*&lt;/span&gt;args, &lt;span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_python"&gt;*&lt;/span&gt;&lt;span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_python"&gt;*&lt;/span&gt;kwargs&lt;/span&gt;)&lt;/span&gt;&lt;/b&gt;&lt;/pre&gt;&lt;pre class="sunburst"&gt;&lt;/pre&gt;&lt;pre class="sunburst"&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;br /&gt;Then, subclass the django model DateField to use the new USADateFieldForm:&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source" style="color: #38761d; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;pre class="sunburst"&gt;&lt;b&gt;&lt;span class="meta meta_class meta_class_python"&gt;&lt;span class="storage storage_type storage_type_class storage_type_class_python"&gt;class&lt;/span&gt; &lt;span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_python"&gt;USADateField&lt;/span&gt;(&lt;span class="meta meta_class meta_class_inheritance meta_class_inheritance_python"&gt;&lt;span class="entity entity_other entity_other_inherited-class entity_other_inherited-class_python"&gt;models.DateField&lt;/span&gt;&lt;/span&gt;):&lt;/span&gt;&lt;br /&gt;&lt;span class="meta meta_function meta_function_python"&gt;    &lt;span class="storage storage_type storage_type_function storage_type_function_python"&gt;def&lt;/span&gt; &lt;span class="entity entity_name entity_name_function entity_name_function_python"&gt;formfield&lt;/span&gt;(&lt;span class="meta meta_function meta_function_parameters meta_function_parameters_python"&gt;&lt;span class="variable variable_parameter variable_parameter_function variable_parameter_function_python"&gt;self&lt;/span&gt;, **&lt;span class="variable variable_parameter variable_parameter_function variable_parameter_function_python"&gt;kwargs&lt;/span&gt;&lt;/span&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="meta meta_function-call meta_function-call_python"&gt;kwargs.update(&lt;span class="meta meta_function-call meta_function-call_arguments meta_function-call_arguments_python"&gt;&lt;span class="meta meta_structure meta_structure_dictionary meta_structure_dictionary_python"&gt;{&lt;span class="meta meta_structure meta_structure_dictionary meta_structure_dictionary_key meta_structure_dictionary_key_python"&gt;&lt;span class="string string_quoted string_quoted_single string_quoted_single_single-line string_quoted_single_single-line_python"&gt;'form_class'&lt;/span&gt;&lt;/span&gt;: &lt;span class="meta meta_structure meta_structure_dictionary meta_structure_dictionary_value meta_structure_dictionary_value_python"&gt;USADateFormField&lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="keyword keyword_control keyword_control_flow keyword_control_flow_python"&gt;return&lt;/span&gt; &lt;span class="meta meta_function-call meta_function-call_python"&gt;&lt;span class="support support_type support_type_python"&gt;super&lt;/span&gt;(&lt;span class="meta meta_function-call meta_function-call_arguments meta_function-call_arguments_python"&gt;USADateField, &lt;span class="variable variable_language variable_language_python"&gt;self&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;.&lt;span class="meta meta_function-call meta_function-call_python"&gt;formfield(&lt;span class="meta meta_function-call meta_function-call_arguments meta_function-call_arguments_python"&gt;&lt;span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_python"&gt;*&lt;/span&gt;&lt;span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_python"&gt;*&lt;/span&gt;kwargs&lt;/span&gt;)&lt;/span&gt;&lt;/b&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;div style="color: #38761d; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;When you're done, your new module will look like this:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://pastie.org/846155.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Finally, import &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;fields&lt;/span&gt; in your models.py module and use it!&amp;nbsp; Your model might look something like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color: #38761d; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;&lt;b&gt;class Appointment(models.Model):&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="color: #38761d; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; scheduled_date = USADateField(blank=True)&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;I like approaches like this, which push logic back into the models.&amp;nbsp; The functionality would be tougher to test and maintain if we wrote custom front-end code for the field.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7781964911499645745-3006579065008834579?l=leone.panopticdev.com' alt='' /&gt;&lt;/div&gt;</description><link>http://leone.panopticdev.com/2010/02/custom-date-formats-in-django-admin.html</link><author>noreply@blogger.com (Mike Leone)</author><thr:total>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7781964911499645745.post-3236535500768224415</guid><pubDate>Fri, 12 Feb 2010 19:03:00 +0000</pubDate><atom:updated>2011-10-20T10:59:54.588-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>ruby</category><category domain='http://www.blogger.com/atom/ns#'>deployment</category><category domain='http://www.blogger.com/atom/ns#'>git</category><category domain='http://www.blogger.com/atom/ns#'>rails</category><category domain='http://www.blogger.com/atom/ns#'>fabric</category><category domain='http://www.blogger.com/atom/ns#'>python</category><category domain='http://www.blogger.com/atom/ns#'>django python</category><category domain='http://www.blogger.com/atom/ns#'>capistrano</category><title>Fabric - A Deployment Tool for Rubyists and Pythonists Alike</title><description>If you're coming from the Ruby/Rails world, the industry standard tool for deployment is clearly &lt;a href="http://capify.org/"&gt;Capistrano&lt;/a&gt;.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;In some cases, though, using &lt;a href="http://fabfile.org/"&gt;Fabric&lt;/a&gt; might make more sense.&amp;nbsp; If you've got a simple web app and want to try something different for deployment, have a look at Fabric. It's a terse, lightweight Python deployment tool and a good alternative to Capistrano. Most importantly, it's SUPER EASY to learn and you don't need ANY Python experience.&lt;br /&gt;&lt;br /&gt;I like how Fabric's tutorial shows a version-control-agnostic deployment pattern.  The fabfile is part of the project we want to deploy, and whatever is in our project directory will be deployed.  With this pattern, Fabric doesn't need any information about our version control system or repository.&lt;br /&gt;&lt;br /&gt;For example, I use git for most of my projects. &lt;br /&gt;&lt;br /&gt;If I'm running the master branch on my development machine and want to deploy master, I just run&lt;br /&gt;&lt;pre class="bash" name="code"&gt;&lt;b style="color: #38761d;"&gt;$ fab deploy&lt;/b&gt;&lt;/pre&gt;What if I want to deploy my release branch instead of the master branch?  I just do the following:&lt;br /&gt;&lt;pre&gt;&lt;b&gt;&lt;span style="color: #38761d;"&gt;$ git checkout my-release-branch&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #38761d;"&gt;$ fab deploy&lt;/span&gt;&lt;/b&gt;&lt;/pre&gt;&lt;br /&gt;Super easy.&amp;nbsp; We can manage the code we're deploying with the tools already built in to our version control system; we don't have to implement those controls again with our deployment tool.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Installing Fabric on Ubuntu 9.10&lt;/span&gt;&lt;br /&gt;&lt;pre style="color: #38761d;"&gt;&lt;b&gt;$ sudo apt-get install python-setuptools&lt;br /&gt;$ sudo easy_install fabric&lt;/b&gt;&lt;/pre&gt;&lt;br /&gt;Wow, that was easy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7781964911499645745-3236535500768224415?l=leone.panopticdev.com' alt='' /&gt;&lt;/div&gt;</description><link>http://leone.panopticdev.com/2010/02/fabric-deployment-tool-for-rubyists-and.html</link><author>noreply@blogger.com (Mike Leone)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7781964911499645745.post-1486086311114572822</guid><pubDate>Thu, 15 Oct 2009 19:06:00 +0000</pubDate><atom:updated>2011-10-20T10:53:14.511-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>ruby</category><category domain='http://www.blogger.com/atom/ns#'>rails</category><category domain='http://www.blogger.com/atom/ns#'>model</category><category domain='http://www.blogger.com/atom/ns#'>refactoring</category><category domain='http://www.blogger.com/atom/ns#'>module</category><title>Sharing Model Code via Modules</title><description>Recently, I worked on an embedded Rails application where there were two models representing network devices.&amp;nbsp; The models were quite different, but nonetheless, both had &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;host&lt;/span&gt; and &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;name&lt;/span&gt; fields, and there was some shared functionality.&amp;nbsp; Here's an example:&lt;br /&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;class NetworkVideoDevice &amp;lt; ActiveRecord::Base&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; require 'ping'&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; def responds_to_ping?&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ping.pingecho host, 1.0&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; end&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; has_many :live_streams&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; validates_uniqueness_of :host&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; validates_presence_of&amp;nbsp;&amp;nbsp; :name&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; named_scope :ordered_by_host, {:order =&amp;gt; "host"}&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;end&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;class NetworkAudioDevice &amp;lt; ActiveRecord::Base&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; require 'ping'&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; def responds_to_ping?&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ping.pingecho host, 1.0&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; end&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; has_many :live_streams&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; validates_uniqueness_of :host&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; validates_presence_of&amp;nbsp;&amp;nbsp; :name&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; named_scope :ordered_by_host, {:order =&amp;gt; "host"}&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;end&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;At this point, developers may be aware of the code smells.&amp;nbsp; Maintaining the same functionality in two places is error-prone, hard to debug, and puts an unnecessary burden on developers.&amp;nbsp; In the pre-Rails 2.0 days, I saw many developers using &lt;a href="http://ar.rubyonrails.org/classes/ActiveRecord/Base.html"&gt;Single Table Inheritence&lt;/a&gt; to share functionality between models.&amp;nbsp; As Rails developers' familiarity with Ruby increased, though, I've noticed developers taking advantage of Ruby's &lt;a href="http://www.ruby-doc.org/core/classes/Module.html"&gt;Modules&lt;/a&gt; for solutions to problems like this.&lt;br /&gt;&lt;br /&gt;First, let's factor out the common method, &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;responds_to_ping?&lt;/span&gt; into a module.&amp;nbsp; Since this module will only be used by Active Record models, I'm going to put it directly in the app/models directory so I don't even have to require it anywhere.&amp;nbsp; Now, the code looks like this:&lt;br /&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;# the newly-created module:&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;module NetworkDevice&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; require 'ping'&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; def responds_to_ping?&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ping.pingecho host, 1.0&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; end&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;end&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;class NetworkVideoDevice &amp;lt; ActiveRecord::Base&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; include NetworkDevice&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; has_many :live_streams&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; validates_uniqueness_of :host&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; validates_presence_of&amp;nbsp;&amp;nbsp; :name&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; named_scope :ordered_by_host, {:order =&amp;gt; "host"}&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;end&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;class NetworkAudioDevice &amp;lt; ActiveRecord::Base&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; include NetworkDevice&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; has_many :live_streams&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; validates_uniqueness_of :host&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; validates_presence_of&amp;nbsp;&amp;nbsp; :name&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; named_scope :ordered_by_host, {:order =&amp;gt; "host"}&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;end&lt;/span&gt;&lt;b&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;Now, if we want to change that ping timeout from one second to two seconds, we only need to change it in one place.&lt;br /&gt;&lt;br /&gt;This is a good start, but we can take our refactoring even further.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: small;"&gt;Sharing ActiveRecord Functionality via &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;included&lt;/span&gt; and &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;class_eval&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;We also do the same validation on some fields, and we have the same named_scope call in both models.&amp;nbsp; Let's stick those in the module, too!&amp;nbsp; Now, NetworkDevice looks like this:&lt;br /&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;module NetworkDevice &amp;lt; ActiveRecord::Base&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; require 'ping'&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; def responds_to_ping?&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ping.pingecho host, 1.0&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; end&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; has_many :live_streams&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; validates_uniqueness_of :host&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; validates_presence_of&amp;nbsp;&amp;nbsp; :name&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; named_scope :ordered_by_host, {:order =&amp;gt; "host"}&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;end&lt;/span&gt;&lt;b&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;b&gt;But wait!&lt;/b&gt;&amp;nbsp; Try to start your application, and it barfs!&amp;nbsp; What happened?&lt;br /&gt;&lt;span style="color: red; font-family: 'Courier New', Courier, monospace;"&gt;NoMethodError: undefined method `has_many' for NetworkDevice:Module&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Our NetworkDevice module doesn't know anything about ActiveRecord methods like has_many, so when Ruby tries to evaluate it outside the context of an AR::Base-descended class, it doesn't work.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;The solution? use &lt;span style="font-family: inherit;"&gt;Module&lt;/span&gt;'s &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;included&lt;/span&gt; method and Class's &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;class_eval&lt;/span&gt; method.&lt;br /&gt;&lt;br /&gt;included, a class method available to modules, lets us defer funcionality until the module is included somewhere.&amp;nbsp; We simply tell Ruby to evaluate some code in the context of the including class, which will descend from ActiveRecord::Base.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;class_eval lets us define or call class methods on the receiver on the fly.&amp;nbsp; In this case, we'll want to call some ActiveRecord::Base class methods, like &lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;named_scope&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Sound confusing?&amp;nbsp; Let's see the new code in action:&lt;br /&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;module NetworkDevice &amp;lt; ActiveRecord::Base&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; require 'ping'&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; def responds_to_ping?&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ping.pingecho host, 1.0&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; end&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; # run this in the context of the including class:&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; def self.included(base_class)&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; base_class.class_eval do&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; has_many :live_streams&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; validates_uniqueness_of :host&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; validates_presence_of&amp;nbsp;&amp;nbsp; :name&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; named_scope :ordered_by_host, {:order =&amp;gt; "host"}&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; end&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; end&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;end&lt;/span&gt;&lt;/div&gt;&lt;div style="color: blue;"&gt;&lt;br /&gt;&lt;/div&gt;There!&amp;nbsp; The errors are gone, and all of our general network device code is in one place.&amp;nbsp; Now, our code is easier to maintain, is less susceptible to bugs, and we'll probably even save our clients/employers some money in the long run.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7781964911499645745-1486086311114572822?l=leone.panopticdev.com' alt='' /&gt;&lt;/div&gt;</description><link>http://leone.panopticdev.com/2009/10/sharing-model-code-via-modules.html</link><author>noreply@blogger.com (Mike Leone)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7781964911499645745.post-376826736607852103</guid><pubDate>Thu, 13 Aug 2009 20:05:00 +0000</pubDate><atom:updated>2011-10-20T10:53:29.164-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>mojo</category><category domain='http://www.blogger.com/atom/ns#'>os</category><category domain='http://www.blogger.com/atom/ns#'>palm</category><category domain='http://www.blogger.com/atom/ns#'>android</category><category domain='http://www.blogger.com/atom/ns#'>ubuntu</category><title>Setting Up the Palm Mojo SDK on 64-Bit Ubuntu 9.04</title><description>I'll probably be buying a new Palm Pre next month.  As such, I've been tinkering with &lt;span style="font-style: italic;"&gt;webOS&lt;/span&gt;, Palm's new Linux-powered mobile platform, the Palm Pre emulator, built on VirtualBox, and Palm's &lt;span style="font-style: italic;"&gt;Mojo SDK&lt;/span&gt;.  The Mojo SDK lets developers create Palm apps using ubiquitous web technologies (HTML, CSS, JavaScript) so it's an attractive choice for web developers looking to get into mobile development.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Here's what I had to do to get everything working on 64-bit Ubuntu 9.04.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;First, the Palm Pre emulator requires VirtualBox 2.2+.  If you're already running version 1.x, included in the Ubuntu repos, uninstall it.&lt;br /&gt;&lt;pre&gt;$ sudo apt-get remove virtualbox&lt;/pre&gt;Download and install the latest 64-bit version of VirtualBox from virtualbox.org.  I found a debian package for version 3.0 &lt;a href="http://download.virtualbox.org/virtualbox/3.0.4/virtualbox-3.0_3.0.4-50677_Ubuntu_jaunty_amd64.deb"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;If you're upgrading from VirtualBox 1.x, you'll need to convert your settings.&lt;br /&gt;&lt;pre&gt;$ VirtualBox --convertSettings&lt;/pre&gt;Next, you'll need to download and install the mojo and novacom packages as noted in Palm's setup instructions.&lt;br /&gt;&lt;br /&gt;But wait, what's this?  There are only 32-bit packages available!  What should we do?  Luckily, someone has already run into the problem.  Read this excellent post from the "Tried It" blog &lt;a href="http://trieditonce.blogspot.com/2009/07/getting-palm-mojo-sdk-to-work-on-64-bit.html"&gt;here&lt;/a&gt;, and apply the author's script to both the mojo and novacom packages.  At that point, they'll install successfully.&lt;br /&gt;&lt;br /&gt;Now, you can finish following Palm's installation instructions.  It's time to start buildin' apps!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7781964911499645745-376826736607852103?l=leone.panopticdev.com' alt='' /&gt;&lt;/div&gt;</description><link>http://leone.panopticdev.com/2009/08/setting-up-palm-mojo-sdk-on-64-bit.html</link><author>noreply@blogger.com (Mike Leone)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7781964911499645745.post-6505885361492074208</guid><pubDate>Tue, 28 Jul 2009 21:09:00 +0000</pubDate><atom:updated>2011-10-20T10:53:40.728-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>ruby</category><category domain='http://www.blogger.com/atom/ns#'>rails</category><category domain='http://www.blogger.com/atom/ns#'>postgres</category><category domain='http://www.blogger.com/atom/ns#'>ubuntu</category><title>Rails/Postgres Setup Gotchas - Ubuntu 9.04</title><description>I recently switched to Ubuntu 9.04 after using OpenSUSE- and Fedora-Based development environments for several years, and it's been great for both Rails development and general use.  The defaults are well-chosen, hardware integration is seamless, and in general, the user experience is the best I've seen of any Linux distro.  Still, the default Ubuntu install is missing many important development packages; I had to take a few unexpected steps to get a simple, Postgres-backed Rails project running under Ruby 1.8.   Hopefully, documenting these steps will save time for other developers.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;First, install basic ruby and rubygems packages:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="Bash" name="code"&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;$ sudo apt-get install ruby ruby-dev rubygems&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;&lt;br /&gt;If your app needs to make requests over SSL, i&lt;/span&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;nstall Ruby OpenSSL bindings:&lt;/span&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;$ sudo apt-get install libopenssl-ruby&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;SET UP POSTGRES  AND DATABASES:&lt;br /&gt;Install basic postgres packages.  Note that some applications won't require postgresql-contrib:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;$ sudo apt-get install postgresql postgresql-8.3 postgresql-8.3-plr&lt;br /&gt;postgresql-client-8.3 postgresql-client-common postgresql-common&lt;br /&gt;postgresql-contrib postgresql-contrib-8.3 postgresql-server-dev-8.3&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Install the postgres gem (tested w/ version 0.7.9.2008.01.28)&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;$ sudo gem install postgres&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Initialize postgres.  As your system's postgres user:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;$ initdb -D /var/lib/pgsql/data&lt;br /&gt;$ pg_ctl -D /var/lib/pgsql/data -l logfile start&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Make sure postgres starts on boot.  In Ubuntu, this should be done automatically for you, but just to be sure:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;$ sudo update-rc.d postgresql-8.3 defaults&lt;br /&gt;# System startup links for /etc/init.d/postgresql-8.3 already exist&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;As the postgres user, create a user for psql; answering no to all questions.  This will probably be the user referenced in your database.yml config file.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;$ createuser &lt;span style="font-family: monospace;"&gt;dbuser&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;In order to give the user privilages to run DROP DATABASE for commands like&lt;br /&gt;rake:test, you may have to do the following in psql:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;ALTER USER dbuser CREATEUSER;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'courier new'; font-size: 100%;"&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7781964911499645745-6505885361492074208?l=leone.panopticdev.com' alt='' /&gt;&lt;/div&gt;</description><link>http://leone.panopticdev.com/2009/07/rails-setup-gotchas-ubuntu-904.html</link><author>noreply@blogger.com (Mike Leone)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7781964911499645745.post-147533569703932837</guid><pubDate>Mon, 11 May 2009 16:13:00 +0000</pubDate><atom:updated>2011-10-20T10:53:59.597-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>ruby-gcal</category><category domain='http://www.blogger.com/atom/ns#'>ruby</category><category domain='http://www.blogger.com/atom/ns#'>gcal</category><category domain='http://www.blogger.com/atom/ns#'>git</category><category domain='http://www.blogger.com/atom/ns#'>google calendar</category><title>Ruby-gcal is Released!</title><description>I just released my open-source Google Calendar library, ruby-gcal, on GitHub!&amp;nbsp; Check it out &lt;a href="http://github.com/mleone/ruby-gcal"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;There are more features in the works, but for now, it allows you to add, update and delete multiple events with few HTTP requests using Google's batch processing API.&amp;nbsp; When I have some more free time, I plan on releasing an "acts_as_google_calendar_event" sort of Rails plugin, so model objects corresponding to Google Calendar events can be saved to a database and synced with a GCal account.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7781964911499645745-147533569703932837?l=leone.panopticdev.com' alt='' /&gt;&lt;/div&gt;</description><link>http://leone.panopticdev.com/2009/05/ruby-gcal-is-released.html</link><author>noreply@blogger.com (Mike Leone)</author><thr:total>0</thr:total></item></channel></rss>
