Arquivo

Textos com Etiquetas ‘Ruby’

Generate PDF with prawn and Google charts

29, dezembro, 2011 Sem comentários

Hey guys,

It’s a quickly post about how to generate pdf with prawn and google charts. Prawn is a awesome lib in ruby for generating PDF documents and google charts is a API to generate charts.

I like to create a class responsible to generate my pdf documents. Here is my implementation:

# encoding: UTF-8
require 'open-uri'
class GenderReportPdf < Prawn::Document

  def initialize(mens, womans)
    super(top_margin: 70)
    add_title
    @mens = mens
    @womans = womans
    add_count
    add_image
  end

  def add_title
    text "Report by Gender", size: 28, style: :bold, position: :center
  end

  def add_count
    move_down 20
    text "Mens #{@h_count}"
    text "Womans #{@m_count}"
  end

  def add_image
    move_down 20
    image get_external_image, :position => :center
  end

  def get_external_image
    img = URI.parse(URI.encode("https://chart.googleapis.com/chart?cht=p3&chd=t:#{@mens},#{@womans}&chs=250x100&chl=Mens|Womans")).to_s
    img = open(img)
  end

end

It’s a simple ruby code, very easy to understand (I guess). In the next post I will show you how to send this report to client using Rails.

Categories: API, Gems, Ruby Tags: , , ,

Validates password strength in Rails app

13, dezembro, 2011 Sem comentários

Hello guys,

In the last weekend I finished a rubygem to validate the password strength. It’s a very simple gem, the code are available at github

To install:

gem install password_strong

It’s very simple to use, just add verify_strong in the attribute.

Example:

class User < ActiveRecord::Base

  verify_strong :password

end

In the future I gonna work in client side validation. Feel free to contribute.

Categories: Rails, Ruby Tags: , , ,

Creating custom middlewares with Rack

12, dezembro, 2011 Sem comentários

To kick off, What is Rack?

A Rack applications is a object that has a methods named ‘call’ and that method receive the enviroment as a argument and return a array with exactly three values: status, header and body.

The following is a simple example:


class App
  def call(env)
    [200, {"Content-Type" => "text/plain"},["LucasAllan.com"]]
  end
end

Rack is the base of a lot of web frameworks written in Ruby, like Ruby On Rails, Sinatra, Camping and others…

What is a Rack Middleware?

Rack middleware is a kind of filter to requests in a Rack application. It behaves like a rack application and needs the same things that a simple rack application. It’s like a rack application inside another rack application.

I created a file named cache_control.rb with the follow code:

require 'rack/utils'

module Rack

  class CacheControl
    include Rack::Utils

    def initialize(app)
      @app = app
    end

    def call(env)
      status, headers, body = @app.call(env)
      headers = Utils::HeaderHash.new(headers)
      headers['Cache-Control'] = "no-cache"
      [status, headers, body]
    end
  end
end

In that code, I get the enviroment (with headers, content and http code) and I can manipulate it. In that case I just added a new header.

Now in my Rack Application I will load that middleware and use it.

require 'rack'
require 'cache_control'

class App
  def call(env)
    [200, {"Content-Type" => "text/plain"},["LucasAllan.com"]]
  end
end

use Rack::CacheControl
run MyApp.new

I used the word ‘use’ to call my middleware.

You can run this app using the Thin server, for this you must have the Thin installed: gem install thin

And use the follow command:
You the file name of your application is config.ru (Rack standard), use it:

thin -R config.ru start

If don’t, replace config.ru for the right filename.

You can try to access the application using your browser or curl:

curl -i localhost:3000

HTTP/1.1 200 OK
Content-Type: text/plain
Cache-Control: no-cache
Connection: close
Server: thin 1.3.1 codename Triple Espresso

LucasAllan.com

Categories: Rack, Ruby Tags: ,

Integrations tests and Devise Login

27, outubro, 2011 Sem comentários

Yesterday I started doing a new project using devise gem to manage login features. When I started to do integration tests using rspec, I found a problem: devise test helpers doesn’t work with rspec integration test.
So this is a quick solution to fix this.

require 'spec_helper'
include Warden::Test::Helpers

describe "UserDashboards" do

  before(:each) do
    @user = Factory.create(:user)
    login_as @user, :scope => :user
  end

  it "should access dashboard" do
    visit users_dashboard_path
    page.should have_content("dashboard")
  end
end

At top of spec file, after require ‘spec_helper’ include Warden::Test::Helpers. And in the before(:each) block I just used a warden helper to do login.

Rails 2.3.10 on App Engine

26, dezembro, 2010 Sem comentários

Durante esse feriado de natal, estive testando o suporte a JRuby no Google App Engine. Conseguir rodar tanto uma aplicação feita com Sinatra quanto uma feita em Rails 2.3.10. Infelizmente a gem google-appengine ainda não suporta o Rails 3, mas esse suporte já está sendo desenvolvido.

