Na outra semana eu fiz um webcast sobre IronRuby com o Alessandro Binhara, do Mono Brasil. Ele falou de IronPython e bastante de DLR, e eu foquei no IronRuby. Fiz algumas demos bem interessantes, incluindo algumas que mostrei aqui no blog, já que tenho falado bastante de IronRuby por aqui. O webcast fez parte da semana de interoperabilidade do MSDN, e foi muito bem, como vocês podem ver nesse e-mail do Rodrigo Dias da Microsoft publicado no Mono Brasil.

O webcast começou com o Binhara falando por uns 40 e poucos minutos sobre Python e DLR, e depois eu encerrei com mais 40 minutos de Ruby. Foi uma hora e meia de webcast!

Aqui estão os recursos da palestra:

Clique aqui para assistir à gravação.

Links da palestra:

  1. Ruby language
  2. IronRuby
  3. IronRuby.info
  4. IronRuby no Codeplex
  5. John Lam
  6. Jimmy Schementi
  7. Rails
  8. RSpec
  9. Cucumber
  10. Ruby Inside

Postado na(s) categoria(s) IronRuby , Eventos pelo Giovanni Bassi em 3 de fevereiro de 2010 às 02:47 | Tags: ,

image[1]

Este é o quinto post sobre IronRuby. Veja os anteriores:

  1. Rodando Ruby com C#: Parte 1
  2. Rodando Ruby com C#: Parte 2 – chamando uma classe Ruby no C#
  3. Rodando Ruby com C#: Parte 3 – chamando uma classe C# a partir do Ruby
  4. Rodando Ruby com C#: Edição especial: ASP.Net MVC 2.0, .Net 4.0 e Visual Studio 2010

Este é o post que eu queria escrever desde o começo. Nele vou mostrar um exemplo de uso real do IronRuby na sua aplicação, vou jogar uma idéia, que vai dar a vocês muitas outras idéias.

A idéia é que tenho uma aplicação feita com C#, mas tenho um pequeno pedaço da minha regra de negócios que quero deixar o usuário editar. Uma opção alternativa seria criar um formulário onde o usuário poderia tentar compor uma regra com textboxes, checkboxes e outros controles, e funcionaria, só que eu limitaria a liberdade do usuário na criação da regra. Com IronRuby posso dar o potencial do cliente escrever a regra em código.

Observação: A princípio eu ia fazer com ASP.Net MVC, usando C#. Por algum motivo não está rodando. Os testes funcionam, e funciona com uma aplicação console, mas não funciona com ASP.Net, seja MVC ou Webforms. Se alguém quiser testar, e não funcionar, votem lá no Codeplex para que o time possa olhar. O bug está aqui. Clique aqui para baixar a solution para testar. O projeto original com MVC está lá, assim como o de WebForms.

Como ficou o projeto:

Criei uma camada de apresentação em console app, só com C#, uma camada de domínio com C# e IronRuby, e os testes, só em C#, e às vezes passando código em IronRuby para testar.

Criei um sistema de pedidos. O cliente pode solicitar um pedido. Vejam as entidades:

Dessas, vale a pena ver a de pedido:

public class Pedido
{
    public Cliente Cliente { get; set; }

    public Pedido(Cliente cliente)
    {
        if (cliente == null)
            throw new InvalidOperationException("Cliente não pode ser nulo.");
        Cliente = cliente;
    }

    private List<ItemPedido> _itens = new List<ItemPedido>();

    public void Adicionar(ItemPedido itemPedido)
    {
        _itens.Add(itemPedido);
    }

    public IEnumerable<ItemPedido> Itens { get { return _itens; } }

    public decimal Valor
    {
        get
        {
            return _itens.Sum(i => i.Quantidade * i.Produto.Preco);
        }
    }

    public int Id { get; set; }
}

As classes do projeto são simples, sem grandes comportamento, praticamente só getters e setters. A classe de pedido é mais esperta e expõe apenas os itens como um Enumerable, mas só permite incluir itens através de seu método.

Há dois serviços também:

O ServicoCriacaoDePedido cria pedidos com o método Criar, passando a eles um objeto de valor chamado de CriarPedido:

Ele então retorna um pedido criado.

O serviço mantém ainda na propriedade RegrasPosCriacaoDoPedido uma lista estática de regras que acontecem após a chamada de criação do pedido.  Você pode criar regras chamando o método Incluir, e pode limpá-las chamando o método Limpar.

Quando o serviço criar um pedido, ele submete o pedido ao método privado RodarRegraSobreOPedido. É lá que as regras são aplicadas. As regras podem ser envio de e-mails, descontos, etc. Vejam a classe de regras:

public abstract class AposCriacaoPedido
{
    public AposCriacaoPedido()
    {
        Id = Guid.NewGuid();
    }
    public abstract void Rodar(Pedido pedido);
    public string Codigo { get; set; }
    public Guid Id { get; set; }
}

Tem um método rodar, que recebe um pedido e é abstrato, ou seja, vai ter que ser implementado por clases herdeiras. É neste método que acontece a regra. A classe tem ainda um Id para identificação. A parte onde você percebe que há algo diferente é na propriedade Codigo. É lá que fica o código do IronRuby. Ele fica lá apenas para referência, já que, vocês verão em breve, teremos classes IronRuby filhas desta classe.

É aí que entra o serviço de criação de regras, a outra classe de serviços, a da direita. Ela tem somente um método público chamado CriarRegraPosCriacaoPedido. Bamos vê-lo:

public AposCriacaoPedido CriarRegraPosCriacaoPedido(string codigo)
{
    const string templateDoMetodo =
        @"
        include RegrasDinamicas::Model
        class {0} < AposCriacaoPedido
            def Rodar(pedido)
                {1}
            end
        end";

    var nomeClasseTemp = "AposCriacaoPedido_" + Guid.NewGuid().ToString().Replace("-", string.Empty);
    var codigoCompleto = string.Format(templateDoMetodo, nomeClasseTemp, codigo);
    _engine.Execute(codigoCompleto, _scope);
    var classe = _runtime.Globals.GetVariable<RubyClass>(nomeClasseTemp);
    var retornoCriacao = _operations.CreateInstance(classe);
    var aposCriacaoPedido = (AposCriacaoPedido)retornoCriacao;
    aposCriacaoPedido.Codigo = codigo;
    return aposCriacaoPedido;
}

Notem que este método cria com código Ruby uma classe com nome aleatório. O template desta classe é uma string, que possui dois placeholders. O zero é o nome da classe, gerado via Guid, e colocado na variável nomeClasseTemp para depois ser substituído no template. O placeholder 1 é o corpo do método da regra, passado pelo usuário, e que fica na variável codigo. O código completo fica na variável codigoCompleto. A classe gerada herda da classe de regras, e portanto pode ser instanciada e feito cast dela de uma classe dinâmica do Ruby para a classe do C#. A partir daí, a classe de regra está gerada. Ela recebe na propriedade Codigo o código passado pelo usuário, e é então repassada para o chamador, que a coloca na coleção estática de regras do serviço de criação de pedidos, que a aplica sempre que um pedido é criado.

