<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Simples Ideias. Por Nando Vieira.</title>
	
	<link>http://simplesideias.com.br</link>
	<description />
	<lastBuildDate>Thu, 15 Mar 2012 14:29:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/simplesideias" /><feedburner:info uri="simplesideias" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>simplesideias</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Usando modelos ActiveRecord entre projetos diferentes</title>
		<link>http://feedproxy.google.com/~r/simplesideias/~3/z8eJEFn8zCs/</link>
		<comments>http://simplesideias.com.br/usando-modelos-activerecord-entre-projetos-diferentes/#comments</comments>
		<pubDate>Tue, 06 Mar 2012 18:36:39 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=772</guid>
		<description><![CDATA[Estou transformando o Presentta, que hoje nada mais é que um hack com um monte de tarefas que precisam ser feitas manualmente, em um produto. Decidi começar este novo projeto do zero, então decidi fazer algo diferente. Em vez de ter um aplicativo monolítico, responsável por todas as partes do sistema, resolvi quebrar este sistema [...]]]></description>
			<content:encoded><![CDATA[<img class="align-right" src="http://m.simplesideias.com.br/lego.jpg" alt="Lego blocks">

<p>Estou transformando o <a rel="external" href="http://simplesideias.com.br/conheca-o-presentta/">Presentta</a>, que hoje nada mais é que um hack com um monte de tarefas que precisam ser feitas manualmente, em um produto. Decidi começar este novo projeto do zero, então decidi fazer algo diferente.</p>

<p>Em vez de ter um aplicativo monolítico, responsável por todas as partes do sistema, resolvi quebrar este sistema em diversos sistemas menores, cada um com sua responsabilidade. No Presentta, por exemplo, já tenho a parte de realtime com Node.js, interface web com Rails e API com Goliath, mas devem entrar outros sistemas mais para a frente.</p>

<p>Uma das coisas que pensei em fazer foi compartilhar modelos entre os sistemas Ruby. Quando eu ainda estava na WebCo, tínhamos tentado fazer algo semelhante usando submódulos do Git, sem muito sucesso. Lembre-se que naquela época não existia o Bundler. E foi justamente o Bundler que permitiu fazer esse compartilhamento de forma muito simples, como você pode conferir abaixo.</p>

<h3>Criando o repositório de modelos</h3>

<p>O primeiro passo foi definir o repositório de modelos que seria compartilhado entre os sistemas. No Bundler, todos os projetos precisam ter um gemspec, que é utilizado para <a href="http://simplesideias.com.br/criando-sua-propria-rubygem/">empacotar uma biblioteca como RubyGem</a>. No meu projeto, criei um arquivo chamado <code>presentta-models.gemspec</code> que tem o seguinte conteúdo.</p>

<pre class="ruby"><code><span class="co1"># -*- encoding: utf-8 -*-</span>
$:.<span class="me1">push</span> <span class="kw4">File</span>.<span class="me1">expand_path</span><span class="br0">&#40;</span><span class="st0">&quot;../lib&quot;</span>, <span class="kw2">__FILE__</span><span class="br0">&#41;</span>
<span class="kw3">require</span> <span class="st0">&quot;presentta/models/version&quot;</span>
&nbsp;
<span class="re2">Gem::Specification</span>.<span class="me1">new</span> <span class="kw1">do</span> |s|
  s.<span class="me1">name</span>        = <span class="st0">&quot;presentta-models&quot;</span>
  s.<span class="me1">version</span>     = <span class="re2">Presentta::Models::Version::STRING</span>
  s.<span class="me1">platform</span>    = <span class="re2">Gem::Platform::RUBY</span>
  s.<span class="me1">authors</span>     = <span class="br0">&#91;</span><span class="st0">&quot;Nando Vieira&quot;</span><span class="br0">&#93;</span>
  s.<span class="me1">email</span>       = <span class="br0">&#91;</span><span class="st0">&quot;fnando.vieira@gmail.com&quot;</span><span class="br0">&#93;</span>
  s.<span class="me1">homepage</span>    = <span class="st0">&quot;http://rubygems.org/gems/presentta-models&quot;</span>
  s.<span class="me1">summary</span>     = <span class="st0">&quot;Share ActiveRecord models between Presentta applications.&quot;</span>
  s.<span class="me1">description</span> = s.<span class="me1">summary</span>
&nbsp;
  s.<span class="me1">files</span>         = <span class="st0">`git ls-files`</span>.<span class="kw3">split</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>
  s.<span class="me1">test_files</span>    = <span class="st0">`git ls-files -- {test,spec,features}/*`</span>.<span class="kw3">split</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>
  s.<span class="me1">executables</span>   = <span class="st0">`git ls-files -- bin/*`</span>.<span class="kw3">split</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>.<span class="me1">map</span><span class="br0">&#123;</span> |f| <span class="kw4">File</span>.<span class="me1">basename</span><span class="br0">&#40;</span>f<span class="br0">&#41;</span> <span class="br0">&#125;</span>
  s.<span class="me1">require_paths</span> = <span class="br0">&#91;</span><span class="st0">&quot;lib&quot;</span><span class="br0">&#93;</span>
&nbsp;
  s.<span class="me1">add_dependency</span> <span class="st0">&quot;mysql2&quot;</span>, <span class="st0">&quot;~&gt; 0.3&quot;</span>
  s.<span class="me1">add_dependency</span> <span class="st0">&quot;activerecord&quot;</span>, <span class="st0">&quot;~&gt; 3.2&quot;</span>
  s.<span class="me1">add_dependency</span> <span class="st0">&quot;simple_auth&quot;</span>, <span class="st0">&quot;~&gt; 1.4&quot;</span>
  s.<span class="me1">add_dependency</span> <span class="st0">&quot;validators&quot;</span>, <span class="st0">&quot;~&gt; 1.0&quot;</span>
  s.<span class="me1">add_dependency</span> <span class="st0">&quot;permalink&quot;</span>, <span class="st0">&quot;~&gt; 1.2&quot;</span>
  s.<span class="me1">add_dependency</span> <span class="st0">&quot;defaults&quot;</span>, <span class="st0">&quot;~&gt; 0.1&quot;</span>
&nbsp;
  s.<span class="me1">add_development_dependency</span> <span class="st0">&quot;rake&quot;</span>, <span class="st0">&quot;~&gt; 0.9&quot;</span>
  s.<span class="me1">add_development_dependency</span> <span class="st0">&quot;rspec&quot;</span>, <span class="st0">&quot;~&gt; 2.8&quot;</span>
  s.<span class="me1">add_development_dependency</span> <span class="st0">&quot;factory_girl&quot;</span>
  s.<span class="me1">add_development_dependency</span> <span class="st0">&quot;factory_girl-preload&quot;</span>
<span class="kw1">end</span></code></pre>

<p>Esse arquivo contém todas as dependências, como plugins do ActiveRecord e bibliotecas que serão usadas nos testes dos modelos.</p>

<p>Você também vai precisar definir o seu <code>Gemfile</code>. Neste caso, nós iremos utilizar as mesmas dependências definidas no arquivo gemspec.</p>

<pre class="ruby"><code>source <span class="re3">:rubygems</span>
gemspec</code></pre>

<p>O arquivo que irá iniciar a biblioteca é o <code>lib/presentta/models.rb</code>. Nele, além de carregar todas as gems que vou usar, ainda defino as configurações do ActiveRecord. Abaixo você pode conferir apenas as partes importantes.</p>

<pre class="ruby"><code><span class="kw3">require</span> <span class="st0">&quot;mysql2&quot;</span>
<span class="kw3">require</span> <span class="st0">&quot;active_record&quot;</span>
&nbsp;
<span class="kw3">require</span> <span class="st0">&quot;presentta/models/user&quot;</span>
<span class="kw3">require</span> <span class="st0">&quot;presentta/models/courses&quot;</span>
<span class="kw3">require</span> <span class="st0">&quot;presentta/models/your_model_here&quot;</span>
&nbsp;
<span class="re2">ActiveRecord::Base</span>.<span class="me1">timestamped_migrations</span> = <span class="kw2">false</span>
<span class="re2">ActiveRecord::Base</span>.<span class="me1">attr_accessible</span><span class="br0">&#40;</span><span class="kw2">nil</span><span class="br0">&#41;</span>
<span class="re2">ActiveRecord::Migrator</span>.<span class="me1">migrations_paths</span> = <span class="kw4">File</span>.<span class="me1">expand_path</span><span class="br0">&#40;</span><span class="st0">&quot;../models/migrations&quot;</span>, <span class="kw2">__FILE__</span><span class="br0">&#41;</span>
&nbsp;
<span class="kw1">module</span> Presentta
  <span class="kw1">module</span> Models
    <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">connect_with</span><span class="br0">&#40;</span>file, environment<span class="br0">&#41;</span>
      <span class="kw3">fail</span> <span class="st0">&quot;#{file.inspect} should be a configuration file&quot;</span> <span class="kw1">unless</span> file &amp;&amp; <span class="kw4">File</span>.<span class="me1">exist</span>?<span class="br0">&#40;</span>file<span class="br0">&#41;</span>
      <span class="re2">ActiveRecord::Base</span>.<span class="me1">configurations</span> = <span class="kw4">YAML</span>.<span class="me1">load_file</span><span class="br0">&#40;</span>file<span class="br0">&#41;</span>
      <span class="re2">ActiveRecord::Base</span>.<span class="me1">establish_connection</span><span class="br0">&#40;</span>environment<span class="br0">&#41;</span>
    <span class="kw1">end</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>Como será preciso estabelecer a conexão de diferentes lugares, preferi centralizar esta conexão à partir do método <code>Presentta::Models.connect_with</code>. Com isso já é possível configurar, por exemplo, as rake tasks que irão executar as migrações.</p>

<p>Uma das premissas do repositório de modelos era ter um modo de executar as <em>migrations</em>. Para fazer isso, criei um diretório <code>lib/presentta/models/migrations</code>, que tem todas as migrações, como <code>001_create_users.rb</code>. Perceba que não estou usando o timestamp; como não vou usar os geradores do Rails, é mais prático escrever <code>001_create_users.rb</code> que <code>20120306135200_create_users.rb</code>, alteração realizada quando utilizei a configuração <code>ActiveRecord::Base.timestamped_migrations = false</code>.</p>

<p>O arquivo <code>lib/presentta/models/rake.rb</code> será carregado tanto pelo arquivo <code>Rakefile</code> do repositório de modelos, quando pelo aplicativo Rails.</p>

<pre class="ruby"><code>ENV<span class="br0">&#91;</span><span class="st0">&quot;RAILS_ENV&quot;</span><span class="br0">&#93;</span> ||= <span class="st0">&quot;development&quot;</span>
&nbsp;
<span class="kw3">require</span> <span class="st0">&quot;presentta/models&quot;</span>
<span class="kw3">require</span> <span class="st0">&quot;rails&quot;</span>
&nbsp;
<span class="re2">Presentta::Models</span>.<span class="me1">connect_with</span><span class="br0">&#40;</span>ENV<span class="br0">&#91;</span><span class="st0">&quot;DATABASE_CONFIG&quot;</span><span class="br0">&#93;</span>, Rails.<span class="me1">env</span><span class="br0">&#41;</span>
<span class="kw3">require</span> <span class="st0">&quot;active_record/railtie&quot;</span>
<span class="kw3">load</span> <span class="st0">&quot;active_record/railties/databases.rake&quot;</span>
&nbsp;
task<span class="br0">&#40;</span><span class="re3">:environment</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="br0">&#125;</span>
&nbsp;
namespace <span class="re3">:db</span> <span class="kw1">do</span>
  task<span class="br0">&#40;</span><span class="re3">:load_config</span><span class="br0">&#41;</span>.<span class="me1">clear_prerequisites</span>.<span class="me1">clear_actions</span>
<span class="kw1">end</span></code></pre>

<p>Duas coisas que você deve notar aqui. Para poder usar as rake tasks de fora do Rails, precisei definir a tarefa <code>environment</code> para um bloco que não faz nada. No Rails, ela existe e é responsável por inicializar o ambiente. Outra coisa importante é que removi a tarefa <code>db:load_config</code> que, basicamente, define o diretório de migrações e o arquivo de configuração. Mas atenção: ao sobrescrever esta tarefa, as migrações de Rails engines não serão detectadas e, por este motivo, devem ser copiadas para o diretório <code>lib/presentta/models/migrations</code>. No meu caso não uso nenhuma engine, então isso não é um problema.</p>

<p>Agora, no arquivo <code>Rakefile</code> da raíz do repositório de modelos, é preciso carregar as rake tasks do banco de dados. Como uso RSpec, também já coloquei sua tarefa neste arquivo.</p>

<pre class="ruby"><code><span class="kw3">require</span> <span class="st0">&quot;rspec/core/rake_task&quot;</span>
<span class="re2">RSpec::Core::RakeTask</span>.<span class="me1">new</span>
&nbsp;
ENV<span class="br0">&#91;</span><span class="st0">&quot;DATABASE_CONFIG&quot;</span><span class="br0">&#93;</span> = <span class="kw4">File</span>.<span class="me1">expand_path</span><span class="br0">&#40;</span><span class="st0">&quot;../database.yml&quot;</span>, <span class="kw2">__FILE__</span><span class="br0">&#41;</span>
<span class="kw3">require</span> <span class="st0">&quot;presentta/models/rake&quot;</span></code></pre>

<p>O arquivo de configuração do ActiveRecord é lido à partir da variável de ambiente <code>DATABASE_CONFIG</code>, que aqui definimos para um arquivo na raíz do repositório. Nada diferente do que você já está acostumado a ver no Rails.</p>

<pre class="text"><code>defaults: &amp;DEFAULTS
  adapter: mysql2
  encoding: utf8
  reconnect: true
  pool: 5
  host: localhost
  username: root
  password:
&nbsp;
development:
  &lt;&lt;: *DEFAULTS
  database: presentta_development
&nbsp;
test:
  &lt;&lt;: *DEFAULTS
  database: presentta_test</code></pre>

<p>Para listar todas as tarefas disponíveis, execute o comando <code>rake -T db</code>.</p>

<pre class="text"><code>$ rake -T db
rake db:create          # Create the database from config/database.yml for the current Rails.en...
rake db:drop            # Drops the database for the current Rails.env (use db:drop:all to drop...
rake db:fixtures:load   # Load fixtures into the current environment's database.
rake db:migrate         # Migrate the database (options: VERSION=x, VERBOSE=false).
rake db:migrate:status  # Display status of migrations
rake db:rollback        # Rolls the schema back to the previous version (specify steps w/ STEP=n).
rake db:schema:dump     # Create a db/schema.rb file that can be portably used against any DB s...
rake db:schema:load     # Load a schema.rb file into the database
rake db:seed            # Load the seed data from db/seeds.rb
rake db:setup           # Create the database, load the schema, and initialize with the seed da...
rake db:structure:dump  # Dump the database structure to db/structure.sql. Specify another file...
rake db:version         # Retrieves the current schema version number</code></pre>

<p>Se tudo estiver configurando de forma correta, você conseguirá ver qual a versão do seu banco de dados executando o comando <code>rake db:version</code>.</p>

<pre class="text"><code>$ rake db:version
Current version: 7</code></pre>

<p>Do lado do repositório de modelos, você não precisa fazer mais nada!</p>

<h3>Configurando o Rails</h3>

<p>Agora você precisa configurar sua aplicação Rails para utilizar o repositório de modelos. O primeiro passo é configurar o arquivo <code>Gemfile</code>. Idealmente, seria interessante apontar os ambientes de desenvolvimento e teste para o repositório local, e o ambiente de produção para o repositório do <a href="http://codeplane.com.br/?simplesideias-shared-models" rel="external">Codeplane</a>. Mas isso não é possível no Bundler, embora seja uma funcionalidade prevista para o release 1.1 (estou usando o Bundler 1.1 RC7 e ainda não é possível). Como ainda estou na fase de desenvolvimento, vou deixar para me preocupar com isso quando chegar a hora. Por enquanto, meu arquivo Gemfile é algo como isto:</p>

<pre class="ruby"><code>source <span class="re3">:rubygems</span>
&nbsp;
gem <span class="st0">&quot;rails&quot;</span>                   , <span class="st0">&quot;3.2.2&quot;</span>
gem <span class="st0">&quot;responders&quot;</span>              , <span class="st0">&quot;~&gt; 0.8&quot;</span>
gem <span class="st0">&quot;simple_form&quot;</span>             , <span class="st0">&quot;~&gt; 2.0&quot;</span>
gem <span class="st0">&quot;simple_presenter&quot;</span>        , <span class="st0">&quot;~&gt; 0.1&quot;</span>
gem <span class="st0">&quot;swiss_knife&quot;</span>             , <span class="st0">&quot;~&gt; 1.0&quot;</span>
&nbsp;
group <span class="re3">:development</span>, <span class="re3">:test</span> <span class="kw1">do</span>
  gem <span class="st0">&quot;presentta-models&quot;</span>      , <span class="re3">:path</span> =&gt; <span class="st0">&quot;~/Sites/presentta-models&quot;</span>
  gem <span class="st0">&quot;thin&quot;</span>                  , <span class="st0">&quot;~&gt; 1.3&quot;</span>
  gem <span class="st0">&quot;awesome_print&quot;</span>         , <span class="re3">:require</span> =&gt; <span class="kw2">false</span>
  gem <span class="st0">&quot;pry&quot;</span>                   , <span class="re3">:require</span> =&gt; <span class="kw2">false</span>
  gem <span class="st0">&quot;rspec-rails&quot;</span>           , <span class="st0">&quot;~&gt; 2.7&quot;</span>
<span class="kw1">end</span>
&nbsp;
group <span class="re3">:test</span> <span class="kw1">do</span>
  gem <span class="st0">&quot;factory_girl&quot;</span>          , <span class="st0">&quot;~&gt; 2.2&quot;</span>
  gem <span class="st0">&quot;factory_girl-preload&quot;</span>  , <span class="st0">&quot;~&gt; 1.0&quot;</span>
  gem <span class="st0">&quot;test_notifier&quot;</span>         , <span class="st0">&quot;~&gt; 0.4&quot;</span>, <span class="re3">:require</span> =&gt; <span class="st0">&quot;test_notifier/runner/rspec&quot;</span>
  gem <span class="st0">&quot;spork&quot;</span>                 , <span class="st0">&quot;~&gt; 0.9.0&quot;</span>
  gem <span class="st0">&quot;capybara&quot;</span>              , <span class="st0">&quot;~&gt; 1.1&quot;</span>
<span class="kw1">end</span></code></pre>

<p>O seu arquivo <code>config/application.rb</code> também precisará ser modificado. A parte importante aqui são os arquivos que o Rails irá carregar ou, melhor dizendo, <strong>não</strong> irá carregar, como o arquivo <code>active_record/railtie</code>.</p>

<pre class="ruby"><code><span class="kw3">require</span> <span class="kw4">File</span>.<span class="me1">expand_path</span><span class="br0">&#40;</span><span class="st0">&quot;../boot&quot;</span>, <span class="kw2">__FILE__</span><span class="br0">&#41;</span>
&nbsp;
<span class="kw3">require</span> <span class="st0">&quot;rails&quot;</span>
<span class="kw3">require</span> <span class="st0">&quot;action_controller/railtie&quot;</span>
<span class="kw3">require</span> <span class="st0">&quot;action_mailer/railtie&quot;</span>
<span class="kw3">require</span> <span class="st0">&quot;active_resource/railtie&quot;</span>
&nbsp;
Bundler.<span class="kw3">require</span><span class="br0">&#40;</span><span class="re3">:default</span>, Rails.<span class="me1">env</span><span class="br0">&#41;</span> <span class="kw1">if</span> <span class="kw1">defined</span>?<span class="br0">&#40;</span>Bundler<span class="br0">&#41;</span>
&nbsp;
<span class="kw1">module</span> Presentta
  <span class="kw1">class</span> Application &lt; <span class="re2">Rails::Application</span>
    config.<span class="me1">time_zone</span> = <span class="st0">&quot;Brasilia&quot;</span>
    config.<span class="me1">i18n</span>.<span class="me1">load_path</span> += <span class="kw4">Dir</span><span class="br0">&#91;</span>Rails.<span class="me1">root</span>.<span class="me1">join</span><span class="br0">&#40;</span><span class="st0">&quot;config/locales/**/*.yml&quot;</span><span class="br0">&#41;</span>.<span class="me1">to_s</span><span class="br0">&#93;</span>
    config.<span class="me1">i18n</span>.<span class="me1">default_locale</span> = :<span class="st0">&quot;pt-BR&quot;</span>
    config.<span class="me1">encoding</span> = <span class="st0">&quot;utf-8&quot;</span>
    config.<span class="me1">filter_parameters</span> += <span class="br0">&#91;</span><span class="re3">:password</span><span class="br0">&#93;</span>
    config.<span class="me1">assets</span>.<span class="me1">enabled</span> = <span class="kw2">false</span>
    config.<span class="me1">generators</span>.<span class="me1">assets</span> = <span class="kw2">false</span>
    config.<span class="me1">generators</span>.<span class="me1">test_framework</span> <span class="re3">:rspec</span>, <span class="re3">:fixtures</span> =&gt; <span class="kw2">false</span>, <span class="re3">:view_specs</span> =&gt; <span class="kw2">false</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>Para estabelecer a conexão com o banco de dados, nós precisaremos utilizar o método <code>Presentta::Models.connect_with</code>. Crie um arquivo <code>config/initializers/activerecord.rb</code> com o conteúdo à seguir.</p>

<pre class="ruby"><code><span class="re2">Presentta::Models</span>.<span class="me1">connect_with</span><span class="br0">&#40;</span>
  Rails.<span class="me1">root</span>.<span class="me1">join</span><span class="br0">&#40;</span><span class="st0">&quot;config/database.yml&quot;</span><span class="br0">&#41;</span>.<span class="me1">to_s</span>,
  Rails.<span class="me1">env</span>
<span class="br0">&#41;</span>
&nbsp;
<span class="kw3">require</span> <span class="st0">&quot;active_record/railtie&quot;</span></code></pre>

<p>Finalmente, é preciso carregar as rake tasks. Crie o arquivo <code>lib/tasks/db.rake</code>.</p>

<pre class="ruby"><code>ENV<span class="br0">&#91;</span><span class="st0">&quot;DATABASE_CONFIG&quot;</span><span class="br0">&#93;</span> = <span class="kw4">File</span>.<span class="me1">expand_path</span><span class="br0">&#40;</span><span class="st0">&quot;../../../config/database.yml&quot;</span>, <span class="kw2">__FILE__</span><span class="br0">&#41;</span>
<span class="kw3">require</span> <span class="st0">&quot;presentta/models/rake&quot;</span></code></pre>

<p>Assim como no repositório de modelos, você pode ver as rake tasks disponíveis com o comando <code>rake -T db</code>.</p>

<h3>Configurando outros apps</h3>

<p>Seus outros aplicativos como Goliath e Sinatra também pode usar os modelos. Para isso, além de definir o repositório de modelos no Gemfile, você também precisará fazer a conexão usando as linhas à seguir.</p>

<pre class="ruby"><code><span class="kw3">require</span> <span class="st0">&quot;presentta-models&quot;</span>
&nbsp;
<span class="re2">Presentta::Models</span>.<span class="me1">connect_with</span><span class="br0">&#40;</span>
  <span class="kw4">File</span>.<span class="me1">expand_path</span><span class="br0">&#40;</span><span class="st0">&quot;../database.yml&quot;</span>, <span class="kw2">__FILE__</span><span class="br0">&#41;</span>,
  ENV<span class="br0">&#91;</span><span class="st0">&quot;RACK_ENV&quot;</span><span class="br0">&#93;</span>
<span class="br0">&#41;</span></code></pre>

<img src="http://feeds.feedburner.com/~r/simplesideias/~4/z8eJEFn8zCs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/usando-modelos-activerecord-entre-projetos-diferentes/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://simplesideias.com.br/usando-modelos-activerecord-entre-projetos-diferentes/</feedburner:origLink></item>
		<item>
		<title>Comparando os meios de pagamento: PayPal, PagSeguro e MoIP</title>
		<link>http://feedproxy.google.com/~r/simplesideias/~3/c2QfU4zjuWE/</link>
		<comments>http://simplesideias.com.br/comparando-os-meios-de-pagamento-paypal-pagseguro-e-moip/#comments</comments>
		<pubDate>Tue, 28 Feb 2012 16:32:40 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
				<category><![CDATA[Produtos & Serviços]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=754</guid>
		<description><![CDATA[Quando alguém decide procurar algum serviço para fazer este papel, é meio óbvio que você quer algo simples e que funcione. Além disso, você quer fazer negócios com uma empresa que considere o vendedor como um parceiro. O mercado brasileiro possui algumas alternativas para quem precisa fazer cobranças na Internet mas, infelizmente, nenhuma delas consegue [...]]]></description>
			<content:encoded><![CDATA[<img src="http://m.simplesideias.com.br/credit-card.jpg" alt="" class="align-right">
<p>Quando alguém decide procurar algum serviço para fazer este papel, é meio óbvio que você quer algo simples e que funcione. Além disso, você quer fazer negócios com uma empresa que considere o vendedor como um parceiro. O mercado brasileiro possui algumas alternativas para quem precisa fazer cobranças na Internet mas, infelizmente, nenhuma delas consegue preencher todos esses requisitos. Para ser considerado um bom serviço, é preciso que ele atue em várias frentes de forma competente.</p>

<p>Junto ao desenvolvedor, fazendo um serviço fácil de usar e com uma documentação que pode ser facilmente acessada, com vários exemplos.</p>

<p>Junto ao vendedor, sendo flexível e provendo o máximo de informações relativas ao pagamento, sempre de forma descomplicada. O serviço de cobrança também deve considerar o vendedor como um parceiro e, em um primeiro momento, estar sempre do seu lado. Oferecer serviços como cobrança recorrente e checkout de pagamentos através de formulários HTML e API também é muito importante.</p>

<p>Junto ao comprador, oferecendo uma interface realmente simples de usar, que funcione em diversos navegadores e dispositivos diferentes com mobiles e tablets.</p>

<p>Em todas as frentes uma coisa extremamente importante é ter um excelente serviço de atendimento ao cliente. Fóruns, chats, suporte através de helpdesk e blog posts. São inúmeras as possibilidades mas, independente dos canais escolhidos, o atendimento deve ser rápido. <strong>Muito rápido</strong>.</p>

<h3>As alternativas disponíveis no Brasil</h3>

<p>O Brasil possui inúmeros serviços de pagamento como PagSeguro, MoIP e PayPal. Nesta comparação, você poderá ler as minhas experiências (não muito boas) com estes serviços. Existem outros meios de pagamento como MercadoPago e Pagamento Digital, mas nunca usei nenhum deles e, por este motivo, ficaram de fora desta comparação.</p>

<h4>PagSeguro</h4>

<img src="http://m.simplesideias.com.br/pagseguro.png" alt="PagSeguro" class="no-border align-right">

<p>Em 2007 o UOL comprou a BRPay, que veio a se tornar o PagSeguro que conhecemos. Um dos principais meios de pagamentos da categoria, foi por muito tempo um dos serviços que mais deixou a desejar. Isso está mudando agora que foi lançada a nova versão da API, embora ainda não possua uma série de funcionalidades disponíveis em outros serviços como MoIP e PayPal.</p>

<p>Características:</p>

<ul>
<li>Tarifa de cartão de crédito: 6,4% + R$ 0,40</li>
<li>Demais tarifas: 2,9% + R$ 0,40</li>
<li>Tarifa de parcelamento: 1,99%/mês, cobrada do comprador ou do vendedor</li>
<li>Cobrança por formulário HTML ou e-mail</li>
</ul>

<p>Vantagens:</p>

<ul>
<li>Possui a marca UOL, muito fortalecida no mercado.</li>
<li>A nova API é muito fácil de usar.</li>
<li>Oferece checkout apenas por formulários HTML ou API.</li>
<li>A interface é simples e bastante funcional.</li>
<li>Envia dados completos do pedido na notificação de pagamento.</li>
</ul>

<p>Desvantagens:</p>

<ul>
<li>Cobrança só pode ser feita de brasileiros.</li>
<li>A URL de retorno é global. Se você possui mais de um produto, terá sempre a mesma página de retorno. Para definir uma URL por transação, o pedido deve ser feito através da API.</li>
<li>Não possui cobrança recorrente.</li>
<li>Atendimento lento, que demora a entender o problema, mesmo eu tendo enviado um screencast. Já tive ticket aberto que demorou 2 semanas para ser respondido.</li>
<li>Saque só pode ser feito após 14 dias do pagamento.</li>
<li>O e-mail enviado ao vendedor confirmando a compra é incompleto.</li>
<li>O painel do comprador limita as buscas em 120 dias.</li>
<li>Não possui ambiente de testes.</li>
<li>A análise do cartão de crédito demora, e muitas vezes é cancelada. Em uma nova tentativa, o mesmo cartão é aprovado.</li>
</ul>

<h4>MoIP</h4>

<img src="http://m.simplesideias.com.br/moip.png" alt="MoIP" class="no-border align-right">

<p>O iG também decidiu pegar uma fatia do mercado que movimentou quase R$20 bilhões em 2011. Para isso comprou o MoIP, investida pela Ideiasnet. O serviço possui muitas funcionalidades como cobrança através da API e cobrança recorrente. Apontado por muitos com a melhor alternativa, só tive experiências negativas no pouco tempo que usei. Possui uma documentação espalhada e difícil de encontrar, uma API confusa e um suporte lento.</p>

<p>Além disso, o site de desenvolvedores <a href="https://skitch.com/fnando/8ggu4/twitter-moip-labs-fnando-realmente-nosso-bl-" rel="external">estava infectado com um malware</a> e aparentemente eles não estavam sabendo de nada.

<p>Características:</p>

<ul>
<li>Tarifa de cartão de crédito: 7,4% + R$ 0,39.</li>
<li>Demais tarifas: 2,9% + R$ 0,39.</li>
<li>Tarifa de parcelamento: 1,99%/mês, cobrada do comprador ou do vendedor.</li>
<li>Cobrança por formulário HTML, e-mail e API.</li>
</ul>

<p>Vantagens:</p>

<ul>
<li>Diversas modalidades de cobrança: recorrente, e-mail, formulário HTML e API.</li>
<li>É possível fazer muitas coisas pela API.</li>
<li>Possui ambiente de testes.</li>
</ul>

<p>Desvantagens:</p>

<ul>
<li>Cobrança só pode ser feita de brasileiros.</li>
<li>Os dados completos do pedido só podem ser acessados quando o pedido foi gerado à partir da API.</li>
<li>Atendimento lento. Demorou 8 dias para responder um ticket, relacionado a uma cobrança debitada do cliente, mas que está como cancelada no MoIP. Este ticket ainda não foi resolvido.</li>
<li>A cobrança com formulário HTML envia dados sem criptografia.</li>
<li>A cobrança recorrente é um envio de e-mail dizendo para o comprador efetuar o pagamento.</li>
<li>A interface é confusa.</li>
<li>Saque só pode ser feito após 14 dias do pagamento.</li>
<li>O painel do vendedor possui erros constantes, como páginas não encontradas.</li>
<li>A aprovação do pagamento com cartão de crédito demora.</li>
</ul>

<h4>PayPal</h4>

<img src="http://m.simplesideias.com.br/paypal.png" alt="PayPal" class="align-right no-border">

<p>Com a entrada do PayPal no mercado brasileiro, as nossas esperanças de um serviço melhor foram renovadas. Ledo engano. O PayPal é tão ruim quanto os outros serviços, com um agravante: é conhecido por cancelar e bloquear contas, mesmo quando estas estão de acordo com os termos de uso.</p>

<p>Características:</p>

<ul>
<li>Tarifa de cartão de crédito: 6,4% + R$0,60.</li>
<li>Tarifa de parcelamento variável de acordo com o número de parcelas.</li>
<li>Cobrança por e-mail, formulário HTML e API.</li>
</ul>

<p>Vantagens:</p>

<ul>
<li>Possui presença mundial.</li>
<li>Permite a cobrança de brasileiros e estrangeiros.</li>
<li>Possui ambiente de testes.</li>
<li>Possui cobrança recorrente.</li>
<li>O saque pode ser feito a qualquer momento.</li>
</ul>

<p>Desvantagens:</p>

<ul>
<li>Ambiente de testes confuso de configurar com contas brasileiras.</li>
<li>Clientes brasileiros só podem ser cobrados em Real (restrição do governo), o que exige uma lógica diferente para cobranças nacionais e internacionais.</li>
<li>Não possui boleto bancário.</li>
<li>Taxas mais altas que os concorrentes para valores baixos.</li>
<li>Não considera o vendedor como um parceiro.</li>
<li>Não funciona direito com diversos países (Alemanha, por exemplo).</li>
<li>Diversos serviços oferecidos nos EUA não estão disponíveis no Brasil.</li>
</ul>

<h3>Finalizando</h3>

<p>Atualmente, não existe nenhum meio de pagamento realmente bom. PayPal consegue ser o menos pior, embora você tenha que conviver com o risco do congelamento de sua conta, sem maiores explicações. Mas mesmo com todos esses poréns, o PayPal ainda é a melhor solução se você precisa fazer cobranças nacionais e internacionais, principalmente para serviços digitais.</p>

<p>Minha escolha para cobrança apenas de brasileiros é o PagSeguro. Mesmo sendo mais incompleto que o MoIP, a nova versão é mais simples e fácil de implementar.</p><img src="http://feeds.feedburner.com/~r/simplesideias/~4/c2QfU4zjuWE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/comparando-os-meios-de-pagamento-paypal-pagseguro-e-moip/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		<feedburner:origLink>http://simplesideias.com.br/comparando-os-meios-de-pagamento-paypal-pagseguro-e-moip/</feedburner:origLink></item>
		<item>
		<title>Conheça o Pingd</title>
		<link>http://feedproxy.google.com/~r/simplesideias/~3/iHshbyGgVig/</link>
		<comments>http://simplesideias.com.br/conheca-o-pingd/#comments</comments>
		<pubDate>Wed, 15 Feb 2012 12:18:58 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Produtos & Serviços]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=747</guid>
		<description><![CDATA[O Pingd é o novo serviço que eu irei desenvolver na Hellobits. sua ideia principal é oferecer uma API unificada dos diversos serviços de pagamentos disponíveis no Brasil. Em vez de implementar e ter que lidar com as diferenças de cada serviço manualmente, o Pingd irá normalizar todas as notificações de pagamento do PayPal, PagSeguro [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://m.simplesideias.com.br/pingd.png" class="align-right no-border"> O <a rel="external" href="http://pingd.com.br/?simplesideias-pingd">Pingd</a> é o novo serviço que eu irei desenvolver na <a rel href="http://hellobits.com/?simplesideias-pingd">Hellobits</a>. sua ideia principal é oferecer uma API unificada dos diversos serviços de pagamentos disponíveis no Brasil. Em vez de implementar e ter que lidar com as diferenças de cada serviço manualmente, o Pingd irá normalizar todas as notificações de pagamento do PayPal, PagSeguro e MoIP (outros serviços poderão ser adicionados) em uma única API. Assim, você só precisará implementar a API do Pingd e poderá receber pagamentos diferentes &#034;automagicamente&#034;.</p>

<p>Em uma segunda fase, será possível utilizar uma interface web para consultar as transações de todos os serviços, além de poder gerar os formulários de cobrança dos serviços de pagamento através do próprio Pingd. Assim, você não precisa se preocupar em montar formulários diferentes para o PagSeguro, PayPal e MoIP, ter que lidar com encoding, nem outros problemas que já estamos cansados de enfrentar.</p>

<p>Quer saber de uma outra coisa legal? Você poderá <strong>acompanhar o desenvolvimento do produto</strong> em tempo real.
Irei criar este produto em uma espécie de &#034;workshop&#034; online, sem data de término, onde todos os inscritos poderão assistir o desenvolvimento do produto em todas as etapas, passando pela concepção, design, desenvolvimento e deployment.</p>

<p>Para ser avisado quando o &#034;workshop&#034; for lançado, acesse o site <a href="http://howtocode.com.br/?simplesideias-pingd">howtocode.com.br</a> e se inscreva na newsletter.</p>

<p>A ideia não é revolucionária, mas lembre-se que bons produtos são aqueles que vem para resolver os seus próprios problemas! ;)</p><img src="http://feeds.feedburner.com/~r/simplesideias/~4/iHshbyGgVig" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/conheca-o-pingd/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		<feedburner:origLink>http://simplesideias.com.br/conheca-o-pingd/</feedburner:origLink></item>
		<item>
		<title>Configurando Ruby, Rails, MySQL e Git no Windows</title>
		<link>http://feedproxy.google.com/~r/simplesideias/~3/P6an7p_--l4/</link>
		<comments>http://simplesideias.com.br/configurando-ruby-rails-mysql-e-git-no-windows/#comments</comments>
		<pubDate>Tue, 07 Feb 2012 18:54:42 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
				<category><![CDATA[Git]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=743</guid>
		<description><![CDATA[Configurar o ambiente de desenvolvimento no Windows não é tarefa das mais fáceis. Embora exista o RubyInstaller e o RailsInstaller, existem muitos detalhes que não são tão simples para quem está começando. Um outro problema é que o RailsInstaller não vem com o MySQL instalado, o que não adianta muito e, por isso, vamos configurar [...]]]></description>
			<content:encoded><![CDATA[<p>Configurar o ambiente de desenvolvimento no Windows não é tarefa das mais fáceis.
Embora exista o <a rel="external" href="http://rubyinstaller.org">RubyInstaller</a> e o <a rel="external"  href="http://railsinstaller.org">RailsInstaller</a>,
existem muitos detalhes que não são tão simples para quem está começando. Um outro problema é que o RailsInstaller não vem com o MySQL instalado, o que não adianta muito e, por isso, vamos configurar manualmente.</p>

<p>Neste artigo, você verá um passo-a-passo de como instalar e configurar o ambiente de desenvolvimento no Windows com Ruby 1.9.3-p0 e Rails 3.2.1, MySQL e Git.</p>

<h3>Instalando o Ruby</h3>

<p>O primeiro passo é instalar o Ruby. Isso pode ser feito com o <a rel="external"  href="http://rubyinstaller.org">RubyInstaller</a>, mantido pelo <a rel="external" href="http://blog.mmediasys.com/">Luis Lavena</a>. Faça o download do instalador Ruby 1.9.3-p0.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/ruby-installer-site.png" alt="Página de download do RubyInstaller"></p>

<p>Assim que o download for concluído, execute-o para iniciar a instalação. Siga os passos apresentados pelo instalador e não deixe de marcar a opção &#034;Add Ruby executables to your PATH&#034;.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/ruby-installer-configuration.png" alt="Configuração do RubyInstaller"></p>

<p>O Ruby já está instalado. Para se certificar de que ele está funcionando, abra o seu terminal. Para isso, digite &#034;powershell&#034; no menu Windows e execute o programa &#034;Windows PowerShell&#034;.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/windows-7-menu.png" alt="Executando o PowerShell"></p>

<p>No terminal, digite o comando <code>ruby -v</code>. Isso deverá exibir a versão instalada do Ruby.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/ruby-version.png" alt="Versão do Ruby"></p>

<p>Nós também iremos precisar do Ruby DevKit, um instalador disponibilizado no próprio site do RubyInstaller e que permitirá instalar extensões nativas como <a rel="external" href="http://rubygems.org/gems/json">json</a> e <a href="http://rubygems.org/gems/mysql2">mysql2</a>. Na <a rel="external" href="http://rubyinstaller.org/downloads">página de downloads</a> do Ruby Installer, faça o download do arquivo <code>DevKit-tdm-32-4.5.2-20111229-1559-sfx.exe</code>.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/ruby-devkit.png" alt="Download do Ruby DevKit"></p>

<p>Assim que o download for concluído, você precisará extrair os arquivos para o diretório <code>C:\Ruby193\devkit</code>. Esse diretório não existe, então você precisará criá-lo.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/ruby-devkit-extract.png" alt="Extraindo os arquivos do Ruby DevKit"></p>

<p>Agora, volte ao terminal. Você precisará instalar o DevKit na instalação atual do Ruby. Para isso, digite o comando <code>cd C:\Ruby193\devkit</code> para ir ao diretório que você acabou de extrair. Execute o comando <code>ruby dk.rb init</code> e depois <code>ruby dk.rb install</code>.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/ruby-devkit-install.png" alt="Instalando o Ruby DevKit"></p>

<p>Pronto! Agora o seu Ruby já está instalado!</p>

<h3>Instalando o MySQL</h3>

<p>Antes de instalar o Rails, você precisará instalar e configurar o MySQL. Para fazer isso, acesse a <a rel="external" href="http://mysql.com/downloads/mysql/">página de downloads</a> e baixe o instalador. Assim que o download for concluído, inicie a instalação.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/mysql-installer.png" alt="Instalador do MySQL"></p>

<p>Quando for perguntado sobre o tipo de instalação, escolha &#034;Complete&#034;. Clique em &#034;Install&#034;.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/mysql-setup-type.png" alt="Definindo o tipo de instalação"></p>

<p>Assim que a instalação finalizar, marque a opção &#034;Launch the MySQL Instance Configuration Wizard&#034; para iniciar o assistente de configuração. Clique em &#034;Finish&#034;.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/mysql-finish-installation.png" alt="Tela final do instalador do MySQL"></p>

<p>No assistente de configuração, selecione a opção &#034;Detailed Configuration&#034;.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/mysql-configuration-type.png" alt="Definindo o tipo de configuração do MySQL"></p>

<p>Defina o tipo de servidor como &#034;Developer Machine&#034;.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/mysql-server-type.png" alt="Definindo o tipo de servidor"></p>

<p>Selecione a opção &#034;Multifunctional Database&#034;, que permite criar bancos de dados do tipo InnoDB e MyISAM.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/mysql-engine.png" alt="Definindo o tipo de engine"></p>

<p>O próximo passo permite definir onde os bancos de dados serão criados. Nós iremos definir um diretório diferente do padrão. Assim, quando uma nova atualização do MySQL for lançada, não perderemos os dados armazenados até então. No dropdown onde está escrito &#034;Instalation Path&#034;, escolha o diretório &#034;\Data&#34;.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/mysql-data-directory.png" alt="Definindo o diretório onde os bancos de dados serão criados"></p>

<p>Agora você precisa escolher quantas conexões concorrentes você espera. Escolha a opção &#034;Decision Support (DSS)/OLAP&#034;.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/mysql-connections.png" alt="Definindo a quantidade de conexões simultâneas"></p>

<p>Marque as opções &#034;Enable TCP/IP Networking&#034; e &#034;Enable Strict Mode&#034;.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/mysql-network.png" alt="Configurações de rede"></p>

<p>Você também pode definir qual o tipo de codificação de caracteres padrão. Escolha a opção &#034;Best Support For Multilingualism&#034;, que irá definir o UTF-8 como o tipo padrão.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/mysql-encoding.png" alt="Codificação padrão dos bancos de dados"></p>

<p>Para iniciar o MySQL automaticamente quando o Windows é iniciado, marque a opção &#034;Install As A Windows Service&#034;. Não deixe de marcar a opção &#034;Include Bin Directory in Windows PATH&#034;.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/mysql-windows-options.png" alt="Configurações de serviço do Windows"></p>

<p>Como estamos executando o MySQL em modo de desenvolvimento, você pode desmarcar a opção &#034;Modify Security Settings&#034;.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/mysql-security.png" alt="Desabilitando as configurações de segurança"></p>

<p>Agora, clique em &#034;Next&#034; e depois &#034;Execute&#034; para aplicar as configurações que acabamos de definir.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/mysql-finish.png" alt="Finalizando a instalação"></p>

<p>Pronto! Para saber se o MySQL foi corretamente instalado, abra uma nova janela do terminal e execute o comando <code>mysql --version</code>. Você deverá ver a versão do MySQL instalado.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/mysql-version.png" alt="Versão instalada do MySQL"></p>

<p>Nós ainda precisaremos configurar o Ruby com suporte ao MySQL. Para fazer isso, acesse a página de downloads do MySQL e clique no link <a rel="external" href="http://mysql.com/downloads/connector/">MySQL Connectors</a>. Você precisará da versão &#034;Connector/C (libmysql)&#034;. Na página de download, escolha a opção sem o instalador. Escolha a versão de 32-bits. Isso é necessário porque o Ruby é 32-bits e, mesmo que a instalação do MySQL tenha sido feita em 64-bits, o conector que será usado por ele deve ter a mesma arquitetura.</p>

<p>Extraia os arquivos e copie o arquivo <code>mysql-connector-c-noinstall-6.0.2-win32/lib/libmysql.dll</code> para o diretório <code>C:\Ruby193\bin</code>. Isso é necessário pois DLLs precisam estar no PATH do Windows e, o diretório <code>bin</code> do Ruby no Windows adiciona todas as dependências lá.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/libmysql.png" alt="Movendo o conector C para o diretório do Ruby"></p>

<p>Se tudo deu certo, você conseguirá usar a gem <a href="http://rubygems.org/gems/mysql2">mysql2</a> no Windows.</p>

<h3>Instalando o Ruby on Rails</h3>

<p>Agora que já temos o Ruby e o MySQL devidamente configurados, podemos instalar o <a rel="external" href="http://rubyonrails.com">Ruby on Rails</a>. Antes, vamos fazer uma pequena configuração para desabilitar a geração de documentação toda vez que uma gem for instalada. Isso não é obrigatório, mas você verá que o tempo usado para gerar a documentação é um tanto quanto longo.</p>

<p>No Windows, o arquivo de configuração do RubyGems deve ser criado em <code>C:\ProgramData\gemrc</code>. O diretório <code>C:\ProgramData</code> não é exibido por padrão, então você precisará modificar suas configurações do Windows para exibir os arquivos e diretórios ocultos.</p>

<p>Com o seu editor de textos preferido, crie o arquivo <code>C:\ProgramData\gemrc</code> com o conteúdo à seguir.</p>

<pre><code>gem: "--no-rdoc --no-ri"</code></pre>

<p>Agora volte ao seu terminal e digite o comando <code>gem install rails</code>. Isso demorar um pouco pois o Rails irá instalar todas as suas dependências.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/rails-install.png" alt="Instalando o Ruby on Rails"></p>

<p>O próximo passo é criar um novo app do Rails. Para isso, execute o comando <code>rails new hello -d mysql</code>. Por padrão, o Rails irá usar o SQLite; por isso passamos o argumento <code>-d mysql</code>.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/rails-app.png" alt="Gerando um novo app com o Ruby on Rails"></p>

<p>Se tudo der certo, seu app foi gerado e as dependências instaladas.</p>

<h3>Instalando o Git</h3>

<p>Já estamos quase no fim! Agora, vamos instalar o Git. O Git é um sistema de versionamento de arquivos que vem sendo cada vez mais utilizado. Se você ainda não conhece sobre Git, fique ligado no workshop <a rel="external" href="http://howtocode.com.br/workshops/git">Git no dia-a-dia</a>, que eu dou no <a href="http://howtocode.com.br/?simplesideias">HOWTO</a>. Veja também o screencast <a rel="external" href="http://akitaonrails.com/2010/08/17/screencast-comecando-com-git">Começando com Git</a>, publicado pelo Fabio Akita.</p>

<p>Uma das alternativas para se usar Git no Windows é usar o <a rel="external" href="http://code.google.com/p/msysgit/">msysGit</a>. Faça o download do instalador. Neste exemplo, irei utilizar a versão <code>Git-1.7.9-preview20120201.exe</code>.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/git-installer.png" alt="Instalador do Git"></p>

<p>Você terá três opções de instalação. Selecione &#034;Run Git from the Windows Command Prompt&#034;.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/git-windows-options.png" alt="Configurações do Git"></p>

<p>A próxima opção do instalador é o tipo de conversão de quebras de linha que deve ser utilizado. A menos que você saiba o que está fazendo, selecione a opção &#034;Checkout as-is, commit as-is&#034; para manter o tipo de quebra de linha presente no arquivo, sem fazer nenhuma conversão automática.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/git-line-ending.png" alt="Definindo o comportamento do Git"></p>

<p>Depois que a instalação for finalizada, inicie uma nova janela do terminal. Execute o comando <code>git --version</code> para saber qual a versão instalada.</p>

<p><img src="http://m.simplesideias.com.br/ruby-win/git-version.png" alt="Versão instalada do Git"></p>
<img src="http://feeds.feedburner.com/~r/simplesideias/~4/P6an7p_--l4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/configurando-ruby-rails-mysql-e-git-no-windows/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		<feedburner:origLink>http://simplesideias.com.br/configurando-ruby-rails-mysql-e-git-no-windows/</feedburner:origLink></item>
		<item>
		<title>Programando em ActionScript sem o Flash</title>
		<link>http://feedproxy.google.com/~r/simplesideias/~3/DhVBfc1gIxk/</link>
		<comments>http://simplesideias.com.br/programando-em-actionscript-sem-o-flash/#comments</comments>
		<pubDate>Sun, 05 Feb 2012 12:50:17 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
				<category><![CDATA[ActionScript]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=732</guid>
		<description><![CDATA[Estou refazendo a parte que faz o broadcasting de áudio e vídeo do Presentta, mas abrir o Flash e re-exportar o código-fonte para compilar o SWF estava se tornando um processo extremamente chato e demorado. Eu já tinha usado o SDK do Flex para compilar ActionScript em SWF antes. A grande vantagem é que eu [...]]]></description>
			<content:encoded><![CDATA[<p>Estou refazendo a parte que faz o broadcasting de
áudio e vídeo do Presentta, mas abrir
o Flash e re-exportar o código-fonte para compilar o SWF
estava se tornando um processo extremamente chato e demorado.</p>

<p>Eu já tinha usado o SDK do Flex para compilar ActionScript em SWF
antes. A grande vantagem é que eu posso usar apenas a linha de comando
para gerar os arquivos. Nada de uma IDE extramente lenta, como
a do Flash. Além disso, ainda posso usar o <a rel="external" href="http://rubygems.org/gems/guard">Guard</a> para compilar
automaticamente sempre que um arquivo for modificado.</p>

<h3>Instalando o Flex SDK no Mac OS X</h3>

<p>A instalação do SDK é bastante simples. Após fazer o
<a rel="external" href="http://fpdownload.adobe.com/pub/flex/sdk/builds/flex4.6/flex_sdk_4.6.0.23201_mpl.zip">download do SDK</a>,
que tem por volta de 164MB, você precisa extrair os arquivos.</p>

<pre><code>$ mkdir -p ~/local/flex
$ cd ~/local/flex
$ curl -O http://fpdownload.adobe.com/pub/flex/sdk/builds/flex4.6/flex_sdk_4.6.0.23201_mpl.zip
$ unzip flex_sdk_4.6.0.23201_mpl.zip
</code></pre>

<p>Agora, você precisa adicionar o diretório <code>~/local/flex/bin</code> ao
seu <code>$PATH</code>. Para isso, basta adicionar a linha abaixo ao arquivo
<code>~/.bash_profile</code> ou equivalente.</p>

<pre><code>$ echo 'export PATH="$HOME/local/flex/bin:$PATH"' &gt;&gt; ~/.bash_profile
</code></pre>

<p>Recarregue suas configurações com o comando <code>source ~/.bash_profile</code>. Se
tudo der certo, o comando <code>which mxmlc</code> está disponível.</p>

<pre><code>$ which mxmlc
/Users/fnando/local/flex/bin/mxmlc
</code></pre>

<h3>Compilando seu primeiro SWF</h3>

<p>Diferente do que você está acostumado, para criar SWFs você usará apenas
código ActionScript. Nada de IDE. E isso é uma coisa boa! Crie um arquivo
chamado <code>Main.as</code>. Esse arquivo será o arquivo principal, que será
equivalente ao stage principal do Flash.</p>

<pre class="actionscript"><code>package <span class="br0">&#123;</span>
  <span class="kw3">import</span> flash.<span class="me1">display</span>.<span class="me1">Sprite</span>;
&nbsp;
  <span class="kw3">public</span> <span class="kw2">class</span> Main <span class="kw3">extends</span> Sprite <span class="br0">&#123;</span>
    <span class="kw3">public</span> <span class="kw2">function</span> Main<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
      <span class="kw3">trace</span><span class="br0">&#40;</span><span class="st0">&quot;It works!&quot;</span><span class="br0">&#41;</span>;
    <span class="br0">&#125;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></code></pre>

<p>Note que o nome do arquivo deve ser igual ao nome da classe, nesse caso, <code>Main</code>.
Para compilar o arquivo <code>Main.as</code> você terá que executar o comando <code>mxmlc</code>.</p>

<pre><code>$ mxmlc -output main.swf \
      -as3 \
      -static-link-runtime-shared-libraries \
      -default-size 130 50 \
      -optimize \
      -verbose-stacktraces \
      Main.as
Loading configuration file /Users/fnando/local/flex/frameworks/flex-config.xml
/private/tmp/main.swf (592 bytes)
</code></pre>

<p>Nada muito complicado. Estamos gerando o arquivo <code>main.swf</code> à partir do
arquivo <code>Main.as</code>. O tamanho do stage será de <code>130x50</code>. É óbvio que esse exemplo,
não faz muita coisa. Se você abrir este arquivo no navegador será presenteado com
uma bela tela branca que não faz nada!</p>

<p>Para visualizar uma descrição dos parâmetros aceitos pelo comando <code>mxmlc</code>, execute
o comando abaixo.</p>

<pre><code>$ mxmlc -help details list
</code></pre>

<h3>Usando componentes</h3>

<p>Um dos problemas que tive com a compilação foi que componentes não estavam sendo renderizados.
O único modo que funcionou para mim foi exportar todos os componentes como uma biblioteca
compartilhada. Como você precisa do Flash para fazer isso, resolvi disponibilizar este arquivo em <a rel="external" href="http://f.simplesideias.com.br/components.swc">http://f.simplesideias.com.br/components.swc</a>.</p>

<p>Vamos atualizar nossa classe <code>Main</code> para adicionar um botão. Ao clicá-lo, iremos alterar seu label para &#034;Clicked&#034;.</p>

<pre class="actionscript"><code>package <span class="br0">&#123;</span>
  <span class="kw3">import</span> flash.<span class="me1">display</span>.<span class="me1">Sprite</span>;
  <span class="kw3">import</span> fl.<span class="me1">controls</span>.<span class="kw3">Button</span>;
  <span class="kw3">import</span> flash.<span class="me1">events</span>.<span class="me1">MouseEvent</span>;
&nbsp;
  <span class="kw3">public</span> <span class="kw2">class</span> Main <span class="kw3">extends</span> Sprite <span class="br0">&#123;</span>
    <span class="kw3">public</span> <span class="kw2">function</span> Main<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
      <span class="kw2">var</span> <span class="kw3">button</span>:<span class="kw3">Button</span> = <span class="kw2">new</span> <span class="kw3">Button</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
&nbsp;
      <span class="kw3">button</span>.<span class="me1">label</span> = <span class="st0">&quot;Click me!&quot;</span>;
      <span class="kw3">button</span>.<span class="me1">move</span><span class="br0">&#40;</span><span class="nu0">15</span>, <span class="nu0">15</span><span class="br0">&#41;</span>;
&nbsp;
      <span class="kw3">button</span>.<span class="me1">addEventListener</span><span class="br0">&#40;</span>MouseEvent.<span class="me1">MOUSE_DOWN</span>, <span class="kw2">function</span><span class="br0">&#40;</span>event:MouseEvent<span class="br0">&#41;</span>:<span class="kw3">void</span> <span class="br0">&#123;</span>
        event.<span class="kw3">target</span>.<span class="me1">label</span> = <span class="st0">&quot;Clicked!&quot;</span>;
      <span class="br0">&#125;</span><span class="br0">&#41;</span>;
&nbsp;
      addChild<span class="br0">&#40;</span><span class="kw3">button</span><span class="br0">&#41;</span>;
    <span class="br0">&#125;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></code></pre>

<p>Para criar novos botões, você precisa carregar a classe <code>flash.controls.Button</code>,
disponibilizada pelo arquivo <code>components.swc</code>. Esse arquivo deve ser carregado
pela linha de comando.</p>

<pre><code>$ mxmlc -output main.swf \
      -as3 \
      -static-link-runtime-shared-libraries \
      -default-size 130 50 \
      -optimize \
      -verbose-stacktraces \
      -include-libraries=`pwd`/components.swc \
      Main.as
</code></pre>

<p>O resultado final será algo como a imagem abaixo.</p>

<p><img src="http://m.simplesideias.com.br/as3-button.png" alt="ActionScript 3 gerando botão"></p>

<h3>Compilando os arquivos automaticamente</h3>

<p>Uma das melhores mudanças nesse processo é que agora posso executar tudo pela linha de comando. E posso, inclusive, cmpilar os arquivos automaticamente usando bibliotecas como o <a rel="external"  href="http://rubygems.org/gems/guard">Guard</a>. Primeiro, vamos instalar as gems necessárias.</p>

<pre><code>$ gem install guard guard-shell
</code></pre>

<p>Na raíz de seu projeto, crie o arquivo <code>Guardfile</code> com o conteúdo à seguir.</p>

<pre class="rails"><code>guard <span class="re3">:shell</span> <span class="kw1">do</span>
  watch<span class="br0">&#40;</span>/\.<span class="me1">as</span>$/<span class="br0">&#41;</span> <span class="kw1">do</span>
    <span class="kw3">system</span> &lt;&lt;-SHELL
      mxmlc -output main.<span class="me1">swf</span> \
            -as3 \
            -static-link-runtime-shared-libraries \
            -default-<span class="kw5">size</span> <span class="nu0">130</span> <span class="nu0">50</span> \
            -optimize \
            -verbose-stacktraces \
            -include-libraries <span class="st0">`pwd`</span>/components.<span class="me1">swc</span> \
            Main.<span class="me1">as</span>
    SHELL
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>O código acima irá compilar o SWF toda vez que uma alteração for detectada
em arquivos com a extensão <code>.as</code>. Para iniciar o monitor, basta executar o comando
<code>guard</code>.</p>

<h3>Finalizando</h3>

<p>Por pior que o Flash seja, ele ainda é imbatível em uma coisa: broadcast de áudio e vídeo.
É muito fácil publicar sua webcam e seu microfone. Já que não existe nenhuma outra
alternativa viável, evitar o uso da IDE já ajuda bastante no dia-a-dia.</p>

<p>Para você ter uma ideia de como o Flex é (sic) flexível, veja o que fiz para o Presentta até agora:</p>

<p><img src="http://m.simplesideias.com.br/as3-presentta.png" alt="Componente gerado com Flex"></p>

O componente acima conecta no media server, faz o broadcast, verifica as conexões e, em caso de queda, reconecta automaticamente. Muito bom para algumas horas de hacking. :)<img src="http://feeds.feedburner.com/~r/simplesideias/~4/DhVBfc1gIxk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/programando-em-actionscript-sem-o-flash/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://simplesideias.com.br/programando-em-actionscript-sem-o-flash/</feedburner:origLink></item>
		<item>
		<title>Ruby e o duck typing</title>
		<link>http://feedproxy.google.com/~r/simplesideias/~3/rq46B1XhtJw/</link>
		<comments>http://simplesideias.com.br/ruby-e-o-duck-typing/#comments</comments>
		<pubDate>Mon, 02 Jan 2012 21:15:03 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=726</guid>
		<description><![CDATA[No Ruby, nós não declaramos o tipo de objetos, nem o tipo do retorno de métodos. Embora isso possa parecer algo muito ruim para quem está acostumado com linguagens como Java, linguagens dinamicamente tipadas como o Ruby são muito flexíveis, produtivas e, acredite, seguras. Na maioria das vezes, o medo de não poder contar com [...]]]></description>
			<content:encoded><![CDATA[<p>No Ruby, nós não declaramos o tipo de objetos, nem o tipo do retorno de métodos. Embora isso possa parecer algo muito ruim para quem está acostumado com linguagens como Java, linguagens dinamicamente tipadas como o Ruby são muito flexíveis, produtivas e, acredite, seguras. Na maioria das vezes, o medo de não poder contar com o compilador para fazer verificações de tipos não tem fundamento.</p>

<p>Desenvolvedores Ruby estão mais acostumados em definir objetos pelo que eles podem fazer, do que por seu tipo. Esta técnica é chamada de <em>duck typing</em>.</p>

<p><strong>Se anda como um pato e faz barulho como um pato, então deve ser um pato.</strong> E o interpretador ficará feliz em fazer com que o objeto seja tratado como um pato. Na prática, isso significa que em vez de fazer verificações de tipo de um objeto, você deve se preocupar se este objeto é capaz de executar o método que você precisa.</p>

<p>Pegue como exemplo strings, arquivos e arrays. As classes <code>Array</code>, <code>File</code> e <code>String</code> implementam o método de instância <code>&lt;&lt;</code>, que quase sempre significa <em>append</em>. Você pode se aproveitar desta <em>interface</em> para criar, por exemplo, uma classe de log que não se importa com o tipo de objeto que irá armazenar esses logs.</p>

<pre class="rails"><code><span class="kw1">class</span> SimpleLogger
  <span class="kw1">def</span> initialize<span class="br0">&#40;</span>io<span class="br0">&#41;</span>
    <span class="re1">@io</span> = io
  <span class="kw1">end</span>
&nbsp;
  <span class="kw1">def</span> log<span class="br0">&#40;</span>message<span class="br0">&#41;</span>
    <span class="re1">@io</span> &lt;&lt; <span class="st0">&quot;#{Time.now} - #{message}<span class="es0">\n</span>&quot;</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>A classe <code>SimpleLogger</code> consegue enviar os logs para arrays, strings, arquivos e, se quiser, para qualquer outro objeto que implemente o método <code>&lt;&lt;</code>.</p>

<p>O Ruby realmente abraça o <em>duck typing</em> por toda a linguagem. Diversos <em>protocolos</em> exigem que o objeto apenas implemente um método <code>to_&lt;protocol&gt;</code>. Muitas operações que envolvem arrays, por exemplo, exigem que o objeto do lado direito da expressão apenas implemente o método <code>to_ary</code>.</p>

<pre class="rails"><code><span class="kw1">class</span> Numbers
  <span class="kw1">def</span> to_ary
    <span class="br0">&#91;</span><span class="nu0">4</span>, <span class="nu0">5</span>, <span class="nu0">6</span><span class="br0">&#93;</span>
  <span class="kw1">end</span>
<span class="kw1">end</span>
&nbsp;
<span class="br0">&#91;</span><span class="nu0">1</span>, <span class="nu0">2</span>, <span class="nu0">3</span><span class="br0">&#93;</span> + Numbers.<span class="kw5">new</span>
<span class="co1">#=&gt; [1, 2, 3, 4, 5, 6]</span></code></pre>

<p>A classe <code>Hash</code>, por exemplo, permite que você una dois objetos, desde que o método <code>to_hash</code> seja implementado.</p>

<pre class="rails"><code><span class="kw1">class</span> Configuration
  <span class="kw1">def</span> to_hash
    <span class="br0">&#123;</span>root: <span class="st0">&quot;/etc&quot;</span><span class="br0">&#125;</span>
  <span class="kw1">end</span>
<span class="kw1">end</span>
&nbsp;
config = Configuration.<span class="kw5">new</span>
&nbsp;
<span class="br0">&#123;</span>name: <span class="st0">&quot;Custom config&quot;</span><span class="br0">&#125;</span>.<span class="me1">merge</span><span class="br0">&#40;</span>config<span class="br0">&#41;</span>
<span class="co1">#=&gt; {:name=&gt;&quot;Custom config&quot;, :root=&gt;&quot;/etc&quot;}</span></code></pre>

<p>Não é preciso dizer que este tipo de <em>protocolo por convenção</em> permite criar códigos muito mais flexíveis, com extrema facilidade.</p>

<p>Isso não significa que saber o tipo de objetos não seja útil. Veja, por exemplo, as operações matemáticas. Qualquer objeto pode ser convertido em números. Para isso, basta implementar o método <code>coerce</code>, que recebe o objeto que está solicitando a coerção. O exemplo abaixo mostra como criar uma classe cuja instância pode ser convertida em números inteiros e flutuantes, mas não em instâncias da classe <code>BigDecimal</code>.</p>

<pre class="rails"><code><span class="kw1">class</span> NumberOne
  <span class="kw1">def</span> coerce<span class="br0">&#40;</span>object<span class="br0">&#41;</span>
    <span class="kw1">case</span> object
    <span class="kw1">when</span> <span class="kw3">Integer</span>
      <span class="br0">&#91;</span>object, <span class="nu0">1</span><span class="br0">&#93;</span>
    <span class="kw1">when</span> <span class="kw3">Float</span>
      <span class="br0">&#91;</span>object, <span class="nu0">1.0</span><span class="br0">&#93;</span>
    <span class="kw1">else</span>
      <span class="kw3">raise</span> <span class="kw4">TypeError</span>, <span class="st0">&quot;#{self.inspect} can't be coerced into #{object.class}&quot;</span>
    <span class="kw1">end</span>
  <span class="kw1">end</span>
<span class="kw1">end</span>
&nbsp;
<span class="kw3">puts</span> <span class="nu0">1</span> + NumberOne.<span class="kw5">new</span>
<span class="co1">#=&gt; 2</span>
&nbsp;
<span class="kw3">puts</span> <span class="nu0">1.0</span> + NumberOne.<span class="kw5">new</span>
<span class="co1">#=&gt; 2.0</span>
&nbsp;
<span class="kw3">require</span> <span class="st0">&quot;bigdecimal&quot;</span>
<span class="kw3">puts</span> BigDecimal.<span class="kw5">new</span><span class="br0">&#40;</span><span class="st0">&quot;1.0&quot;</span><span class="br0">&#41;</span> + NumberOne.<span class="kw5">new</span>
<span class="co1">#=&gt; TypeError: FakeNumber can't be coerced into BigDecimal</span></code></pre>

<p>O <em>duck typing</em> vai além de simples regras; é um <em>estilo</em> de programação. Antes de exigir tipos de objetos, pergunte-se se isso é realmente necessário. Às vezes, o tipo do objeto é muito importante, mas muitas vezes isso simplesmente não importa.</p>

<p><strong>NOTA:</strong> Este artigo foi tirado do e-book "Conhecendo o Ruby" que estou escrevendo. Se inscreva na <a href="http://howtocode.com.br/?simplesideias">newsletter do HOWTO</a> e saiba quando ele for lançado.</p><img src="http://feeds.feedburner.com/~r/simplesideias/~4/rq46B1XhtJw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/ruby-e-o-duck-typing/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://simplesideias.com.br/ruby-e-o-duck-typing/</feedburner:origLink></item>
		<item>
		<title>Hospendando sites estáticos no Heroku</title>
		<link>http://feedproxy.google.com/~r/simplesideias/~3/nyEt5yNLepI/</link>
		<comments>http://simplesideias.com.br/hospendando-sites-estaticos-no-heroku/#comments</comments>
		<pubDate>Wed, 28 Dec 2011 03:04:50 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=719</guid>
		<description><![CDATA[Faz algum tempo que venho usando o plano gratuito do Heroku para hospedar páginas estáticas, embora você consiga ir muito além disso. De qualquer modo, é uma maneira muito prática de ter sites estáticos com o poder do deploy de aplicações através de um simples push do Git. O processo em si é bastante simples. [...]]]></description>
			<content:encoded><![CDATA[<p>Faz algum tempo que venho usando o plano gratuito do <a rel="external" href="http://heroku.com">Heroku</a> para hospedar páginas estáticas, embora você consiga ir muito além disso. De qualquer modo, é uma maneira muito prática de ter sites estáticos com o poder do deploy de aplicações através de um simples <em>push</em> do Git.</p>

<p>O processo em si é bastante simples. Primeiro, você deve organizar todos os seus arquivos em algum diretório, por exemplo, <code>some_site/public</code>. Este diretório pode conter arquivos HTML, JavaScript e CSS. Na prática, você pode servir qualquer tipo de arquivo.</p>

<p>Crie o arquivo <code>some_site/config.ru</code>. Nós iremos servir os arquivos estáticos com <a rel="external" href="http://rack.rubyforge.org">Rack</a>. Primeiro, nós vamos criar um aplicativo usando o <code>Rack::Builder</code>. Este aplicativo usará um middleware que redirecionará a requisição na raíz do site para o arquivo <code>some_site/public/index.html</code>.</p>

<p>Todos os outros arquivos do diretório <code>some_site/public</code> serão servidos com o <code>Rack::Directory</code>.</p>

<pre class="rails"><code>app = <span class="re2">Rack::Builder</span>.<span class="kw5">new</span> <span class="kw1">do</span>
  use <span class="re2">Rack::Static</span>, urls: <span class="br0">&#123;</span><span class="st0">&quot;/&quot;</span> =&gt; <span class="st0">&quot;index.html&quot;</span><span class="br0">&#125;</span>, root: <span class="st0">&quot;public&quot;</span>
  run <span class="re2">Rack::URLMap</span>.<span class="kw5">new</span><span class="br0">&#40;</span><span class="br0">&#123;</span>
    <span class="st0">&quot;/&quot;</span> =&gt; <span class="re2">Rack::Directory</span>.<span class="kw5">new</span><span class="br0">&#40;</span><span class="st0">&quot;public&quot;</span><span class="br0">&#41;</span>
  <span class="br0">&#125;</span><span class="br0">&#41;</span>
<span class="kw1">end</span>
&nbsp;
run app</code></pre>

<p>Crie também um arquivo <code>Gemfile</code>, que terá como única dependência o próprio Rack. Este arquivo <code>Gemfile</code> deve estar na raíz do seu projeto e será algo como isto.</p>

<pre class="rails"><code>source <span class="re3">:rubygems</span>
gem <span class="st0">&quot;rack&quot;</span>, <span class="st0">&quot;~&gt; 1.3&quot;</span></code></pre>

<p>Execute o comando <code>bundle install</code> para instalar a dependência e gerar o arquivo <code>Gemfile.lock</code>.</p>

<p>Na raíz do projeto, inicie um novo repositório Git e faça o commit inicial.</p>

<pre class="text"><code>$ cd some_site
$ git init
Initialized empty Git repository in /Users/fnando/Sites/some_site/.git/
$ git add .
$ git ci -am &quot;Initial commit&quot;
[master (root-commit) 54e37c9] Initial commit
 4 files changed, 31 insertions(+), 0 deletions(-)
 create mode 100644 Gemfile
 create mode 100644 Gemfile.lock
 create mode 100644 config.ru
 create mode 100644 public/index.html</code></pre>

<p>Agora, basta criar seu aplicativo no Heroku. Se você ainda não possui uma conta configurada, <a rel="external" href="http://devcenter.heroku.com/articles/quickstart">veja o que é preciso fazer</a>. Se tudo estiver certo, você pode criar um novo aplicativo com o comando <code>heroku apps:create &lt;seu-app&gt;</code>. O stack padrão é baseado no Ruby 1.9, então estamos muito bem acompanhados.</p>

<pre class="text"><code>$ heroku apps:create some-site
Creating some-site... done, stack is bamboo-mri-1.9.2
http://some-site.heroku.com/ | git@heroku.com:some-site.git
Git remote heroku added</code></pre>

<p>Para fazer o deploy, execute o comando <code>git push heroku</code>.</p>

<pre class="text"><code>$ git push heroku 
Counting objects: 7, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (7/7), 768 bytes, done.
Total 7 (delta 0), reused 0 (delta 0)
&nbsp;
-----&gt; Heroku receiving push
-----&gt; Ruby/Rack app detected
-----&gt; Gemfile detected, running Bundler version 1.0.7
       Unresolved dependencies detected; Installing...
       Using --without development:test
       Fetching source index for http://rubygems.org/
       Installing rack (1.3.5) 
       Using bundler (1.0.7) 
       Your bundle is complete! It was installed into ./.bundle/gems/
-----&gt; Compiled slug size is 152K
-----&gt; Launching... done, v3
       http://some-site.heroku.com deployed to Heroku
&nbsp;
To git@heroku.com:some-site.git
 * [new branch]      HEAD -&gt; master</code></pre>

<p>Certifique-se que está tudo funcionando. Basta acessar a URL exibida após o deploy que, neste caso, é <code>http://some-site.heroku.com</code>.</p>

<p>Obviamente, usar esta URL não é nada profissional. Você pode configurar seu próprio domínio, sem gastar nada (se não me engano, você precisa adicionar o seu cartão de crédito, mesmo sendo funcionalidades gratuitas). Adicione a extensão &#034;Custom Domains&#034;.</p>

<pre class="text"><code>$ heroku addons:add custom_domains:basic
-----&gt; Adding custom_domains:basic to some-site... done, (free)</code></pre>

<p>Adicione também a extensão &#034;Zerigo DNS&#034;.</p>

<pre class="text"><code>$ heroku addons:add zerigo_dns:basic
-----&gt; Adding zerigo_dns:basic to some-site... done, (free)</code></pre>

<p>Finalmente, você pode adicionar seu domínio com o comando <code>heroku domains:add &lt;seu domínio&gt;</code>.</p>

<pre class="text"><code>$ heroku domains:add somesite.com
Added somesite.com as a custom domain name for some-site</code></pre>

<p>Você precisará adicionar o registro de DNS que irá redirecionar <code>www.somesite.com</code> para <code>somesite.com</code> no site da Zerigo. Para acessar este painel de controle, execute o comando <code>heroku addons:open zerigo_dns:basic</code>.</p>

<pre class="text"><code>$ heroku addons:open zerigo_dns:basic
Opening zerigo_dns:basic for some-site...</code></pre>

<p>Clique no botão &#034;Configure&#034;.</p>

<p><img src="http://m.simplesideias.com.br/heroku-zerigo.png" alt="Painel do Zerigo DNS no Heroku"/></p>

<p>Você será redirecionado para uma tela como esta:</p>

<p><img src="http://m.simplesideias.com.br/zerigo-dns.jpg" alt="Zerigo DNS" /></p>

<p>Clique no link &#034;Host > Add&#034; para adicionar um novo registro. No campo &#034;Host&#034;, digite &#034;www&#034;, defina o tipo do registro como sendo &#034;Redirect&#034; e, por último, digite a URL de destino no campo &#034;Data&#034;.</p>

<p><img src="http://m.simplesideias.com.br/zerigo-dns-redirect.png" alt="Zerigo DNS - Adicionando redirecionamento" /></p>

<p>O Zerigo DNS funciona bem para poucos acessos, mas você pode rapidamente ultrapassar o limite do plano básico. Neste caso, sugiro que dê uma olhada no serviço oferecido pela <a href="https://dnsimple.com/r/2b362d48987a9a">DNSimple</a>, que custa apenas US$3 para 10 domínios e é extremamente simples de configurar; existe até uma opção de configuração com apenas um clique para aplicativos hospedados no Heroku.</p><img src="http://feeds.feedburner.com/~r/simplesideias/~4/nyEt5yNLepI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/hospendando-sites-estaticos-no-heroku/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://simplesideias.com.br/hospendando-sites-estaticos-no-heroku/</feedburner:origLink></item>
		<item>
		<title>Usando presenters no Rails</title>
		<link>http://feedproxy.google.com/~r/simplesideias/~3/YfZMHoHchUc/</link>
		<comments>http://simplesideias.com.br/usando-presenters-no-rails/#comments</comments>
		<pubDate>Sun, 18 Dec 2011 19:49:09 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=706</guid>
		<description><![CDATA[Um problema muito recorrente de aplicativos de médio-grande porte é que as views são uma bagunça. É muito comum termos condições em nossas views. Objetos possuem diferentes estados e muitas vezes precisamos mostrar esses estados visualmente. E normalmente começamos pelo caminho mais fácil, que é adicionar ifs na view. Acontece que isso não precisa ser [...]]]></description>
			<content:encoded><![CDATA[<p>Um problema muito recorrente de aplicativos de médio-grande
porte é que as views são uma bagunça.</p>

<p>É muito comum termos condições em nossas views. Objetos possuem
diferentes estados e muitas vezes precisamos mostrar esses estados
visualmente. E normalmente começamos pelo caminho mais fácil, que é 
adicionar <code>ifs</code> na view.</p>

<p>Acontece que isso não precisa ser sempre assim. Neste artigo vou
mostrar como funciona um pattern chamado Presenter, que permite
diminuir/remover a complexidade de views e controllers.</p>

<h3>Começando com o seu próprio presenter</h3>

<p>A primeira coisa que você precisa detectar é que tipo de lógica
é possível extrair de sua view. Algumas coisas mais genéricas
fazem mais sentido serem extraídas como helpers. Outras, como <code>ifs</code>
para determinar qual partial deve ser renderizada provavelmente
devem ser movidas para seu presenter.</p>

<p>Imagine que você tenha uma view como esta:</p>

<pre class="text"><code>&lt;h1&gt;&lt;%= @product.name %&gt;&lt;/h1&gt;
&nbsp;
&lt;% if @product.description %&gt;
  &lt;p class=&quot;description&quot;&gt;&lt;%= @product.more %&gt;&lt;/p&gt;
&lt;% end %&gt;</code></pre>

<p>Não se deixe enganar por esse tipo de lógica. Embora pareça inofensiva, 
coisas como esta podem sair do controle rapidamente.</p>

<p>Esta view precisa de uma variável <code>@product</code> que deve ser definida em nosso controller:</p>

<pre class="rails"><code><span class="kw1">class</span> ProductsController &lt; ApplicationController
  <span class="kw1">def</span> <span class="kw5">show</span>
    <span class="re1">@product</span> = Product.<span class="me1">find</span><span class="br0">&#40;</span>params<span class="br0">&#91;</span><span class="re3">:id</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>Agora, precisamos de uma classe que irá &#034;envelopar&#034; nossa instância da classe <code>Product</code>. Crie o arquivo <code>app/presenters/product_presenter.rb</code>. Como este 
diretório não está no load path do Rails, vamos ter que fazer uma configuração no arquivo <code>config/application.rb</code>.</p>

<pre class="rails"><code><span class="kw1">module</span> HOWTO
  <span class="kw1">class</span> Application &lt; <span class="re2">Rails::Application</span>
    <span class="co1"># ... </span>
    config.<span class="me1">autoload_paths</span> &lt;&lt; config.<span class="me1">root</span>.<span class="me1">join</span><span class="br0">&#40;</span><span class="st0">&quot;app/presenters&quot;</span><span class="br0">&#41;</span>.<span class="kw5">to_s</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>Volte ao arquivo <code>product_presenter.rb</code> e crie a classe <code>ProductPresenter</code>. </p>

<pre class="rails"><code><span class="kw1">class</span> ProductPresenter
  <span class="kw1">def</span> initialize<span class="br0">&#40;</span>product<span class="br0">&#41;</span>
    <span class="re1">@product</span> = product
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>Esta classe será responsável por <strong>expor</strong> todos os atributos que nossa view irá acessar. Em vez de definir cada um dos métodos manualmente, podemos apenas <em>delegar</em> as chamadas para o objeto. Para fazer isso, vamos usar o método <a rel="external" href="http://rubydoc.info/docs/rails/3.1.1/Module:delegate">Module#delegate</a>, adicionado pelo ActiveSupport. </p>

<pre class="rails"><code><span class="kw1">class</span> ProductPresenter
  delegate <span class="re3">:name</span>, <span class="re3">:description</span>, to: :<span class="st0">&quot;@product&quot;</span>
&nbsp;
  <span class="kw1">def</span> initialize<span class="br0">&#40;</span>product<span class="br0">&#41;</span>
    <span class="re1">@product</span> = product
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>Qualquer chamada aos métodos <code>ProductPresenter#name</code> e <code>ProductPresenter#description</code> serão delegadas para o objeto que foi armazenado em <code>@product</code>. Você também poderia utilizar o módulo <a rel="external" href="http://www.ruby-doc.org/stdlib-1.9.3/libdoc/forwardable/rdoc/index.html">Forwardable</a>, mas a versão adicionada pelo ActiveSupport é mais elegante.</p>

<p>Agora, podemos remover aquele <code>if</code>. Se você não se lembra mais dele, dê uma última olhadela, pois logo ele não mais existirá! Adicione o método <code>description</code>. Faça com que este método retorne o parágrafo com a descrição, caso ela tenha sido definida. 
Como é necessário retornar uma tag HTML, vamos usar o helper <code>content_tag</code>.</p>

<pre class="rails"><code><span class="kw1">class</span> ProductPresenter
  delegate <span class="re3">:name</span>, to: :<span class="st0">&quot;@product&quot;</span>
&nbsp;
  <span class="kw1">def</span> initialize<span class="br0">&#40;</span>product<span class="br0">&#41;</span>
    <span class="re1">@product</span> = product
  <span class="kw1">end</span>
&nbsp;
  <span class="kw1">def</span> description
    <span class="kw1">if</span> <span class="re1">@product</span>.<span class="me1">description</span>.<span class="me1">present</span>?
      helpers.<span class="kw5">content_tag</span><span class="br0">&#40;</span><span class="re3">:p</span>, <span class="re1">@product</span>.<span class="me1">description</span>, <span class="kw1">class</span>: <span class="st0">&quot;description&quot;</span><span class="br0">&#41;</span>
    <span class="kw1">end</span>
  <span class="kw1">end</span>
&nbsp;
  private
  <span class="kw1">def</span> helpers
    ApplicationController.<span class="me1">helpers</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>Altere o controller para que ele passe a instância da classe <code>Product</code> para o presenter.</p>

<pre class="rails"><code><span class="kw1">class</span> ProductsController &lt; ApplicationController
  <span class="kw1">def</span> <span class="kw5">show</span>
    <span class="re1">@product</span> = ProductPresenter.<span class="kw5">new</span><span class="br0">&#40;</span>Product.<span class="me1">find</span><span class="br0">&#40;</span>params<span class="br0">&#91;</span><span class="re3">:id</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>Para finalizar, basta modificar nossa view.</p>

<pre class="text"><code>&lt;h1&gt;&lt;%= @product.name %&gt;&lt;/h1&gt;
&lt;%= @product.description %&gt;</code></pre>

<p>Para o caso de partials, o funcionamento é basicamente o mesmo. No entanto, em vez de fazer a renderização no próprio presenter, é mais fácil retornar o nome da partial que deve ser renderizada.</p>

<p>Imagine que nossa view tenha mais um <code>if</code> que irá renderizar uma partial diferente para produtos gratuitos.</p>

<pre class="text"><code>&lt;% if @product.paid? %&gt;
  &lt;%= render &quot;order&quot;, product: @product %&gt;
&lt;% else %&gt;
  &lt;%= render &quot;download&quot;, product: @product %&gt;
&lt;% end %&gt;</code></pre>

<p>Podemos implementar um método chamado <code>ProductPresenter#checkout_partial</code> que irá fazer aquele <code>if</code>, retornando apenas o nome da partial.</p>

<pre class="rails"><code><span class="kw1">class</span> ProductPresenter
  delegate <span class="re3">:name</span>, to: :<span class="st0">&quot;@product&quot;</span>
&nbsp;
  <span class="kw1">def</span> initialize<span class="br0">&#40;</span>product<span class="br0">&#41;</span>
    <span class="re1">@product</span> = product
  <span class="kw1">end</span>
&nbsp;
  <span class="kw1">def</span> description
    <span class="kw1">if</span> <span class="re1">@product</span>.<span class="me1">description</span>.<span class="me1">present</span>?
      helpers.<span class="kw5">content_tag</span><span class="br0">&#40;</span><span class="re3">:p</span>, <span class="re1">@product</span>.<span class="me1">description</span>, <span class="kw1">class</span>: <span class="st0">&quot;description&quot;</span><span class="br0">&#41;</span>
    <span class="kw1">end</span>
  <span class="kw1">end</span>
&nbsp;
  <span class="kw1">def</span> checkout_partial
    <span class="re1">@product</span>.<span class="me1">paid</span>? ? <span class="st0">&quot;order&quot;</span> : <span class="st0">&quot;download&quot;</span>
  <span class="kw1">end</span>
&nbsp;
  private
  <span class="kw1">def</span> helpers
    ApplicationController.<span class="me1">helpers</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>E na nossa view, basta renderizar o retorno do método <code>ProductPresenter#checkout_partial</code>.</p>

<pre class="text"><code>&lt;%= render @product.checkout_partial, product: @product %&gt;</code></pre>

<p>A esta altura, você já deve ter percebido como presenters podem remover completamente a lógica das views. Embora seja muito fácil fazer isso sem a necessidade de bibliotecas, algumas coisas precisam ser implementadas toda vez. É o caso de helpers, rotas e métodos de internacionalização.</p>

<p>Pensando nisso, decidi extrair aquela organização de código que eu estava utilizando em uma gem chamada <a rel="external" href="http://rubygems.org/gems/simple_presenter">simple_presenter</a>.</p>

<h3>Usando o simple_presenter</h3>

<p>Para instalar, basta executar o comando abaixo:</p>

<pre class="text"><code>$ gem install simple_presenter</code></pre>

<p>Lembre-se de adicionar a gem ao arquivo Gemfile.</p>

<pre class="rails"><code>source <span class="re3">:rubygems</span>
gem <span class="st0">&quot;rails&quot;</span>, <span class="st0">&quot;3.1.3&quot;</span>
gem <span class="st0">&quot;simple_presenter&quot;</span>, <span class="st0">&quot;~&gt; 0.1&quot;</span></code></pre>

<p>Aquele mesmo presenter que definimos pode ser trocado por algo como isto:</p>

<pre class="rails"><code><span class="kw1">class</span> ProductPresenter &lt; Presenter
  expose <span class="re3">:name</span>, <span class="re3">:description</span>
&nbsp;
  <span class="kw1">def</span> description
    <span class="kw1">if</span> <span class="re1">@subject</span>.<span class="me1">description</span>.<span class="me1">present</span>?
      h.<span class="kw5">content_tag</span><span class="br0">&#40;</span><span class="re3">:p</span>, <span class="re1">@subject</span>.<span class="me1">description</span>, <span class="kw1">class</span>: <span class="st0">&quot;description&quot;</span><span class="br0">&#41;</span>
    <span class="kw1">end</span>
  <span class="kw1">end</span>
&nbsp;
  <span class="kw1">def</span> checkout_partial
    <span class="re1">@subject</span>.<span class="me1">paid</span>? ? <span class="st0">&quot;order&quot;</span> : <span class="st0">&quot;download&quot;</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>Note que não precisamos mais definir o método <code>ProductPresenter#initialize</code>, nem o método <code>ProductPresenter#helpers</code>. Também tivemos que mudar todas as referências a <code>@product</code> para <code>@subject</code>; isso é necessário  porque, por padrão, o nome do objeto que receberá os métodos delegados é <code>@subject</code>.</p>

<p>O simple_presenter adiciona os métodos <code>helpers</code> e <code>h</code> que permite acessar os helpers do Rails. Os helpers de rotas podem ser acessados com os métodos <code>routes</code> e <code>r</code>. E, finalmente, os helpers de internacionalização podem ser acessados por <code>translate</code> e <code>t</code>, e <code>localize</code> e <code>l</code>.</p>

<h3>Escrevendo testes</h3>

<p>Escrever testes para presenters é muito simples. No caso do RSpec, basta criar o diretório <code>spec/presenters</code>. Aquele nosso presenter pode ter testes como este:</p>

<pre class="rails"><code><span class="kw3">require</span> <span class="st0">&quot;spec_helper&quot;</span>
&nbsp;
describe ProductPresenter <span class="kw1">do</span>
  let<span class="br0">&#40;</span><span class="re3">:product</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> mock<span class="br0">&#40;</span>Product, name: <span class="st0">&quot;Some product&quot;</span><span class="br0">&#41;</span> <span class="br0">&#125;</span>
  subject <span class="br0">&#123;</span> described_class.<span class="kw5">new</span><span class="br0">&#40;</span>product<span class="br0">&#41;</span> <span class="br0">&#125;</span>
&nbsp;
  its<span class="br0">&#40;</span><span class="re3">:name</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> should eql<span class="br0">&#40;</span><span class="st0">&quot;Some product&quot;</span><span class="br0">&#41;</span> <span class="br0">&#125;</span>
&nbsp;
  describe <span class="st0">&quot;#description&quot;</span> <span class="kw1">do</span>
    it <span class="st0">&quot;returns content&quot;</span> <span class="kw1">do</span>
      product.<span class="me1">stub</span> description: <span class="st0">&quot;Some description&quot;</span>
      expected = %<span class="br0">&#91;</span>&lt;p <span class="kw1">class</span>=<span class="st0">&quot;description&quot;</span>&gt;Some description&lt;/p&gt;<span class="br0">&#93;</span>
&nbsp;
      subject.<span class="me1">description</span>.<span class="me1">should</span> eql<span class="br0">&#40;</span>expected<span class="br0">&#41;</span>
    <span class="kw1">end</span>
&nbsp;
    it <span class="st0">&quot;returns no message&quot;</span> <span class="kw1">do</span>
        subject.<span class="me1">description</span>.<span class="me1">should</span> be_blank
    <span class="kw1">end</span>
  <span class="kw1">end</span>
&nbsp;
  describe <span class="st0">&quot;#checkout_partial&quot;</span> <span class="kw1">do</span>
    it <span class="st0">&quot;returns partial for paid products&quot;</span> <span class="kw1">do</span>
      product.<span class="me1">stub</span> paid?: <span class="kw2">true</span>
      subject.<span class="me1">checkout_partial</span>.<span class="me1">should</span> eql<span class="br0">&#40;</span><span class="st0">&quot;order&quot;</span><span class="br0">&#41;</span>
    <span class="kw1">end</span>
&nbsp;
    it <span class="st0">&quot;returns partial for free products&quot;</span> <span class="kw1">do</span>
      product.<span class="me1">stub</span> paid?: <span class="kw2">false</span>
      subject.<span class="me1">checkout_partial</span>.<span class="me1">should</span> eql<span class="br0">&#40;</span><span class="st0">&quot;download&quot;</span><span class="br0">&#41;</span>
    <span class="kw1">end</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<h3>Finalizando</h3>

<p>Você deve ter percebido que presenters permitem tornar suas views muito mais simples. Além disso, eles tem a vantagem de serem fáceis de testar.</p>

<p>A coisa mais difícil dos presenters é se acostumar com eles. Mas depois que você se acostuma, dificilmente terá uma view complicada e também nem vai querer deixar de usá-los!</p>

<p><strong>UPDATE 1:</strong> O <a rel="external" href="http://twitter.com/#!/josevalim/status/148709799574511616">Valim me lembrou</a> que à partir do Rails 3 não é mais preciso adicionar diretórios <code>app/*</code>, pois o Rails faz isso automaticamente. Eu sabia disso, mas o costume ainda permanece.</p><img src="http://feeds.feedburner.com/~r/simplesideias/~4/YfZMHoHchUc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/usando-presenters-no-rails/feed/</wfw:commentRss>
		<slash:comments>31</slash:comments>
		<feedburner:origLink>http://simplesideias.com.br/usando-presenters-no-rails/</feedburner:origLink></item>
		<item>
		<title>Gravando screencasts com o ScreenFlow</title>
		<link>http://feedproxy.google.com/~r/simplesideias/~3/7S13MYZYmnw/</link>
		<comments>http://simplesideias.com.br/gravando-screencasts-com-o-screenflow/#comments</comments>
		<pubDate>Thu, 24 Nov 2011 16:29:12 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
				<category><![CDATA[Mac OS X]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=696</guid>
		<description><![CDATA[Uma das melhores ferramentas para quem precisa gravar screencasts no Mac é o ScreenFlow. Ele possui uma série de funcionalidades avançadas que são muito simples de usar como animações e zoom, dentre outras. No HOWTO as aulas são gravadas para quem quer assistir depois. O grande problema é que, como as aulas são longas (por [...]]]></description>
			<content:encoded><![CDATA[<p>
  Uma das melhores ferramentas para quem precisa gravar screencasts no Mac é o
  <a rel="external" href="http://www.telestream.net/screen-flow/">ScreenFlow</a>.
  Ele possui uma série de funcionalidades avançadas que são muito simples de usar
  como animações e zoom, dentre outras.
</p>

<p>
  No <a rel="external" href="http://howtocode.com.br">HOWTO</a> as aulas são gravadas
  para quem quer assistir depois. O grande problema é que, como as aulas são longas
  (por volta de 2 horas de duração), os vídeos ficam muito grandes. Tentando resolver
  este problema, consegui encontrar a <strong>configuração perfeita</strong> para
  quem precisa exportar vídeos longos.
</p>

<h3>Antes</h3>

<p>
  Antes de encontrar estas configurações, não tinha muito o que fazer. Eu modificava
  o <em>preset</em> Web &ndash; High como o screenshot abaixo.
</p>

<p>
  <img src="http://m.simplesideias.com.br/screenflow-h264.jpg"
    alt="Configurações personalizadas de Web - High com o codec H.264" />
</p>

<p>
  A minha última tentativa de exportação de uma aula de 2h15 levou 4 horas
  para exportar o vídeo e resultou em um arquivo de 665MB. A qualidade ficou
  muito boa, mas o tamanho do arquivo é, obviamente, um problema.
</p>

<p>
  Antes, eu usava o <a rel="external" href="http://www.shinywhitebox.com/ishowu-v1/">iShowU</a>
  e um vídeo com a mesma duração ficava por volta de 300MB, o que já é um tamanho extremamente
  razoável. A grande vantagem do iShowU é que você não precisa exportar o vídeo depois de gravá-lo
  (obviamente isso tem um ponto negativo que é a falta de recursos que o ScreenFlow oferece, mas
  se você não precisa, nem vai sentir falta) e que tornava a liberação do vídeo muito mais rápida,
  já que bastava fazer o upload do vídeo.
</p>

<p>
  Mas, então, porque deixei de usar o iShowU? Bem, nas duas últimas gravações tive problemas com
  ele: um dos vídeos ficou sem áudio e o outro ficou com a imagem fixa. E esses erros aconteceram
  mais ou menos no meio do vídeo, sem nenhuma explicação.
</p>

<h3>Depois</h3>

<p>
  Dado o tamanho do arquivo gerado pelo ScreenFlow, comecei a procurar configurações melhores que
  reduzissem drasticamente o tamanho do vídeo. Fazendo algumas buscas madrugada adentro, encontrei esse
  <a rel="external" href="http://blogs.telestream.net/screenflow/2010/02/apple-h-264-vs-x264-in-screenflow-better-exports/">artigo</a> no blog da própria <a rel="external" href="http://telestream.net/">Telestream</a>,
  empresa que criou o ScreenFlow.
</p>

<p>
  Neste artigo eles mostram como configurar o ScreenFlow com um codec chamado x264. Mesmo seguindo este artigo, você precisará modificar algumas outras configurações que não são mencionadas.
</p>

<p>
  Para instalar este codec, que é gratuito, basta você fazer o download no
  <a rel="external" href="http://www003.upp.so-net.ne.jp/mycometg3/">site do desenvolvedor</a>.
  Depois, copie o arquivo <code>x264Encoder.component</code> para o diretório
  <code>~/Library/QuickTime</code>. Pronto! Agora, basta configurar o ScreenFlow com este
  novo codec. Reinicie o ScreenFlow para que ele faça a detecção.
</p>

<p>
  Na hora de exportar (<kbd>&#x2318;+E</kbd>), clique no botão &ldquo;Customize > Video > Settings&rdquo;.
  Na opção &ldquo;Compression Type&rdquo;, selecione o codec &ldquo;x264Encoder&rdquo;. Altere as
  configurações desta janela para as mesmas do screenshot abaixo.
</p>

<p>
  <img src="http://m.simplesideias.com.br/screenflow-video-settings.jpg"
    alt="Configurações de vídeo com o codec x264Encoder" />
</p>

<p>
  Você vai precisar configurar também o próprio codec. Para isso, nesta mesma janela clique no
  botão &ldquo;Options&rdquo;. Isso abrirá uma janela com todas as opções de personalização do
  codec. Modifique as opções como o screenshot abaixo.
</p>

<p>
  <img src="http://m.simplesideias.com.br/screenflow-x264.jpg"
    alt="Configurações do codec x264Encoder" />
</p>

<p>
  Por último, se o seu screencast é baseado em voz, com quase nenhuma trilha sonora,
  você também pode modificar as configurações do áudio, diminuindo ainda mais o tamanho
  do vídeo exportado. Basta você modificar a qualidade do áudio para 64kbps de bitrate,
  como no screenshot abaixo.
</p>

<p><img src="http://m.simplesideias.com.br/screenflow-audio.jpg"
    alt="Configurações de áudio" />
</p>

<p>
  Meu Macbook Pro não é lá essas coisas (Mid 2009, com processador Core 2 Duo 2.26 GHz),
  então demorou <em>um pouquinho</em>. Depois de <strong>6 horas</strong>, aquele mesmo vídeo
  que tinha ficado com 665MB de tamanho foi exportado como <strong>266MB</strong>.
</p>

<p>O meu servidor agradece, e os alunos também!</p><img src="http://feeds.feedburner.com/~r/simplesideias/~4/7S13MYZYmnw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/gravando-screencasts-com-o-screenflow/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://simplesideias.com.br/gravando-screencasts-com-o-screenflow/</feedburner:origLink></item>
		<item>
		<title>Classe singleton e definição de métodos de classe</title>
		<link>http://feedproxy.google.com/~r/simplesideias/~3/3ib0-VjRdKk/</link>
		<comments>http://simplesideias.com.br/classe-singleton-e-definicao-de-metodos-de-classe/#comments</comments>
		<pubDate>Sun, 23 Oct 2011 22:33:37 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=688</guid>
		<description><![CDATA[Quando falei sobre classes singleton no Ruby, mostrei como era possível atuar no contexto da classe. Uma coisa muito comum entre os desenvolvedores é definir métodos de classe através da classe singleton. class Person class &#60;&#60; self def description &#34;It defines an user&#34; end end end No exemplo acima estamos definindo uma método de classe [...]]]></description>
			<content:encoded><![CDATA[<p>Quando falei sobre <a href="http://simplesideias.com.br/ruby-object-model-singleton-class/">classes singleton no Ruby</a>, mostrei como era possível atuar no contexto da classe. Uma coisa muito comum entre os desenvolvedores é definir métodos de classe através da classe singleton.</p>

<pre class="ruby"><code><span class="kw1">class</span> Person
  <span class="kw1">class</span> &lt;&lt; <span class="kw2">self</span>
    <span class="kw1">def</span> description
      <span class="st0">&quot;It defines an user&quot;</span>
    <span class="kw1">end</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>No exemplo acima estamos definindo uma método de classe <code>Person.description</code>. Infelizmente, quando a quantidade de métodos é muito grande, a legibilidade fica prejudicada; você não consegue saber rapidamente se este método é de classe ou instância.</p>

<p>Na maioria das vezes essa escolha é feita sem um objetivo; a explicação é que é possível salvar alguns caracteres ao não digitar <code>self</code> de novo e de novo.</p>

<p>Particularmente, acho que o código acima fica muito mais legível quando escrito desta forma:</p>

<pre class="ruby"><code><span class="kw1">class</span> Person
  <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">description</span>
    <span class="st0">&quot;It defines an user&quot;</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>Isso não significa que você não deva usar nunca a classe singleton. Eu uso constantemente. Mas não para definir métodos dessa maneira. Eu gosto, por exemplo, de definir atributos.</p>

<pre class="ruby"><code><span class="kw1">class</span> Config
  <span class="kw1">class</span> &lt;&lt; <span class="kw2">self</span>
    attr_accessor <span class="re3">:root_dir</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>Um outro uso é quando preciso modificar alguma classe quando um hook é executado, como em plugins do ActiveRecord.</p>

<pre class="ruby"><code><span class="kw1">module</span> MyPlugin
  <span class="kw1">module</span> ClassMethods; <span class="kw1">end</span>
  <span class="kw1">module</span> InstanceMethods; <span class="kw1">end</span>
&nbsp;
  <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">extended</span><span class="br0">&#40;</span>base<span class="br0">&#41;</span>
    <span class="kw1">class</span> &lt;&lt; base
      <span class="kw1">include</span> InstanceMethods
      extend ClassMethods
    <span class="kw1">end</span>
  <span class="kw1">end</span>
<span class="kw1">end</span>
&nbsp;
<span class="re2">ActiveRecord::Base</span>.<span class="me1">extend</span><span class="br0">&#40;</span>MyPlugin<span class="br0">&#41;</span></code></pre>

<p>O método <code>Module#include</code> é privado. Uma alternativa seria injetar este módulo com o método <code>Object#send</code>. Eu só não faço isso pois terei que estender este objeto com os métodos de classe, então prefiro usar a classe singleton para manter o código mais legível.</p>

<h3>Finalizando</h3>

<p>Definir muitos métodos com a classe singleton pode ser prático, mas prejudica a legibilidade e você não quer que isto aconteça. Prefira a classe singleton para métodos que não estão disponíveis no contexto da classe como o <code>attr_accessor</code>. <strong>Não é porque você pode fazer algo, que você deve fazê-lo mesmo assim.</strong></p><img src="http://feeds.feedburner.com/~r/simplesideias/~4/3ib0-VjRdKk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/classe-singleton-e-definicao-de-metodos-de-classe/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://simplesideias.com.br/classe-singleton-e-definicao-de-metodos-de-classe/</feedburner:origLink></item>
	</channel>
</rss>