Então pesquisando no Github achei um gist mostrando como gerar uma aplicação com Rails 2.3.10 e DataMapper, infelizmente não funcionou como deveria. Mas ao analisar percebi que o problema era não está incluindo o DataMapper::Resource no model, então fiz um fork do gist e modifiquei, testei e agora tudo está funcionando. Para acessar o gist clique aqui e divirta-se.

Categories: Gae, Java, JRuby, Rails, Ruby Tags: , , , , ,

Pesquisa avançada com MongoMapper, simulando um “like %”

3, agosto, 2010 Sem comentários

Esse post é uma “continuação” do anterior, estarei demonstrando como fazer uma query no “like %” no MongoDb, utilizando a gem MongoMapper

Como no post anterior, eu tenho o model “Person”:

class Person
  include MongoMapper::Document
  key :name, String
  key :middle_initial, String
end

E eu preciso encontrar todos os registros (no caso do Mongodb, documentos) que contenham o nome “Silva” em ‘name’, podendo ter vários Silva’s, como: “João da Silva”, “Maria Silva” e etc…

A solução, mais uma vez, é simples:

Person.all("$where" => "function() { return this.name.match(/"Silva"/i)"})

Pesquisa avançada com Mongoid, simulando um “like %”

1, agosto, 2010 Sem comentários

Comecei semana passada a utilizar o Mongodb (utilizando a biblioteca mongoid) em um novo projeto que estou desenvolvendo. Embora a documentação do Mongoid seja excelente, tive problemas para utilizar uma query com o ‘like %%’ de pesquisa como eu utilizava em bancos de dados relacionais.
A solução que eu encontrei foi utilizar uma Regex no parâmetro de busca.
Imagine que eu tenho um model chamado Person, como o abaixo:

class Person
  include Mongoid::Document
  field :name
  field :middle_initial
end

E eu preciso encontrar todos os registros (no caso do Mongodb, documentos) que contenham o nome “Silva” em ‘name’, podendo ter vários Silva’s, como: “João da Silva”, “Maria Silva” e etc…

A solução é simples:

Person.find(:all, :conditions => {:name => Regexp.new("Silva")}).entries

Então será retornado um array contendo todos os documentos com o termo “Silva” no nome.

Categories: Mongodb, NoSql, Rails, Ruby Tags: , , , ,

Iniciando no desenvolvimento de aplicações Desktop com Qt e Ruby

26, julho, 2010 2 comentários

Esse post é o inicio de uma série que estou preparando sobre desenvolvimento desktop com Ruby. Para quem não sabe o Qt é um framework para desenvolvimento de aplicações Desktop muito utilizado pelo comunidade OpenSource. E já provou sua eficácia em grandes projetos. Foi desenvolvido originalmente pela empresa e mais tarde adquirido pela Nokia. Nesse exemplo, será desenvolvido uma simples aplicação “Hello World!” e no futuro aprofundaremos mais no assunto.

require 'Qt4'

app = Qt::Application.new(ARGV)

hello = Qt::PushButton.new('Hello World!')
hello.resize(100, 30)
hello.show()

app.exec()
Categories: QT, Ruby Tags: ,

Utilizando o is_paranoid

13, junho, 2010 2 comentários

O is_paranoid é uma gem que faz com que os registros do banco não sejam apagados através do método destroy. Ao chamar o método destroy nosso objeto é apenas marcado como apagado e pode ser restaurado posteriormente, bem como listado através de método fornecidos pelo is_paranoid.
Sua utilização é bem simples, primeiro instale a gem:

gem install is_paranoid

Para que funcione em sua aplicação Rails, adicione no enviroment.rb , dentro do bloco de inicialização:

config.gem "is_paranoid"

Deixando mais ou menos assim:

Rails::Initializer.run do |config|
  # ...
  config.gem "is_paranoid"
end

Agora, nos models que vão utilizar dos recursos do is_paranoid, adicione logo após a declaração da classe ‘is_paranoid’

Exemplo:

class Student < ActiveRecord::Base
  is_paranoid
end

E para finalizar, crie uma migrate que adicione na tabela que vai utilizar o is_paranoid, o campo ‘deleted_at’, do tipo ‘timestamp’.

Exemplo:

class AddIsparanoidInStudent < ActiveRecord::Migration
  def self.up
    add_column :students, :deleted_at, :timestamp
  end

  def self.down
    remove_column :students, :deleted_at
  end
end

Pronto! Se quiser saber mais sobre o is_paranoid, consulte a documentação oficial no site do projeto.

Categories: Dicas, Rails, Ruby Tags: , ,

Remember password com restful_authentication

10, abril, 2010 2 comentários

O restful_authentication é um plugin de autenticação para aplicativos ruby on rails, com excelentes recursos, super fácil de configurar. Enfim, não vou falar muito sobre ele, pois não é o propósito desse tutorial. Irei assumir que você já tem o restful_authentication funcionando e quer apenas adicionar a funcionalidade de enviar um código de reset password via email para o usuário que esqueceu sua senha. Ao acessar o link com esse código o sistema irá exibir uma tela de troca de senha, lembrando que esse código deverá ser único e poderá ser usado somente uma vez. Então vamos lá:

Primeiro iremos gerar uma migration que adiciona na tabela o usuário a coluna ‘reset_password_code’.

script/generate migration reset_password_code

Agora editarei a migration gerada, deixando da seguinte forma:

class ResetPasswordCode < ActiveRecord::Migration
  def self.up
    add_column :users, :reset_password_code, :string
  end

  def self.down
    remove_column :users, :reset_password_code
  end
end

em seguida, ‘rake db:migration’ e estaremos pronto para começar!

Na classe UsersController irei criar um método protected que irá gerar um código para ser enviado ao usuário.

protected
  def random_code( len = 40 )
    chars = (("a".."z").to_a + ("1".."9").to_a )- %w(i o 0 1 l 0)
    newpass = Array.new(len, '').collect{chars[rand(chars.size)]}.join
  end

Agora criarei o método que chamará a view com o campo para o usuário colocar seu email:

  def change_reset_password
  end

Agora criarei a view que receberá o endereço de email do usuário e chamará o método “reset_password” passando o email:

<p>
    <%= form_tag (:controller => 'users', :action => 'reset_password' ) %>

    <p>
        <%= label_tag 'Email' %>
        <br/>
        <%= text_field_tag (:email) %>
    </p>
    <p>
        <%= submit_tag 'Enviar' %>
    </p>
    <%= flash[:alert] %>
</p>

Já método reset_password, irá receber o email, procurar o usuário com esse email, gerar o código de reset password, e chamar o UserMailer para enviar o email com o código.

  def reset_password
    user = User.find_by_email(params[:email])
    unless user.nil?
      user.reset_password_code = random_code
      if user.save!
        UserMailer.deliver_new_password(user)
        flash[:done] = "Verifique seu email para trocar a senha"
        redirect_to ('/')
      else
        flash[:error] = "Erro ao efetuar trocar de senha"
        render :action => 'change_reset_password'
      end
    else
      flash[:error]  = "Email Inválido"
      render :action => 'change_reset_password'
    end
  end

Vejam que estou chamando “UserMailer.deliver_new_password(user)” e passando o usuário como parâmetro. Na classe ‘UserMailer’ devo criar o método ‘new_password’ que será usado para enviar o email.
Meu método new_password deverá ficar assim:

  def new_password(user)
    setup_email(user)
    @subject    += 'Mudança de senha'
    @body[:url]  = "#{$SERVER_CONTENT_BASE}/password/#{user.reset_password_code}"
  end

Agora criarei a view para esse email, dentro de ‘app/views/user_mailer’ com o nome de ‘new_password.html.erb’

Olá <%=h @user.login %> alguém solicitou a troca de senha para essa conta.
Se deseja realmente trocar sua senha, clique no link abaixo:
<%=h @url %>

Agora de volta ao UsersController, criarei o método que recebe o reset_code e se ele estiver correto será jogado em um campo hidden na view de troca de senha.

  def code_password_reset
    user = User.find_by_reset_password_code(params[:reset_code])
    if user.nil?
      flash[:error]  = "Código inválido"
      redirect_to ('/')
    else
      @reset_code = params[:reset_code]
      render :action => "new_password"
    end
  end

Criarei a view de troca de senha, chamada ‘new_password’

<p>
    <%= form_tag (:controller => 'users', :action => 'reset_password_update', :method => 'put' ) %>
    <p>
        <%= label_tag 'Nova Senha' %>
        <br/>
        <%= password_field_tag (:password) %>
    </p>
    <p>
        <%= label_tag 'Confirmação' %>
        <br/>
        <%= password_field_tag (:password_confirmation) %>
    </p>
    <%= hidden_field_tag(:reset_code, @reset_code) %>
    <p>
        <%= submit_tag 'Enviar' %>
    </p>
	<%= flash[:alert]%>
</p>

E agora o método que de fato executa a troca de senha:

  def reset_password_update
    @user = User.find_by_reset_password_code(params[:reset_code]) unless params[:reset_code].blank?
    if ((params[:password] == params[:password_confirmation]) && !params[:password_confirmation].blank?)
       @user.password_confirmation = params[:password_confirmation]
       @user.password = params[:password]
       @user.reset_password_code = nil
      if @user.save!
        flash[:done] = "Senha atualizada com sucesso!"
        redirect_to ("/")
      else
        flash[:alert] = "Falha ao atualizar senha."
        render :action => 'new_password'
      end
    else
      flash[:alert] = "Senhas diferentes!"
      render :action => 'new_password'
   end
  end

Para finalizar iremos configurar as rotas;

  map.resources :users, :collection => { :change_reset_password => :get,
                                         :new_password => :get, :reset_password_update => :post,
                                         :code_password_reset => :get, :reset_password => :get}
  map.connect 'password/:reset_code', :controller => 'users', :action => 'code_password_reset'

E assim chegamos ao fim desse tutorial.