O resto desta classe de serviço é código de infra que já vimos nos outros posts.

Tem mais uns negócios interessantes no projeto, como repositórios, e um padrão MVC para escrita na console. Vale a pena dar uma olhada.

A partir daí é só utilizar. Vejam o controller de regras (um pouco resumido):

class RegrasController : IRegrasController
{
    private IList<AposCriacaoPedido> _regras;
    private IRegrasView _regrasView;
    private readonly ServicoCriacaoDeRegras _servicoCriacaoDeRegras = new ServicoCriacaoDeRegras();

    public RegrasController(IRegrasView regrasView)
    {
        _regrasView = regrasView;
    }

    public void ExibirRegras()
    {
        if (_regras == null)
            _regras = ServicoCriacaoDePedido.RegrasPosCriacaoDoPedido.ToList();
        var proximaAcao = _regrasView.Listar(_regras);
        proximaAcao(this);
    }

    public void CriarNova()
    {
        var proximaAcao = _regrasView.ExibirNova();
        proximaAcao(this);
    }

    public void CriarNova(string codigo)
    {
        var regra = _servicoCriacaoDeRegras.CriarRegraPosCriacaoPedido(codigo);
        ServicoCriacaoDePedido.IncluirRegraPosCriacaoDoPedido(regra);
        _regras = null;
        ExibirRegras();
    }

    public void ExibirRegra(int posicaoSelecionada)
    {
        if (posicaoSelecionada == -1)
            return;
        var pedido = _regras[posicaoSelecionada];
        var proximaAcao = _regrasView.ExibirRegra(pedido);
        proximaAcao(this);
    }
}

Posso listar as regras, que passa pelo método ExibirRegras:

Posso listar uma regra:

Notem no método CriarNova, que o serviço de regras é utilizado. Isso me permite criar uma regra (com multi line):

E entao executá-la ao inserir um pedido:

Note a mudança no preço. Ao alterarmos o preço de um produto, todos os pedidos mudam (pequeno erro de modelagem…).

O código está disponível para vocês baixarem. Depois vou postar sobre o MVC que usei no projeto, que achei que ficou interessante.


Postado na(s) categoria(s) IronRuby pelo Giovanni Bassi em 2 de fevereiro de 2010 às 03:00 | Tags: , , ,

image[1]

Esta é uma edição especial da série de IronRuby com C#. Este seria o quarto post. Vejam os anteriores:

  1. Rodando Ruby com C#: Parte 1
  2. Rodando Ruby com C#: Parte 2 – chamando uma classe Ruby no C#
  3. Rodando Ruby com C#: Parte 3 – chamando uma classe C# a partir do Ruby

Nesse eu vou pegar uma tarefa maior: vou colocar pra rodar o IronRuby com ASP.Net MVC 2.0, .Net 4.0, e usando o Visual Studio 2010.

O que você vai precisar:

  1. IronRuby CTP para .Net 4 Beta 2
  2. Visual Studio 2010 Beta 2
  3. A solução do projeto (sem incluir o banco Northwind)

O trabalho está baseado no que já havia sido desenvolvido pelo Jimmy Schementi. Eu não criei tudo do zero, simplesmente evolui uma idéia muito boa que já existia. Boa mas bastante desorganizada. Encontrei muito código incompleto, ou que não fazia nada. Gastei um bom tempo limpando o projeto, reorganizando, removendo arquivos desnecessários, refatorando. Atualizei todas as referências, do IronRuby, do .Net, das bibliotecas de testes, enfim, todas estão com as últimas versões disponíveis neste momento. Não está 100% do jeito que eu gostaria, mas está bom o suficiente para ser entendido.

A solução funcionando:

Home Page:

Home Page

Tela de categoria de produtos:

Tela de categoria de produtos

Selecionando uma categoria os produtos desta categoria são exibidos:

Selecionando uma categoria os produtos desta categoria são exibidos

Editando um produto:

Editando um produto

Tela de Login (não tem master page):

Tela de Login (não tem master page)

Aqui está a solução no Visual Studio 2010, notem os arquivos .rb e .erb, arquivos Ruby, responsáveis pela execução:

Solution Explorer

Há três projetos: um de teste (IronRubyMvcLibrary.Tests), um de web (IronRubyMvcWeb), e um de infraestrutura (IronRubyMvcWeb.Core). O projeto de infraestrutura, que vocês podem ver lá embaixo do Solution Explorer contém todo o código necessário para integrar o ASP.Net MVC e o IronRuby.

Vou mostrar neste post as bases de como funciona o projeto MVC. O projeto de infra fica para outro dia.

O projeto é um projeto de ASP.Net MVC 2 comum do Visual Studio 2010. O projeto é baseado fortemente em convenções. Para registrar as rotas, você coloca um arquivo rotas.rb na raiz. O meu usa o caminho padrão de rotas. Vejam:

#default routes
$routes.ignore_route("{resource}.axd/{*pathInfo}");
$routes.map_route("default", "{controller}/{action}/{id}", {:controller => 'Home', :action => 'index', :id => ''})

O web.config é um web.config normal, não foi alterado em nada específico.

O modelo

O modelo é baseado em LINQ to SQL para obter os dados, que claro, é baseado em um banco de dados Northwind.

Modelo LINQ to SQL

Ainda que existam 4 classes definidas, só produtos e categorias estão sendo usadas. Não vou entrar em detalhes do LINQ to SQL, até porque quase ninguém hoje em dia começa projeto com LINQ to SQL.

O projeto utiliza o padrão repositório. Uma classe IronRubyRepository, feita em C#, define os métodos de obtenção dos dados. Vejam aqui alguns deles (ocultei pedaços da classe por brevidade):

public class IronRubyRepository 
{
    private readonly NorthwindDataContext _dataContext;

    public IronRubyRepository () : this(new NorthwindDataContext()){}

    public IronRubyRepository(NorthwindDataContext dataContext)
    {
        _dataContext = dataContext;
    }

    public virtual IQueryable<Category> Categories
    {
        get { return _dataContext.Categories; }
    }

    private Category GetCategoryByName(string name)
    {
        return Categories.SingleOrDefault(c => c.CategoryName == name);
    }
    //abreviada por brevidade
}

E uma classe ProductsRepository, definida em Ruby, herda dela:

require 'helpers/model'

class ProductsRepository < IronRubyRepository
end

Viram o require 'helpers/model'? Ele indica que precisamos do arquivo model.rb do diretório helpers. Nele estão umas declarações de importações de namespaces .Net:

include IronRubyMvcWeb::WebApp::Models
include IronRubyMvcWeb::WebApp::Models::Northwind

