<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Underneath the already known &#187; Development</title>
	<atom:link href="http://vaskas.ru/category/development/feed/" rel="self" type="application/rss+xml" />
	<link>http://vaskas.ru</link>
	<description>What Vaskas thinks</description>
	<lastBuildDate>Mon, 13 Jul 2009 19:38:23 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>IR_Black for highlight.js</title>
		<link>http://vaskas.ru/2009/07/13/ir_black-for-highlight-js/</link>
		<comments>http://vaskas.ru/2009/07/13/ir_black-for-highlight-js/#comments</comments>
		<pubDate>Mon, 13 Jul 2009 19:38:23 +0000</pubDate>
		<dc:creator>vaskas</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[highlight.js]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://vaskas.ru/?p=93</guid>
		<description><![CDATA[I&#8217;ve just ported InfiniteRed&#8217;s IR_black color scheme that I use in vim to highlight.js. And now I am the first ever person using it in the blog   Here you can see some ruby code highlighting and there goes some JavaScript. I&#8217;ve also tested it with CSS (looks just fine, trust me). Haven&#8217;t tested [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just ported InfiniteRed&#8217;s IR_black color scheme that I use in vim to <a href="http://softwaremaniacs.org/soft/highlight/">highlight.js</a>. And now I am the first ever person using it in the blog <img src='http://vaskas.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Here you can see some <a href="http://vaskas.ru/2008/08/05/using-erb-for-massive-static-pages-compilation/">ruby code highlighting</a> and there goes <a href="http://vaskas.ru/2008/08/06/browser-persistence/#more-34">some JavaScript</a>. I&#8217;ve also tested it with CSS (looks just fine, trust me). Haven&#8217;t tested with any other languages (sorry).<br />
<a href="http://gist.github.com/146382">Get it here</a> and please tell me about any glitches or ugliness with it.</p>
]]></content:encoded>
			<wfw:commentRss>http://vaskas.ru/2009/07/13/ir_black-for-highlight-js/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Compiling Ruby 1.9 on OS X Leopard with iPhone SDK</title>
		<link>http://vaskas.ru/2009/07/10/compiling-ruby-1-9-on-os-x-leopard-with-iphone-sdk/</link>
		<comments>http://vaskas.ru/2009/07/10/compiling-ruby-1-9-on-os-x-leopard-with-iphone-sdk/#comments</comments>
		<pubDate>Fri, 10 Jul 2009 10:25:18 +0000</pubDate>
		<dc:creator>vaskas</dc:creator>
				<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://vaskas.ru/?p=64</guid>
		<description><![CDATA[Some of you may be running into the same problem while trying to compile ruby 1.9 on OS X with iPhone SDK installed:
ld: in /usr/local/lib/libstdc++.6.dylib, file is not of required architecture
collect2: ld returned 1 exit status
make[1]: *** [.ext/i386-darwin9.6.0/enc/encdb.bundle] Error 1
This odd error is produced by iPhone SDK, which installs ARM libraries in /usr/local/lib.
You can easily [...]]]></description>
			<content:encoded><![CDATA[<p>Some of you may be running into the same problem while trying to compile ruby 1.9 on OS X with iPhone SDK installed:</p>
<pre>ld: in /usr/local/lib/libstdc++.6.dylib, file is not of required architecture
collect2: ld returned 1 exit status
make[1]: *** [.ext/i386-darwin9.6.0/enc/encdb.bundle] Error 1</pre>
<p>This odd error is produced by iPhone SDK, which installs ARM libraries in /usr/local/lib.<br />
You can easily work this around by specifying proper LDFLAGS for make:</p>
<pre>$ make LDFLAGS="-L. -L/usr/lib"</pre>
]]></content:encoded>
			<wfw:commentRss>http://vaskas.ru/2009/07/10/compiling-ruby-1-9-on-os-x-leopard-with-iphone-sdk/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>(Almost) instant RMagick on Leopard</title>
		<link>http://vaskas.ru/2009/03/05/almost-instant-rmagick-on-leopard/</link>
		<comments>http://vaskas.ru/2009/03/05/almost-instant-rmagick-on-leopard/#comments</comments>
		<pubDate>Thu, 05 Mar 2009 15:27:19 +0000</pubDate>
		<dc:creator>vaskas</dc:creator>
				<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://vaskas.ru/?p=44</guid>
		<description><![CDATA[If you (like me) use Mac OS X for your ruby development, you might need to install the RMagick gem. ImageMagick is the essential tool when it comes to automated image processing and RMagick is a nice ruby wrapper for it. The only problem is that ImageMagick has a lot of dependencies which involve numerous [...]]]></description>
			<content:encoded><![CDATA[<p>If you (like me) use Mac OS X for your ruby development, you might need to install the <a title="RMagick" href="http://rmagick.rubyforge.org/">RMagick</a> gem. <a title="ImageMagick" href="http://www.imagemagick.org/script/index.php">ImageMagick</a> is the essential tool when it comes to automated image processing and RMagick is a nice ruby wrapper for it. The only problem is that ImageMagick has a lot of dependencies which involve numerous libraries needing to be built (or installed) alongside with it.</p>
<p>Of course you might use <a title="MacPorts" href="http://www.macports.org/">MacPorts</a> or <a title="Fink" href="http://www.finkproject.org/">Fink</a> for the installation, but if you don&#8217;t really need these massive-impressive tools, here is a simple solution to get Rmagick installed fast. <a title="Download this tar archive" href="http://vaskas.ru/up/getRMagick.tar">Download this tar archive</a>, unpack it with <em>tar xvf</em>, <em>cd</em> to the getRMagick folder and launch the <em>getRMagick.sh</em> script. Please note that you should have Developer Tools installed on your Mac (usually available on the OS X installation DVD) as well as ruby + rubygems in order for the script to compile everything for you. After a while, if everything goes well, you&#8217;ll get the Magick stuff installed. I used the script on Intel and PowerPC Macs with OS X 10.5.6.<br />
And yeah, the script is very simple.<br />
<span id="more-44"></span></p>
<pre>
<code class="bash">
#!/bin/sh
tar xzvf freetype-2.3.5.tar.gz
cd freetype-2.3.5
./configure --prefix=/usr/local
make
sudo make install
cd ..

tar jxvf libpng-1.2.22.tar.bz2
cd libpng-1.2.22
./configure --prefix=/usr/local
make
sudo make install
cd ..

tar xzvf jpegsrc.v6b.tar.gz
cd jpeg-6b
ln -s `which glibtool` ./libtool
export MACOSX_DEPLOYMENT_TARGET=10.5
./configure --enable-shared --prefix=/usr/local
make
sudo make install
cd ..

tar xzvf tiff-3.8.2.tar.gz
cd tiff-3.8.2
./configure --prefix=/usr/local
make
sudo make install
cd ..

tar xzvf libwmf-0.2.8.4.tar.gz
cd libwmf-0.2.8.4
make clean
./configure
make
sudo make install
cd ..

tar xzvf lcms-1.17.tar.gz
cd lcms-1.17
make clean
./configure
make
sudo make install
cd ..

tar zxvf ghostscript-8.62.tar.gz
cd ghostscript-8.62/
./configure  --prefix=/usr/local
make
sudo make install
cd ..

tar zxvf ghostscript-fonts-std-8.11.tar.gz
sudo mv fonts /usr/local/share/ghostscript

tar xzvf ImageMagick-6.4.1-3.tar.gz
cd ImageMagick-6.4.1
export CPPFLAGS=-I/usr/local/include
export LDFLAGS=-L/usr/local/lib
./configure --prefix=/usr/local --disable-static --with-modules --with-quantum-depth=8 --with-gs-font-dir=/usr/local/share/ghostscript/fonts
make
sudo make install
cd ..

sudo gem install rmagick
</code>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://vaskas.ru/2009/03/05/almost-instant-rmagick-on-leopard/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Displaying Google Analytics charts on the website</title>
		<link>http://vaskas.ru/2008/08/08/displaying-google-analytics-charts-on-the-website/</link>
		<comments>http://vaskas.ru/2008/08/08/displaying-google-analytics-charts-on-the-website/#comments</comments>
		<pubDate>Fri, 08 Aug 2008 09:09:15 +0000</pubDate>
		<dc:creator>vaskas</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[charts]]></category>
		<category><![CDATA[curb]]></category>
		<category><![CDATA[google analytics]]></category>
		<category><![CDATA[rexml]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[statistics]]></category>

		<guid isPermaLink="false">http://vaskas.ru/?p=39</guid>
		<description><![CDATA[We wanted our Google Analytics charts to be displayed in one of the sections of Inshaker. GA is an excellent service for complex auditorium analysis. Unfortunately, it has no public API (though, I think it will be available in future). Fortunately, it is able to export reports to several formats, including XML.
There are several existing [...]]]></description>
			<content:encoded><![CDATA[<p>We wanted our <a href="http://www.google.com/analytics/">Google Analytics</a> charts to be displayed in one of the sections of <a href="http://www.inshaker.ru/about.html#view-stat">Inshaker.</a> GA is an excellent service for complex auditorium analysis. Unfortunately, it has no public API (though, I think it will be available in future). Fortunately, it is able to export reports to several formats, including XML.<br />
There are several existing tools for drawing charts on-the fly. Among them are the excellent flash-based amCharts and url-based Google Charts. I chose <a href="http://www.amcharts.com">amCharts</a> because they are more nice-looking and interactive. AmCharts rely on their own XML data files, which have rather straightforward formats.<br />
<span id="more-39"></span><br />
<img src="http://vaskas.ru/up/stat.png" alt="Visitors/visits chart" /><br />
So the first problem was to download and convert GA reports into amCharts-compatible formats. The second was to be able to do it automatically, so that our charts always reflect actual statistics.<br />
What I came up to was writing a <a href="http://vaskas.ru/up/analytic.rb">Ruby script</a> to do all the download-and-convert job and launching it with cron each N minutes.</p>
<p>I think the code can speak for itself (since it&#8217;s Ruby). Some notes on it: I used the Curb library to download the reports. It&#8217;s not mature yet to handle cookies, so I had to do cookie handling myself (fetching them from HTTP response and adding them to request). Why care about cookies? In order to authorize in Google Analytics.<br />
The REXML part is rather simple.<br />
Before using the script make sure to create directories specified in Config module (and provide correct login data and site id)<br />
<a href="http://vaskas.ru/up/analytic.rb">Grab the script here</a> or continue reading the code:</p>
<pre>
<code class="ruby">
require 'rubygems'
require 'activesupport'
require 'rexml/document'
require 'unicode'
require 'curb'
require 'cgi'
include REXML
$KCODE = 'u'

# Downloading and conversion of
# Google Analytics reports into amCharts data.xml files

class String
  def merge_i
    self.gsub(" ", "").to_i
  end
end

module Config
  SITE_ID = "9038802" # your site id
  PERIOD = ARGV[0] ? ARGV[0].to_i : 30 # period (days)

  REPORTS_PATH = "reports/" # directory to store downloaded GA reports

  VISITORS_REPORT = "VisitorsOverviewReport"
  CONTENT_REPORT  = "ContentReport"
  GEO_REPORT      = "GeoMapReport"

  OUT_VISITS = "./stat/visitors/data.xml" # amCharts data.xml file (visitors stats)
  OUT_CITIES = "./stat/cities/data.xml" # (cities report xml file)

  EMAIL    = "my_google_analytics@mail.com" # your GA login email
  PASSWORD = "my_password" # your GA password
  PIE_COLORS = ["#a2bcda", "#c1b76f", "#f28358", "#edef00", "#24cbe5", "#64e572"]
end

def process_visits
  path_label = "AnalyticsReport/Report/Graph/Serie/Point/Label"
  path_value = "AnalyticsReport/Report/Graph/Serie/Point/Value"

  vxml = Document.new File.new(Config::REPORTS_PATH + Config::VISITORS_REPORT + ".xml")
  dates    = vxml.elements.to_a(path_label).map {|d| d = d.text}
  visitors = vxml.elements.to_a(path_value).map {|v| v = v.text.merge_i}

  cxml = Document.new File.new(Config::REPORTS_PATH + Config::CONTENT_REPORT + ".xml")
  views = cxml.elements.to_a(path_value).map {|v| v = v.text.merge_i}

  data_file = Document.new

  chart = Element.new("chart")
  data_file.add chart

  # X-Axis - dates
  series = Element.new("series")
  dates.each_with_index { |date, i|
    value = Element.new("value")
    value.attributes["xid"] = i.to_s
    value.text = date
    series.add value
  }
  chart.add_element series

  graphs = Element.new("graphs")
  chart.add_element graphs

  # Y-Axis - numbers
  [views, visitors].each_with_index { |set, i|
    graph = Element.new("graph")
    graph.attributes["gid"] = (i+1).to_s
    set.each_with_index { |num, j|
      value = Element.new("value")
      value.attributes["xid"] = j.to_s
      value.text = num
      graph.add value
    }
    graphs.add graph
  }

  # Output
  File.open(Config::OUT_VISITS, "w+") {|charts| data_file.write(charts) }
  puts "Built visits/visitors chart..."
end

def process_cities
  path_name  = "AnalyticsReport/Report/GeoMap/Region[position()<7]/Name"
  path_value = "AnalyticsReport/Report/GeoMap/Region[position()<7]/Value"

  cxml = Document.new File.new(Config::REPORTS_PATH + Config::GEO_REPORT + ".xml")
  cities = cxml.elements.to_a(path_name).map {|c| c = c.text}
  visitors =  cxml.elements.to_a(path_value).map {|v| v = v.text.merge_i}

  data_file = Document.new
  pie = Element.new("pie")

  data_file.add pie

  cities.each_with_index {|city, i|
    slice = Element.new("slice")
    slice.attributes["title"] = city
    if Config::PIE_COLORS[i] then slice.attributes["color"] = Config::PIE_COLORS[i] end
    slice.text = visitors[i].to_s
    pie.add slice
  }

  # Output
  File.open(Config::OUT_CITIES, "w+") {|pie| data_file.write(pie) }
  puts "Built cities chart..."
end

def get_cookies(header_str)
  cookies = {}
  headers = header_str.split("\n")
  headers.each {|h|
    if h =~ /Set-Cookie: (.+)/
      arr = $1.split("=")
      name = arr[0]
      cookies[name] = arr[1].split(";")[0]
    end
  }
  cstr = ""
  cookies.each {|name, val| cstr += name + "=" + CGI.escape(val) + ";" }
  cstr
end

def download_reports
  statuses = {} # statuses of downloading of reports (true - success, false - failed)

  dates = [Config::PERIOD.days.ago, Time.now].map {|d| d.strftime("%Y%m%d")}

  auth_url   = "https://www.google.com/accounts/ServiceLoginBoxAuth"
  report_pfx = "https://www.google.com/analytics/reporting/export?fmt=1&#038;id=#{Config::SITE_ID}&#038;pdr=#{dates[0]}-#{dates[1]}&#038;segkey=city&#038;cmp=average&#038;&#038;rpt="

  serv  = Curl::PostField.content("service", "analytics")
  hl    = Curl::PostField.content("hl", "ru-RU")
  email = Curl::PostField.content("Email", Config::EMAIL)
  passw = Curl::PostField.content("Passwd", Config::PASSWORD)

  # Authorization in Google Analytics
  c = Curl::Easy.new(auth_url)
  c.http_post(serv, hl, email, passw)
  cstr = get_cookies(c.header_str)

  # Downloading of reports
  [Config::VISITORS_REPORT, Config::CONTENT_REPORT, Config::GEO_REPORT].each { |rpt|
    c = Curl::Easy.new(report_pfx + rpt)
    c.headers["Cookie"] = cstr
    c.http_get
    if c.body_str =~ /<\/AnalyticsReport>/
      puts "Downloaded "+ rpt + "..."
      File.open(Config::REPORTS_PATH + rpt + ".xml", "w+") {|out| out.write(c.body_str) }
      statuses[rpt] = true
    else
      puts "Failed to download " + rpt + "..."
      statuses[rpt] = false
    end
  }
  statuses
end

dates = [Config::PERIOD.days.ago, Time.now].map {|d| d.strftime("%d %B %Y")}
puts "Trying to download reports from #{dates[0]} to #{dates[1]}"
statuses = download_reports
if(statuses[Config::VISITORS_REPORT] &#038;&#038; statuses[Config::CONTENT_REPORT]) then process_visits end
if(statuses[Config::GEO_REPORT]) then process_cities end
</code></pre>
<p>The crontab (crontab -e) is like this</p>
<pre>
# m h  dom mon dow   command
0,30 * * * * /www/mysite/update_stats.sh
</pre>
<p>update_stats.sh executes analytic.rb and does some other work.</p>
]]></content:encoded>
			<wfw:commentRss>http://vaskas.ru/2008/08/08/displaying-google-analytics-charts-on-the-website/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Browser persistence</title>
		<link>http://vaskas.ru/2008/08/06/browser-persistence/</link>
		<comments>http://vaskas.ru/2008/08/06/browser-persistence/#comments</comments>
		<pubDate>Wed, 06 Aug 2008 12:22:38 +0000</pubDate>
		<dc:creator>vaskas</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[persistence]]></category>
		<category><![CDATA[storage]]></category>
		<category><![CDATA[userData behavior]]></category>

		<guid isPermaLink="false">http://vaskas.ru/?p=34</guid>
		<description><![CDATA[Why use server-side data storage, if you don&#8217;t do any data processing on server? There are many cases when you&#8217;d rather keep your data structures on the client side. In Inshaker, we had to manipulate and persist large amounts of user-specific data on the client side. Cookies were not an option because of the 4kb [...]]]></description>
			<content:encoded><![CDATA[<p>Why use server-side data storage, if you don&#8217;t do any data processing on server? There are many cases when you&#8217;d rather keep your data structures on the client side. In <a href="http://www.inshaker.ru">Inshaker,</a> we had to manipulate and persist large amounts of user-specific data on the client side. Cookies were not an option because of the 4kb limit. So we used <a href="http://browserpersistence.ru">the persistency library by Ilya Kantor</a> with slight modifications. It makes use of window.globalStorage object in Mozilla, userData behavior in MSIE and Flash storage in other cases (we will be implementing Safari sqlite storage too). All three mechanisms are different: flash storage is loaded asynchronously and userData values can&#8217;t be accessed in other paths (i.e. /page.html and /dir/otherpage.html won&#8217;t be sharing the same data). That&#8217;s why we use a &#8220;proxy&#8221; page, which is loaded in an iframe. The data we persist is &#8220;attached&#8221; to an element in this page. </p>
<p>Usage is rather simple:</p>
<pre><code class="javascript">
	// needs callback because it's asynchronous in case of flash
	Storage.init(function(){
		Storage.put("js", "cool language");
		var desc = Storage.get("js");
		Storage.remove("js");
		Storage.put("objc", "pretty too");
		alert(Storage.get("objc"));
		Storage.clear();
	});
</code></pre>
<p><span id="more-34"></span><br />
<a href="http://browserpersistence.ru/storage.zip">Get the library from Ilya&#8217;s site</a>. If you need cross-directory storage sharing for IE, replace his Storage.userData section with this snippet:</p>
<pre><code class="javascript">
Storage.userData = function(onready) {
    var namespace = "data";

    if (!document.body.addBehavior) {
        throw new Error("No addBehavior available");
    }

	var e = document.createElement("iframe");
	e.setAttribute('id', 'storageFrame');
	e.style.border = '0';
	e.style.width  = '0';
	e.style.height = '0';
	var iframe = document.body.appendChild(e);
	iframe.src='proxy.html';

	iframe.addEventListener('load', function(e){
		var storage = iframe.contentWindow.document.getElementById('storageElement');
		storage.load(namespace);

	    Storage = {
	        get: function(key) {
	            return storage.getAttribute(key);
	        },

	        put: function(key, value) {
	            storage.setAttribute(key, value);
	            storage.save(namespace);
	        },

	        remove: function(key) {
	            storage.removeAttribute(key);
	            storage.save(namespace);
	        },

	        clear: function() {
	            var attrs = storage.XMLDocument.documentElement.attributes;

	            for(var i = 0; i < attrs.length; i++) storage.removeAttribute(attrs[i].name);
	            storage.save(namespace);
	        },

	        getKeys: function() {
	            var res = [];
	            var attrs = storage.XMLDocument.documentElement.attributes;

	            for(var i = 0; i < attrs.length; i++) res.push(attrs[i].name);
	            return res;
	        }
	    }
	    onready();
	}, false);
};
</code></pre>
<p>proxy.html is very simple:</p>
<pre><code class="html">
&lt;html&gt;
&lt;head&gt;
	&lt;title&gt;userData proxy object&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
	&lt;span id=\&quot;storageElement\&quot; style=\&quot;behavior:url(\'#default#userData\')\&quot;&gt;&lt;/span&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://vaskas.ru/2008/08/06/browser-persistence/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Objective-C</title>
		<link>http://vaskas.ru/2008/08/05/%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b2-objective-c-%d0%bd%d0%b0-%d1%80%d1%83%d1%81%d1%81%d0%ba%d0%be%d0%bc/</link>
		<comments>http://vaskas.ru/2008/08/05/%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b2-objective-c-%d0%bd%d0%b0-%d1%80%d1%83%d1%81%d1%81%d0%ba%d0%be%d0%bc/#comments</comments>
		<pubDate>Tue, 05 Aug 2008 11:15:03 +0000</pubDate>
		<dc:creator>vaskas</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[os x]]></category>

		<guid isPermaLink="false">http://vaskas.ru/?p=28</guid>
		<description><![CDATA[Так сложилось, что в России небольшой процент пользоваталей компьютеров Apple. А программистов, создающих desktop-приложения для Mac OS X, и того меньше. Однако с распространением iPhone, а особенно с появлением iPhone SDK интерес к программированию под iPhoneOS, несущей в себе компоненты Mac OS X и Darwin, в нашей стране возрос.
В настоящее время единственным языком, поддерживаемым iPhone [...]]]></description>
			<content:encoded><![CDATA[<p>Так сложилось, что в России небольшой процент пользоваталей компьютеров Apple. А программистов, создающих desktop-приложения для Mac OS X, и того меньше. Однако с распространением iPhone, а особенно с появлением iPhone SDK интерес к программированию под iPhoneOS, несущей в себе компоненты Mac OS X и Darwin, в нашей стране возрос.</p>
<p>В настоящее время единственным языком, поддерживаемым iPhone SDK, является Objective-C. Не лишенный обаяния, он впитал в себя черты C и Smalltalk. Всем, кому он любопытен, советую обратить внимание на замечательный ресурс <a href="http://pyobjc.ru/">&#8220;Программирование на Python и Objective-C в Mac OS&#8221;</a> Evgeniy&#8217;a Krysanov&#8217;a и статью <a href="http://steps3d.narod.ru/tutorials/objective-c-tutorial.html">&#8220;Язык программирования Objective-C&#8221;</a> Алексея Борескова.</p>
]]></content:encoded>
			<wfw:commentRss>http://vaskas.ru/2008/08/05/%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b2-objective-c-%d0%bd%d0%b0-%d1%80%d1%83%d1%81%d1%81%d0%ba%d0%be%d0%bc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using ERB for massive static pages compilation</title>
		<link>http://vaskas.ru/2008/08/05/using-erb-for-massive-static-pages-compilation/</link>
		<comments>http://vaskas.ru/2008/08/05/using-erb-for-massive-static-pages-compilation/#comments</comments>
		<pubDate>Tue, 05 Aug 2008 10:44:34 +0000</pubDate>
		<dc:creator>vaskas</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[erb]]></category>
		<category><![CDATA[inshaker]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://vaskas.ru/?p=13</guid>
		<description><![CDATA[For Inshaker, we needed a templating mechanism for pages sharing the same design. We also wanted the pages to be static (for performance reasons). We did not need them to be generated on-the-fly.
ERB was an ideal option for such a purpose. It allows us to generate all (75+) static pages when we need to make [...]]]></description>
			<content:encoded><![CDATA[<p>For <a href="http://www.inshaker.ru">Inshaker</a>, we needed a templating mechanism for pages sharing the same design. We also wanted the pages to be static (for performance reasons). We did not need them to be generated on-the-fly.<br />
ERB was an ideal option for such a purpose. It allows us to generate all (75+) static pages when we need to make an update.<br />
It is also very simple in terms of use:</p>
<p>1. You create a template for your page (template.rhtml)</p>
<pre><code class="html">
&lt;html&gt;
&lt;head&gt;
	&lt;title&gt;&lt;%= @title %&gt;&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
	This page was generated by &lt;%= @name %&gt; on &lt;%= Time.now.to_s %&gt;.
	&lt;ul&gt;
	&lt;% @tags.each do |tag| %&gt;
	&lt;li&gt;&lt;%= tag %&gt;&lt;/li&gt;
	&lt;% end %&gt;
	&lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>2. You create a ruby class which is bound to the template and run erb (erb_test.rb)</p>
<pre><code class="ruby">
require 'rubygems'
require 'erb'

class MyPage
  def initialize(hash)
    @title = hash[:title] + " - that's what I mean"
    @name = hash[:name]
    @tags = hash[:tags]
  end

  def get_binding
    binding
  end
end

# Instantiate ERB with the instance of that class and flush the output
template = File.open("template.rhtml").read
renderer = ERB.new(template)
page     = MyPage.new({:title => "ERB rules",
                       :name => "Ninja",
                       :tags => ["ruby", "erb", "html", "example"]})

File.open("mypage.html", "w+") { |html|
    html.write renderer.result(page.get_binding)
}
</code></pre>
<p>Of course, this is just a basic usage example. ERB shows its power when there are A LOT of pages to be generated, not a single one <img src='http://vaskas.ru/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /><br />
I should have a closer look at SproutCore since they seem to be using the same principle for views compilation.</p>
]]></content:encoded>
			<wfw:commentRss>http://vaskas.ru/2008/08/05/using-erb-for-massive-static-pages-compilation/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