O ProductsRepository simplesmente herda do IronRubyRepository, e não muda nada. Ele vai ser usado no controller de produtos. Temos ainda um arquivo de modelo para a Home, o HomeModel.rb:

class HomeModel
  def salutation
    "ASP.NET MVC <3 IronRuby!!!"
  end
end

Os controllers

Os controladores são definidos diretamente em Ruby. Há toda uma infraestrutura por trás, que vou discutir outro dia. Basicamente eles herdam de uma classe base Controller, que também é definida em Ruby no projeto de Infra. Abaixo vocês vêem o HomeController, também editado por brevidade. Nele há ação “index” para a página principal, e as ações para fazer o login, que na verdade só está simulado (autenticação ainda não está integrada). Notem que a  ação index coloca um item no view data, e chama o método view, passando nulo para o nome da view, “layout” para o nome da master page, e um novo modelo HomeModel.

require "HomeModel"
require 'MyFilter'

class HomeController < Controller
  
  def index
    view_data['salutation'] = "Hello there!"
    view(nil, 'layout', HomeModel.new)
  end
  
  def validation    
    view  
  end


  def validate
      #simple validation, just to prove a point
    if (params[:username] != "giovanni" || params[:password] != "brazil")
        model_state.add_model_error("username".to_clr_string, "You must specify a username.") 
        model_state.add_model_error("password".to_clr_string, "You must specify a password.") 
        model_state.add_model_error "_FORM", "The current password is incorrect or the new password is invalid."
        view 'validation', nil
    else
        redirect_to :action=>"index"
    end
  end
  
  #editado por brevidade
end 

O controlador de produtos é mais interessante. Ele interage com o repositório, também um pouco cortado por brevidade:

require 'ProductsRepository'

class ProductsController < Controller
  
  def index
    repository = ProductsRepository.new    
    @categories = repository.categories
    view nil, 'layout', @categories
  end
  
  def list
    @category = params[:id]    
    repository = ProductsRepository.new
    @products = repository.get_products_for_category @category    
    view nil, 'layout', nil
  end
  
  def edit
    @id = params[:id]    
    repository = ProductsRepository.new
    @product = repository.get_product @id
    view nil, 'layout', nil
  end
  
  def update
    id = params[:id]
    category = params[:category_name]    
    repository = ProductsRepository.new
    @product = repository.get_product id
    @product.product_name = request.form.get_Item('Product.productname')
    @product.unit_price = to_decimal request.form.get_Item('Product.unitprice')
    repository.submit_changes    
    redirect_to 'list', {:id => category }
  end
  
  def to_decimal(value)
      System::Convert::ToDecimal value
  end
end

Vejam que o código é extremamente simples. A única diferença nos métodos é que todas as letras são minusculas e separadas por underscore, de resto é muito parecido com um código C#. Não vou explicar mais, acho que o código fala por si só.

 

As views

O ViewEngine foi feito sob medida. Há todo um mecanismo para exibir as views e as master pages, muito parecido com uma view aspx. Vejam aqui a view da ação index do controlador Home:

<div class="main">
  <p>
    The following message is brought to you by the 
    <code>salutation</code> property of the Ruby <code>HomeModel</code>
    object within <code>/Models/HomeModel.rb</code>.
  </p>
  <blockquote>
    <p>
      <strong class="salutation">
        <%= model.salutation %>
      </strong>
    </p>
  </blockquote>

  <p>
    And the following message is brought to you by the view data.
  </p>
  <blockquote>
    <p>
      <strong class="salutation">
        <%= view_data['salutation'] %>
      </strong>
    </p>
  </blockquote>

  <% 8.times do |i| %>
    Testing Loop <%= i %><br />
  <% end %>
  <%= html.render_partial("partial", "my model!") %>
  <p>
    Click on <strong>
      <%= html.action_link("Products", "index", "products") %>
    </strong> to get started.
  </p>
</div>

Na linha 10 ele exibe o valor do modelo e na linha 21 do view data. Na linha 29 há uma chamada a uma view parcial chamada “partial”, e o modelo “my model!” é passado. Vejam no solution explorer que tipo de view é essa. É uma view aspx. Aqui está ela:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<h2>Hello from <%=ViewData.Model%> in .aspx land!</h2> 

E ela integra no código exibido na view de Ruby. Interessante, não é?

Da mesma forma, a view de validação, aquela que não tem master page, é uma view aspx também.

E aqui está o código da master, que vem do arquivo views/shared/layout.html.erb (editada por brevidade):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>IronRuby on ASP.NET MVC Demo</title>
    <link rel="stylesheet" type="text/css" href="/content/style.css" media="screen" />
</head>
<body>
    <div id="wrap">
        <div id="header">
            <h1><%= html.ActionLink("ASP.NET MVC w/ IronRuby Demo", {:controller => "Home", :action => "index"}) %></h1>
            <h2>DLR and ASP.NET MVC BFF Edition</h2>
        </div>

        <div id="menu">
            <ul>
                <li><%= html.ActionLink("Login", {:controller => "Home", :action => "Validation"}) %></li>
                <li><%= html.ActionLink("Home", {:controller => "Home", :action => "index"}) %></li>
                <li><%= html.ActionLink("Products", {:controller => "Products", :action => "index"}) %></li>
            </ul>
        </div>

        <div id="content">
            <div class="main">
                <% yield %>
            </div>
        </div>

        <div id="bottom"></div>

    </div>
</body>
</html>

Vejam o yield na linha 24. É lá que é inserida a página na master. Notem também que os html helpers funcionam perfeitamente, nas linhas 16 a 18, e que, ao invés de usar objetos anônimos como no C#, no Ruby usa-se símbolos.

Toda a iteração de postbacks funciona perfeitamente, e você pode editar os arquivos ruby (controller, model, view, etc) sem precisar recompilar a aplicação, já que no Ruby é tudo interpretado. Na prática a experiência de trabalhar com ASP.Net MVC utilizando IronRuby é muito parecida com a de utilizar C#. Fica uma opção, caso o Ruby se mostra uma opção mais adequada para atender algum cenário específico.

No próximo post farei a segunda parte, explicando como foi feito para tudo funcionar, vou explicar o projeto do infra. Ou você se adianta, baixa a solução, lê o código e entende.

O que você achou? Vale a pena fazer um projeto com ASP.Net MVC e IronRuby? Ou pedaços dele?


Postado na(s) categoria(s) IronRuby pelo Giovanni Bassi em 13 de janeiro de 2010 às 03:35 | Tags: , ,

image[1] 

Semana que vem, na semana de interoperabilidade, vou participar fazendo um webcast sobre IronRuby. Vou fazer junto com o Alessandro Binhara, que vai falar de IronPython. Vão ser 90 minutos de Iron. Vai ser dia 22, sexta-feira, às 17 horas.

Pra se inscrever é só clicar aqui.

Até lá.


Postado na(s) categoria(s) IronRuby pelo Giovanni Bassi em 12 de janeiro de 2010 às 08:21 | Tags: ,

image[2]

Esse é o terceiro post sobre como rodar Ruby no .Net, com IronRuby, e integrado ao C#. Estou usando o Visual Studio 2010 que é onde as coisas funcionam mais bem integradas, mas o primeiro post dá pra trabalhar ainda com o Visual Studio 2008. Os posts anteriores estão aqui:

  1. Rodando Ruby com C#: Parte 1
  2. Rodando Ruby com C#: Parte 2 – chamando uma classe Ruby no C#

No primeiro post eu mostrei como configurar o ambiente, e no post seguinte executamos código Ruby via .Net, inclusive passando parâmetros, e pegamos o retorno e utilizamos no C#. Utilizamos classes Ruby no C# normalmente com as novas capacidades dinâmicas do C# 4.

Neste post vou mostrar como fazer o contrário: tenho uma classe no C# que quero ser capaz de chamar a partir do Ruby. Isso é possível, vamos ver como.

Primeiro vou definir a classe que quero chamar do C#. Segue o mesmo molde das classes de antes, ela tem só um método que recebe dois parâmetros, e retorna uma string de acordo com os argumentos recebidos:

public class Teste
{
    public string Chamar(bool flag, string texto)
    {
        return flag ?
            texto + "sufixo" :
            texto;
    }
}

Quero chamar o método “Chamar” desta classe a partir do Ruby. Para poder fazer isso, preciso dizer pra ele referenciar minha dll de alguma forma. No Ruby, a maneira que você usa pra ele acessar outros arquivos Ruby é com a palavra chave “require”. Se você escrever “require MeuArquivo” o Ruby vai tentar encontrar o arquivo “MeuArquivo.rb” nos diretórios especificados na variável $LOAD_PATH, que normalmente inclui o diretório local (.). Pra saber quais são esses diretórios basta inspecionar a variável:

Console Ruby

No IronRuby, além de procurar arquivos .rb, o require vai procurar também dlls. Então você precisa acrescentar uma linha de require com o nome da sua DLL.

O código Ruby então fica assim:

require 'IronRubyNetFX4Test1'
IronRubyNetFX4Test1::Teste.new

Na primeira linha eu referencio meu assembly de testes, que é chamado IronRubyNetFX4Test1.dll. Na linha seguinte eu crio a classe Teste que havia especificado. Notem que os dois pontos duplos :: separaram a especificação do namespace e da classe. Como no Ruby a última linha sempre retorna o resultado, a classe Teste do C# está sendo retornada. O objeto retornado é entendido pelo C# como um objeto dinâmico, e pode ser chamado. Vejam o teste todo:

[TestMethod]
public void ConsigoCriarUmObjetoDotNetEChamarUmMetodoDinamicamenteUsandoONomeCompletoDoTipoEVariavelDinamica()
{
    var source = @"
        require 'IronRubyNetFX4Test1'
        IronRubyNetFX4Test1::Teste.new";

    var scriptSource = _defaultScriptEngine.CreateScriptSourceFromString(source);
    var teste = scriptSource.Execute();
    var resultado = teste.Chamar(true, "ttt");
    Assert.AreEqual("tttsufixo", resultado);
}

Mas eu poderia fazer um cast do retorno, já que o tipo retornado é um tipo .Net, e usá-lo normalmente:

[TestMethod]
public void ConsigoCriarUmObjetoDotNetEChamarUmMetodoDinamicamenteUsandoONomeCompletoDoTipoEVariavelEstatica()
{
    var source = @"
        require 'IronRubyNetFX4Test1'
        IronRubyNetFX4Test1::Teste.new";

    var scriptSource = _defaultScriptEngine.CreateScriptSourceFromString(source);
    var teste = (Teste)scriptSource.Execute();
    var resultado = teste.Chamar(true, "ttt");
    Assert.AreEqual("tttsufixo", resultado);
}

Faz mais sentido, se eu sei que o retorno é um tipo conhecido do C#.

O Ruby tem ainda uma palavra chave que faz a importação do namespace, semelhante ao “using” do C#, é o “include”. E nós podemos usá-la também:

[TestMethod]
public void ConsigoCriarUmObjetoDotNetEChamarUmMetodoDinamicamenteUsandoOInclude()
{
    var source = @"
        require 'IronRubyNetFX4Test1'
        include IronRubyNetFX4Test1
        Teste.new";
    var scriptSource = _defaultScriptEngine.CreateScriptSourceFromString(source);
    var teste = scriptSource.Execute();
    var resultado = teste.Chamar(true, "ttt");
    Assert.AreEqual("tttsufixo", resultado);
}

Com isso, fecho os exemplos do Ruby chamando o C#. Já conseguimos fazer código Ruby chamar C#, e vice-versa. A seguir vou mostrar alguns cenários onde penso que isso pode ser útil. Em breve.


Postado na(s) categoria(s) C# , IronRuby pelo Giovanni Bassi em 11 de janeiro de 2010 às 08:14 | Tags: , ,

IronRuby

Feliz ano novo, pessoal! Vamos começar o ano acelerando.

Volto a falar de IronRuby com C#. Este é o segundo post sobre o assunto, e não vou voltar no básico. Para isso leia o primeiro post, onde mostro como configurar o básico dos testes, baixar e configurar o IronRuby, e preparar o resto do ambiente:

  1. Rodando Ruby com C#: Parte 1

Nesse post vou mostrar como criar uma classe no IronRuby e chamar ela no C# 4 com Visual Studio 2010.

A classe Ruby que quero rodar contém apenas um método, e não faz nada de mais:

class Teste2
    def Chamar(flag, texto)
        if !flag
            texto
        else
            texto + 'sufixo'
        end
    end
end 

A idéia é criar uma instância dessa classe e após declará-la, retorná-la, tudo no mesmo script. No Ruby, a última linha retorna o resultado. Pra isso, então basta incluir:

Teste2.new 

Ok, para fazer isso funcionar, é igualzinho o que é feito no post anterior, que fazia uma soma simples:

[TestMethod]
public void ConsigoCriarUmObjetoRubyEChamarUmMetodoDinamicamente()
{
    var source = @"
        class Teste2
            def Chamar(flag, texto)
                if !flag
                    texto
                else
                    texto + 'sufixo'
                end
            end
        end
        Teste2.new";

    var scriptSource = _defaultScriptEngine.CreateScriptSourceFromString(source);
    var teste = scriptSource.Execute();
    //continua...

A linha 17 está iluminada porque ela é quem executa o código. Adivinham qual o tipo da variável “teste”? Um Ruby de pelúcia pra quem disse “dynamic” (mais sobre ela aqui). No exemplo anterior eu fazia cast para inteiro, porque o resultado era um inteiro, produto da soma de 1 mais 2. E agora o resultado é uma classe que só existe no Ruby, e não existe em lugar nenhum no C#, e portanto não pode ser chamada estaticamente. E o C# é uma linguagem estaticamente tipada, ele não conhece a classe Teste2 declarada no Ruby. Só que na versão 4 ele consegue realizar Dynamic Dispatch, enviando a chamada ao método dinamicamente (mais informação sobre Dynamic Dispatch em uma discussão que tivemos no .Net Architects).

Isso significa que consigo chamar quaisquer métodos e propriedades que existam no objeto Ruby. E é isso que faço:

    //continuando...
    var resultado = teste.Chamar(true, "ttt");
    Assert.AreEqual("tttsufixo", resultado);
} 

Na linha 2 estou executando o método “Chamar”, via dynamic dispatch, que existe na classe Teste2, declarada no IronRuby, e executando seu código. Na linha 3 eu verifico se o resultado era o esperado. O código todo do teste fica assim (apenas repetindo para deixar mais claro):

[TestMethod]
public void ConsigoCriarUmObjetoRubyEChamarUmMetodoDinamicamente()
{
    var source = @"
        class Teste2
            def Chamar(flag, texto)
                if !flag
                    texto
                else
                    texto + 'sufixo'
                end
            end
        end
        Teste2.new";

    var scriptSource = _defaultScriptEngine.CreateScriptSourceFromString(source);
    var teste = scriptSource.Execute();
    var resultado = teste.Chamar(true, "ttt");
    Assert.AreEqual("tttsufixo", resultado);
}

E se eu não quiser escrever o corpo do método Ruby no C#, mas defini-lo em outro arquivo? Não tem problema, o ScriptSource sabe executar arquivos também, além de texto puro. Veja este outro teste, onde faço exatamente isso:

[TestMethod]
public void ConsigoCriarUmObjetoRubyAPartirDeUmArquivoEChamarUmMetodoDinamicamente()
{
    var scriptSource = _defaultScriptEngine.CreateScriptSourceFromFile(
        ObterCaminhoArquivo("RubyTeste.rb"),
        Encoding.UTF8);
    var teste = scriptSource.Execute();
    var resultado = teste.Chamar(true, "ttt");
    Assert.AreEqual("tttsufixo", resultado);
} 

O método CreateScriptSourceFromFile lê o arquivo e executa. O arquivo RubyTeste.rb contém praticamente o mesmo código utilizado no teste anterior. Coloquei ele na estrutura do projeto:

image 

Marquei nas propriedades do arquivo o parâmetro “Copy to Output Directory” como “Copy if newer”, o que garante que o arquivo vai estar no mesmo diretório da dll de testes. O método ObterCaminhoArquivo sabe que deve procurar os arquivos Ruby no diretório especificado, olhando na pasta onde a dll está:

private static string ObterCaminhoArquivo(string arquivo)
{
    return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), arquivo);
}

(Fique atento para colocar o encoding correto no arquivo, no meu caso, UTF8, ou vai dar erro na hora de rodar.)

Para executar o script de definição da classe, mas só criar ela quando quisermos é fácil. Aqui está um teste que faz exatamente isso:

[TestMethod]
public void ConsigoExecutarUmArquivoRubyECriarOObjetoDinamicamente()
{
    var scriptCriaClasse = _defaultScriptEngine.CreateScriptSourceFromFile(
        ObterCaminhoArquivo("RubyTeste2.rb"),
        Encoding.UTF8);
    scriptCriaClasse.Execute();
    var scriptInstanciaObjeto = _defaultScriptEngine.CreateScriptSourceFromString("Teste4.new");
    var teste = scriptInstanciaObjeto.Execute();
    var resultado = teste.Chamar(true, "ttt");
    Assert.AreEqual("tttsufixo", resultado);
}

O arquivo RubyTeste2 tem a definição da classe, mas não cria e retorna, ou seja, o retorno é nulo:

class Teste4
    def Chamar(flag, texto)
        if !flag
            texto
        else
            texto + 'sufixo'
        end
    end
end

Na linha 7 do teste eu executo este arquivo, e na linha 9 eu executo a criação da classe. Como o código está executando sob o mesmo contexto, o mesmo ScriptEngine, a definição da classe ainda está no escopo, ele cria uma instância da classe na linha 9 e retorna.

Pelo que andei pesquisando, há outras maneiras de fazer isso, mas só como o método Execute do ScriptSource, e os métodos CreateScriptSourceFromString e CreateScriptSourceFromFile do ScriptEngine você já faz quase toda a interação básica.

Interessante, certo? Já podemos definir arquivos Ruby e executá-los dinamicamente. Será que o IronRuby consegue ele mesmo criar e interagir com objetos .Net? Não perca as cenas do próximo capítulo.


Postado na(s) categoria(s) C# , IronRuby pelo Giovanni Bassi em 4 de janeiro de 2010 às 08:17 | Tags: , ,

IronRuby

Agora o C# traz diversas características dinâmicas, na sua versão 4. Falei semana passada como usar uma delas semana passada, com um leitor de XML dinâmico. Além disso, dá pra fazer diversos outros malabarismos com C# 4 e o dinamismo. Já falei disso aqui, aqui, aqui e aqui.

Mas tem uma coisa que não dá pra fazer ainda de maneira muito simples, que é compilar código C# dinamicamente. Até dá pra fazer, mas dá um trabalho violento. Você tem que usar as classes do compilador do C# disponível em Microsoft.CSharp, como a CSharpCodeCompiler, e fazer todo o trabalho de referências, usings, namespaces, e dá um trabalhão que simplesmente não se paga.

O problema vem do fato de o C# não ser uma linguagem que nasceu para ser compilada dinamicamente, aberta desta forma, apesar de estar caminhando para isso. O ideal seria trabalhar uma linguagem que funciona melhor com scripts, mais dinâmica, como o VB. Infelizmente com VB dá o mesmo trabalhão, já que ele é irmão (quase siamês) do C#. Isso não é mais um problema: o .Net agora tem uma linguagem mais adaptada para isso, que é o IronRuby, implementação de Ruby para rodar nativamente no runtime do .Net, assim como o JRuby é a implementação do Ruby para o runtime do Java.

O IronRuby está em versão release candidate e já compila quase toda a especificação do Ruby, rodando os principais frameworks de Ruby, como o Rails (um MVC para web) e o RSpec (framework de BDD). Você pode pegar a versão que funciona com o .Net 3.5, que é o RC1, aqui. Essa versão é numerada como 0.9.3. A versão que vou usar neste post é a 0.9.1, a que tem como o .Net framework 4 Beta 2 (fique atento, há uma versão 0.9.1 que foca no .Net 3.5 também):

Versão do IronRuby

Não vou ficar explicando aqui a sintaxe do Ruby, que é super simples, e tenho certeza que vocês, que gostam de ponto e vírgula e chaves, vão entender. Pra quem quiser ver mais de perto dê uma olhada no tutorial oficial aqui. Eu gosto muito deste tutorial também, e ele é bem mais direto que o oficial.

Vamos ver o que podemos fazer com o Ruby integrado no .Net. Pra começar, baixe a versão que apontei, a que compila com o .Net 4, e baixe, se ainda não baixou (não??), o VS 2010 Beta 2.

Descompacte o zip em C:\ruby. Seu diretório deve ficar assim:

Diretório do ruby 

Não invente de colocar no D:, não invente de colocar debaixo de MyDocuments, ou em qualquer outro lugar. A instalação padrão do Ruby é no c:\ruby, e o Ruby é sensível. Amanhã se você quiser se integrar com a versão original do Ruby, feita em C (chamada de MRI), você vai ter problemas se o IR não estiver neste diretório. Não que não seja impossível colocar em outro lugar, mas se você não gosta de dor de cabeça, acredite em mim, e coloque ele lá, ok? Todos os exemplos do mundo de Ruby em Windows assumem que ele está lá.

Crie um projeto de testes com C# no Visual Studio 2010. Sim, testes. Porque você quer testar o IronRuby, lembra? Nós não testamos com projeto de console, ou Winforms, ou WPF, ou ASP.Net, nós testamos com projetos de testes automatizados, pra ter feedback constante e rápido se fizemos alguma coisa errada. Lembre-se disso, vamos em frente.

Referencie as seguintes dlls do IronRuby e do DLR que vão estar em c:\ruby\bin:

  1. IronRuby.dll
  2. IronRuby.Libraries.dll
  3. Microsoft.Dynamic.dll
  4. Microsoft.Scripting.dll

Em tempo, DLR é o que dá suporte às linguagens dinâmicas e agora faz parte do .Net Framework. O código é aberto e está no Codeplex.

Referencie também Microsoft.CSharp.dll, que deve estar nas suas referências de DLLs .Net. Ele é o assembly que permite usar a palavra chave dynamic, e fornece a infraestrutura de contato com a DLR, entre outras coisas. (Estou esperando desde o Beta 1 essa DLL sumir para dentro do BCL, ou do CLR, mas até agora nada…)

Pronto, infra resolvida. Agora basta fazer os testes.

Crie uma classe de testes, e crie a inicialização do contexto, que basicamente vai consistir em criar o runtime que vai rodar o Ruby. É código padrão, vai ser praticamente sempre igual em toda aplicação. Basicamente a inicialização cria um ScriptRuntime, que define o ambiente de scripting, e então, a partir dele, cria um ScriptEngine, que é quem executa nosso código fonte Ruby. O resto é detalhe. Criei um ScriptEngine estático, que será o padrão, usado por todos os testes. Precisando, podemos criar outro a partir do runtime, se fosse o caso. Ficou assim:

[TestClass]
public class Dado_Um_Contexto_Ruby
{

    private static ScriptRuntime _scriptRuntime;
    private static ScriptEngine _defaultScriptEngine;

    [ClassInitialize]
    public static void E_Um_ScriptRuntime_e_ScripEngine_Padrao_Inicializados(TestContext testContext)
    {
        CriarScriptRuntimeEEnginePadrao();
    }

    public static void CriarScriptRuntimeEEnginePadrao()
    {
        var setup = new ScriptRuntimeSetup();
        setup.LanguageSetups.Add(
            new LanguageSetup(
                "IronRuby.Runtime.RubyContext, IronRuby",
                "IronRuby 1.0",
                new[] { "IronRuby", "Ruby", "rb" },
                new[] { ".rb" }));
        _scriptRuntime = ScriptRuntime.CreateRemote(AppDomain.CurrentDomain, setup);
        _defaultScriptEngine = _scriptRuntime.GetEngine("Ruby");
    }
} 

Com isso, precisamos criar algum código fonte Ruby que execute. Se você abrir a console do IronRuby, disponível no executável c:\ruby\bin\ir.exe, vai poder digitar 1+2 e digitar enter. Vai dar o resultado, assim:

Console do IronRuby

Essa é a instrução mais simples do mundo, uma soma simples.

Que tal testar esse essa instrução? Fica assim:

[TestMethod]
public void Consigo_Somar()
{
    var source = "1 + 2";
    var scriptSource = _scriptEngine.CreateScriptSourceFromString(source);
    var resultado = (int)scriptSource.Execute();
    Assert.AreEqual(3, resultado);
}

Mais simples impossível! Na primeira linha criamos o complicadíssimo fonte, “1 + 2”, que é nosso código Ruby (depois vamos ver códigos mais interessantes, mas esse serve por enquanto). Na segunda linha chamamos o método “CreateScriptSourceFromString” no ScriptEngine e passamos nosso código fonte. Depois executamos, pegamos o resultado e comparamos com o esperado. Rode o teste, vai passar.

Esse é o básico. Nos próximos posts eu vou mostrar pra vocês como criar, com Ruby, um objeto a partir de uma classe definida no próprio Ruby e devolvê-la para o C# manipular, como criar um objeto a partir de uma classe definida em C# e usar ela no Ruby e devolver pro C#, e como chamar métodos de C# para Ruby e vice-versa.

Em tempo, todo esse exemplo rodaria no C# 3. A partir do próximo não vai rodar mais.
E se você gostou do Ruby, e está sentindo falta de uma IDE para te ajudar, dê uma olhada na RubyMine da JetBrains, que é a empresa que faz o Resharper. Já vi o Uncle Bob dizendo que usa, e o Brian Marick, do manifesto ágil, com quem pareei no Ágiles 2009, também usa. Eu tenho usado, e, apesar de não ser um Visual Studio (longe disso), é melhor que o Notepad, ou seus amigos anabolizados como Notepad++, Textmate, etc (que continuam mirrados).

Gostaria de saber se vocês se interessam pelo assunto, ou se encerro ele mais cedo por falta de interesse. Garanto que vou chegar em uma aplicação viável de negócio, mas só mais para o final…


Postado na(s) categoria(s) C# , IronRuby pelo Giovanni Bassi em 14 de dezembro de 2009 às 08:16 | Tags: , ,

Neste sábado o Raphael Molesim e eu, podres depois de enfrentar o Ágiles 2009 e a noite de Floripa, resolvemos resolver um Kata proposto pelo Uncle Bob, e fazer um Coding Dojo de fatoração. O Raphael propôs fazermos em Ruby com RSpec, já que, segundo ele, não dá pra fazer Coding Dojo sem RSpec (deixa ele ir na próxima reunião do .Net Architects que mostramos que ele está enganado).

Enfim, resolvemos o problema em pouco menos de uma hora e depois fizemos uma retrospectiva, conferindo como o Uncle Bob havia resolvido o problema dele, já que ele postou um Powerpoint da solução.

Algumas conclusões da retrospectiva:

  • A solução do Uncle Bob foi muito mais simples que a nossa, já que resolvemos antes o problema dos números primos, algo que ele não fez (algo que não era necessário, dependendo de como você encara o problema).
  • O Ruby realmente permite programar sem IDE, mas uma IDE decente faz muita falta, principalmente para quem não conhece muito o Ruby ou as APIs do RSpec. Um Notepad anabolizado, como o GEdit, ou o Notepad++, chega só até uma distância, e não é suficiente.
  • RSpec traz uma maneira muito legal de fazer testes. O código fica com uma elegância invejável.
  • O runner do RSpec não permite rodar só o teste que você quiser, e isso não é legal.
  • A performance no IronRuby é sofrível. Chega a ser 50 vezes mais lento que o MRI.

Vejam o que fizemos. Aqui estão os testes do fatorador, que é a classe que faz a fatoração.

require 'fatorador'

describe "Motor calculo fatoracao" do
    it "deve saber ser criado" do
        Fatorador.new
    end

    it "deve retornar 0 se for informado o número 0" do
        fatorador = Fatorador.new
        numeros = fatorador.fatorar 0
        numeros[0].should == 0
    end

    it "deve retornar 1 se for informado o número 1" do
        fatorador = Fatorador.new
        numeros = fatorador.fatorar 1
        numeros[0].should == 1
    end

    it "deve retornar 2 se for informado o número 2" do
        fatorador = Fatorador.new
        numeros = fatorador.fatorar 2
        numeros[0].should == 2
    end

    it "deve retornar 2,2 se for informado o número 4" do
        fatorador = Fatorador.new
        numeros = fatorador.fatorar 4
        numeros[0].should == 2
        numeros[1].should == 2
    end

    it "deve retornar 5 se for informado o número 5" do
        fatorador = Fatorador.new
        numeros = fatorador.fatorar 5
        numeros[0].should == 5
    end

    it "deve retornar 2,3 se for informado o número 6" do
        fatorador = Fatorador.new
        numeros = fatorador.fatorar 6
        numeros[0].should == 2
        numeros[1].should == 3
    end

    it "deve retornar 2,2,5 se for informado o número 20" do
        fatorador = Fatorador.new
        numeros = fatorador.fatorar 20
        numeros[0].should == 2
        numeros[1].should == 2
        numeros[2].should == 5
    end

    it "deve retornar 37 se for informado o número 37" do
        fatorador = Fatorador.new
        numeros = fatorador.fatorar 37
        numeros[0].should == 37
    end

    it "deve retornar 7,7 se for informado o número 49" do
        fatorador = Fatorador.new
        numeros = fatorador.fatorar 49
        numeros[0].should == 7
        numeros[1].should == 7
    end

    it "deve retornar 2,163 se for informado o número 326" do
        fatorador = Fatorador.new
        numeros = fatorador.fatorar 326
        numeros[0].should == 2
        numeros[1].should == 163
    end

    it "deve retornar 3 10 vezes se for informado o número 59049" do
        fatorador = Fatorador.new
        numeros = fatorador.fatorar 59049
        numeros.size.should == 10
        numeros.each {|n| n.should == 3}
    end

    it "deve retornar 3,5,7 se for informado o número 105" do
        fatorador = Fatorador.new
        numeros = fatorador.fatorar 105
        numeros[0].should == 3
        numeros[1].should == 5
        numeros[2].should == 7
    end
end

 

Algumas observações sobre este código:

  1. Erramos na definição de fatoração, que não devia incluir o um. Mas não consertei depois, esse foi o código gerado entre o Raphael e eu, sem a correção.
  2. Um programador experiente de Ruby vai perceber que não somos fluentes na linguagem, mas foi divertido fazer este código.

Depois fizemos um coding dojo com Brian Marick, que foi o keynote speaker do Ágiles 2009, além de ser um dos autores do Agile Manifesto. Com ele aprendemos mais algumas coisas de Ruby e teste com Shoulda. Demos sorte de ele estar no aeroporto, de termos quase uma hora de espera do vôo e de ele ser super simpático. Depois eu vi um kata do Uncle Bob e percebi que podia ficar melhor ainda.

Seguindo em frente, o código da classe foi esse:

require 'Fixnum'

class Fatorador
    def fatorar numero
        return 0 if numero == 0
        if numero.primo?
            [numero]
        else
            numeros = []
            primo = 1
            numero_sendo_divido = numero

            begin
                primo = primo.proximo_primo
                while numero_sendo_divido % primo == 0
                    numero_sendo_divido = numero_sendo_divido / primo
                    numeros << primo
                end
            end while (primo < numero_sendo_divido)

            numeros
        end
    end
end

Notem que ele checa se o número é primo. A rigor isso não é necessário pra bater a meta, que é descobrir os números que fatoram outro número, mas acabamos fazendo isso também, fomos além da meta. Dessa forma, ele evita tentar dividir um número por outro que não é primo, como tentar dividir 15 por 10, por exemplo (outras otimizações ainda teriam que ser feitas pra ficar melhor). Para isso, alteramos a classe Fixnum, que no Ruby define inteiros. É como se fosse a classe System.Int32 do .Net.

Os testes de Fixnum foram esses:

require 'Fixnum'

describe "Numeros primos" do

    describe "primos" do
        it "deve retornar falso se for informado 0" do
            0.primo?.should be_false
        end

        it "deve retorno verdadeiro se for informado 1" do
            1.primo?.should be_true
        end

        it "deve retorno falso se for informado 4" do
            4.primo?.should be_false
        end

         it "deve retorno falso se for informado 6" do
            6.primo?.should be_false
        end

         it "deve retorno verdadeiro se for informado 13" do
            13.primo?.should be_true
        end

         it "deve retorno falso se for informado 21" do
            21.primo?.should be_false
        end

        it "deve retorno verdadeiro se for informado 37" do
            37.primo?.should be_true
        end

        it "deve retorno falso se for informado 49" do
            49.primo?.should be_false
        end
    end

    describe "proximo primo" do
        it "deve conseguir me entregar 3 quando informado 2" do
            primo = 2
            proximo_primo = primo.proximo_primo
            proximo_primo.should == 3
        end

        it "deve conseguir me entregar 5 quando informado 3" do
            primo = 3
            proximo_primo = primo.proximo_primo
            proximo_primo.should == 5
        end

    end
end

E aqui está a classe em si:

class Fixnum
    def primo?
        return false if self == 0

        for i in 2..(self/2) do
            return false if self % i == 0
        end

        true
    end

    def proximo_primo
        proximo = self
        while true
            proximo = proximo + 1
            return proximo if proximo.primo?
        end
    end
end

(Uma coisa um pouco irritante no Ruby é que ele não tem o operador “++”, ou seja, ou você usa “+= 1” ou faz como fizemos, “proximo = proximo + 1”.)

O download do código está aqui. Pra rodar isso tudo em IronRuby você precisa baixar a gem rspec com:

igems install rspec

E colocar os arquivos ispec e ispec.bat no diretório bin do IronRuby (normalmente c:\ruby\bin), já que estes arquivos não são criados na instalação do RSpec. Estes arquivos foram criados por mim depois que eu apanhei um pouco para descobrir como fazer pra criar, se você usa o MRI não vai precisar deste passo extra. Espero que o IronRuby passe a criá-los automaticamente até a versão 1.0, ou ao menos disponibilize uma maneira de criarmos estes arquivos de maneira mais simples, ou um diretório.

Pra rodar o RSpec é muito simples, basta chamar “ispec” e o nome do arquivo sendo testado:

ispec fatorador_spec.rb
ispec fixnum_spec.rb

Aqui vocês vêem os resultados dos testes:

Testes com RSpec rodando no IronRuby

Simples, expressivo e interessante, não é?


Postado na(s) categoria(s) IronRuby pelo Giovanni Bassi em 14 de outubro de 2009 às 12:31 | Tags: ,

Tinha testado a versão 0.9 do IronRuby. Queria rodar Rails, mas deu mais trabalho do que seria aceitável. Havia um problema com as Ruby Gems, além de outros menores.

A versão 0.9.1 (baixe aqui) saiu esses dias, e só corrige bugs, como vocês podem ver no change log. E agora roda Rails sem problemas.

Ainda há algumas coisinhas pra fazer, o IronRuby ainda não está perfeito, mas são poucos detalhes, e estão todos aqui. Esse documento é da versão 0.6 do IronRuby, mas serve também pra 0.9.2.

Pra baixar o Rails é simples:

igem install rails

Daí é só seguir o screencast de blog de 15 minutos pra ter ele rodando, inclusive com contato com SQL Server.

Vejam aqui, o rails rodando no IronRuby com WEBrick, o web server de desenvolvimento do Rails:

WEBrick rodando rails no IronRuby

Aqui vocês vêem ele rodando no navegador. À esquerda está o site base (notem o adapter de mssql), à direita uma página customizada que fiz do blog de 15 minutos:

Home page do Rails

Site Rails rodando localmente no IE

Ele gera o banco de dados sozinho com o comando:

irake db:migrate

Olha o banco de dados gerado:

Banco gerado pelo Rails

Para editar não estou usando o Visual Studio, mas o Notepad++, que eu já usava por ser rápido e muito útil. Vejam como fica legal:

Notepad++ configurado pra editar Rails (arquivo .builder)

Notepad++ configurado pra editar Rails (arquivo .rb)

Peguei umas dicas de preparação do estilo de cores do Notepad++ pra Ruby/Rails aqui.

Conclusão: já dá pra testar o rails no Windows com IronRuby. Sem dúvida fica muito mais simples trabalhar assim do que ficar me preocupando em montar uma máquina Linux só pra rodar um framework web, que é o que muita gente tem feito. As únicas reclamações que tenho no momento são os pequenos ajustes que tem que ser feitos pro rails rodar (mencionados no começo), a performance, que ainda não está excelente (e é algo que está sendo focado neste momento), e por fim o editor. Não gosto de escrever “<h2">” e ter que fechar a tag com “</h2>”. O Visual Studio já faz isso pra mim, é mais produtivo. O Notepad++ não faz. Talvez precise de um editor melhor (aceito sugestões).

Em tempo: se você já conhece o ASP.Net MVC, o Rails vai ser bastante familiar. Há uma clara inspiração do MVC no Rails.


Postado na(s) categoria(s) IronRuby pelo Giovanni Bassi em 7 de outubro de 2009 às 05:09 | Tags: , ,

Vocês viram isso?

Projeto IronRubyInline no Github.

Permite compilar código C#, VB e até F# no meio do código IronRuby.

Não consegui testar ainda, porque está dando pau no download do GitHub, mas sem dúvida parece algo muito legal. Pelo fonte que vi online, ele parece estar usando alguma infra da própria Microsoft. Interessante!

Já começo a pensar em algumas aplicações para isso.

Será que a performance é boa?

Será que funciona?


Postado na(s) categoria(s) IronRuby , C# pelo giovanni bassi em 6 de agosto de 2009 às 04:59 | Tags: , , ,

Para instalar uma gem (como se fosse um componente, uma série deles) no Ruby você usa o comando "gem". Esse comando, sozinho, baixa tudo que é necessário, coloca no diretório correto, compila, gera documentação, etc. Só falta falar. No Ironruby ele se chama "igem". Para instalar o cucumber, eu faço assim:

igem install cucumber

Eu fiz isso, e tive esse problema:

ERROR:  While executing gem ... (ArgumentError)
Illegal characters in path.

Erro na instalação de uma gem no ironruby

E você pode bingar a web inteira, de várias formas, não vai encontrar nada.

Então fiz o seguinte, rodei o instalador verbose:

igem install cucumber –V

Encontrei alguma coisa:

Erro na instalação de uma gem no ironruby (Verbose)

Está na cara que o tamanho do meu path é grande demais. Eu tinha colocado o IronRuby debaixo do diretório "Visual Studio 2008\References\ironruby-0.6.0". O camanho ficou grande demais e deve ter passado o limite do sistema operacional, que são parcos 255 caracteres. Mudei ele para "c:\bin\ironruby-0.6.0", rodei de novo:

Instalação da Gem concluída

Bingo! Cucumber, aí vou eu.

Na pasta das gems:

Pasta das gems


Postado na(s) categoria(s) IronRuby pelo giovanni bassi em 17 de julho de 2009 às 09:59 | Tags: ,

Quem é Giovanni Bassi

Giovanni Bassi Sou uma pessoa apaixonada por tecnologia e especificamente por .Net. Sou consultor independente especialista em .Net, focado em arquitetura e melhores práticas. Tenho dezenas de artigos publicados na .Net Magazine, revista da qual sou editor técnico. Ministro palestras e cursos de vez em quando, e quando dá tempo eu respiro um pouco. Mais detalhes nesta página.

Busca

Selos

Eu vou ao TechEd Brasil 2010, e você?

MVP

MCPD

MCSD

.Net Magazine

Abaixo ao if!

Calendário

«  setembro 2010  »
seteququsedo
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910
Ver detalhamento de posts no calendário

Blogs interessantes

    OPMLDownload OPML file

    Postagens recentes

    Comentários recentes

    Disclaimer / Aviso
    As opiniões colocadas neste blog são minhas e pessoais e não expressam necessariamente as opiniões de meus empregadores, pareceiros e amigos. Da mesma forma, os comentários feitos por leitores do blog não expressam a minha opinião.

    © Copyright 2010 .Net Unplugged
    Log in