activeresource

Ajouter une api key d'authentification dans toutes les requêtes ActiveResource pour Devise

J’ai chercher du coté de Rack en middleware pour ajouter les paramètres d’authentification attendu par devise lorsqu’on active l’option :token_authenticatable mais malheureusement je n’ai pas réussi à les ajouter…

Cependant j’ai trouvé une solution en surchargeant les méthodes d’ActiveResource

Ajouter la librairie suivante dans le répertoire /lib/active_resource/extend/ ne pas oublier de dé-commenter le ligne
"config.autoload_paths += %W(#{config.root}/lib)" dans config/application.rb

module ActiveResource #:nodoc:
  module Extend
    module AuthWithApi
      module ClassMethods
        def element_path_with_auth(*args)
          element_path_without_auth(*args).concat("?auth_token=#{self.api_key}")
        end
        def new_element_path_with_auth(*args)
          new_element_path_without_auth(*args).concat("?auth_token=#{self.api_key}")
        end
        def collection_path_with_auth(*args)
          collection_path_without_auth(*args).concat("?auth_token=#{self.api_key}")
        end
      end

      def self.included(base)
        base.class_eval do
          extend ClassMethods
          class << self
            alias_method_chain :element_path, :auth
            alias_method_chain :new_element_path, :auth
            alias_method_chain :collection_path, :auth
            attr_accessor :api_key
          end
        end
      end  
    end
  end  
end

dans les modèles il faut inclure le module

class Post < ActiveResource::Base
  include ActiveResource::Extend::AuthWithApi

  self.site = "http://application.localhost.com:3011/"
  self.format = :json

  self.api_key = 'jCxKPj8wJJdOnQJB8ERy'

  schema do
    string  :title
    string  :content
  end

end

Et le tour est joué !

Dreams, dreamers and dreaming

Dreams, dreamers and dreaming

Imagination, visions and
where we are going…

“You may say I’m a dreamer,
but I’m not the only one.
I hope someday you’ll join us.
And the world will live as one.”
John Lennon

“Hold fast to dreams,
For if dreams die
Life is a broken-winged bird,
That cannot fly.”
Langston Hughes

“Logic will get you from A to Z; imagination will get you everywhere.”
Albert Einstein

“Some might think that…

View On WordPress

ActiveResource with a different name

If you need to use a different name for an activeresource, just set the element_name value:

class Candidate < ActiveResource::Base
  self.site = 'http://my_other_app.local'
  self.element_name = 'users'
end
Rails ActiveResource HTTP_AUTHORIZATION headers

prblm: ActiveResource in Rails does not allow to add request headers, which is a general way to send authentication information. How to add custom headers to every request sent using ActiveResource?

solution: The ActiveResource has a very poorely written API, which does not provide any hook to provide custom headers to be added. We need to metaprogram our way around it as follows.

  • Add an entry to application.rb to load all files from app/extensions.
  • Create a module CustomAuthHeaders and include it in ActiveResource::Base
  • In the created module override headers method so that, when any request is made from ActiveResource::Base, custom request headers will be added.

https://gist.github.com/1100092

    You can copy paste the above mentioned code in respective locations and all of ActiveResource requests will have extra headers as returned by AppAuthHeaders.headers

    Using Rails ActiveResource via OAuth2

    Exposing Resources via a REST interface can be a nice way to split-off certain parts of a larger Rails application. To consume those, ActiveResource has been a nice way to go for quite some time now, and still is in my opinion even thought with Rails 4 it will move to its own gem and be no longer tied to Rails Core (good or bad?).

    One hurdle left is that in some cases resources are, or should be protected. In this case working with OAuth2 for example is quite easy the only thing needed is setting a header.

    The token obtained for example via Omniauth and then set in the Controller. So thats it now using the Resource works just as using an ActiveRecord Model.

    SOA com Rails e Sinatra - parte 1
    O que é SOA

    Nos ultimos tempos muitas figuras famosas na comunidade Ruby/Rails vem se mostrando insatisfeita com o modelo ‘monolítico’ que o Rails adota. Por um lado ter toda a sua logica de negócio em um só aplicativo facilita o desenvolvimento, afinal, é apenas um projeto para manter. Porém, conforme o projeto cresce o negócio começa a ficar insustentavel. Não é incomum um projeto Rails grande ter mais de 50 modelos. A manutenção fica bem complicada.

    Uma saida para esse problema é desenvolver sistemas distribuido. Essa prática, apesar de não ser nem um pouco nova, entrou na ‘moda’ recentemente com o nome de SOA (ou Service Oriented Architecture). Esse tipo de arquitetura oferece uma série de vantagem à abordagem convencional de desenvolvimento web. Recomendo a leitura desses artigos para se aprofundar um pouco mais no assunto. Algumas das vantagens mais evidentes são:

    • Reutilização dos componentes em diversos sistemas (Um serviço de usuário, por exemplo, pode ser utilizado como um servidor de single login para várias aplicações).
    • Independência de implementação entre os componentes (que podem utilizar tecnologias, linguagens e até plataformas diferentes).
    • Melhor gerenciamento de recursos (na forma de mais facilidade para escalar os componentes independentemente uns dos outros, reduzindo custo).

    Nessa artigo a gente vai construir um sistema distribuido para uma biblioteca. O único requisito do sistema é permitir que um usuário gerencie os livros da biblioteca através de um CRUD bem básico.

    A gente vai utilizar o Rails para constuir um aplicativo que irá servir o front-end do sistema. No lugar dos modelos ActiveRecord nós vamos utilizar o ActiveResource para se comunicar com um serviço Rest feito com o Sinatra. Esse serviço vai ser responsavel por manter os dados no banco, e vai oferecer uma api que será acessada pela aplicação Rails. A comunicação será feita com JSON.

    Construindo o servico com Sinatra e ActiveRecord

    "Sinatra is a DSL for quickly creating web applications in Ruby with minimal effort" - Documentação do Sinatra

    O Sinatra é uma biblioteca (e não um framework) para construção de aplicativos web simples. Ele oferece uma DSL que permite o desenvolmento rápido de aplicaçãos web e se mostra muito util para construção de web-services.

    Nós vamos criar um web-service bem simples que vai constituir de um único arquivo onde vamos definir nosso modelo Book e gerar as rotas para manipulá-lo.

    Antes de mais nada vamos intalar algumas gems que serão usadas nesse exercicio:

    $ gem install sinatra rails mysql therubyracer
    

    Crie um diretório para o serviço:

    $ mkdir books
    $ touch books/service.rb
    

    O nosso serviço vai guardar os dados no banco de dados, e para isso vamos utilizar o ActiveRecord.

    É necessário criar o banco de dados para o serviço. Para esse exemplo a gente vai utilizar o MySQL e criar o banco na mão, fique a vontade para usar o banco que achar melhor. Em um post futuro eu explico como gerar e rodar migrações no Sinatra.

    $ mysql -u root
    mysql> create database books_development;
    mysql> use books_development;
    mysql> create table books (id int NOT NULL AUTO_INCREMENT PRIMARY KEY, name varchar(100));
    

    O código para o serviço em si ficará no arquivo service.rb que a gente acabou de criar:

    require 'sinatra'
    require 'active_record'
    
    
    class Book < ActiveRecord::Base; end
    ActiveRecord::Base.establish_connection(
        adapter: 'mysql',
        host: 'localhost',
        database: 'books_development',
        username: 'root'
    )
    
    
    get '/books.json' do
        Book.all.to_json
    end
    
    
    get '/books/new.json' do
        Book.new.to_json
    end
    
    
    get '/books/:id.json' do |id|
        Book.find(id).to_json
    end
    
    
    post '/books.json' do
        parameters = JSON.parse(request.body.read)
        Book.create(parameters["book"])
    end
    
    
    put '/books/:id.json' do |id|
        book = Book.find id
        parameters = JSON.parse(request.body.read)
        book ? book.update_attributes(parameters["book"]) : 404
    end
    
    
    delete '/books/:id.json' do |id|
        book = Book.find id
        book ? book.delete : 404
    end

    Vamos por parte. Primeiro nós carregamos o sinatra e o active_record que são as únicas dependências que nosso serviço vai ter por enquanto. Depois disso define o modelo Book inline. A linha seguinte faz a conexão com o banco de dados que nós criamos.

    Os blocos que vem em seguida são chamadas para a DSL do Sinatra. É dessa forma que nós definimos o que será executado para cada requisição. A DSL do Sinatra é bem simples, e até intuitiva. Cada bloco desses vai responder a uma requisição para determinado verbo e determinada url. Sugiro a leitura da documentação do Sinatra para se familiarizar com sua DSL.

    Trabalhando com JSON no Sinatra

    A únicas linhas do service.rb que podem causar estranhesa são:

    parameters = JSON.parse(request.body.read)

    Isso é necessario por causa da forma como o Sinatra parseia query-strings e o body da requisição.

    Quando você envia um GET ‘/books?order=name’, por exemplo, o Sinatra transforma a query-string (‘order=name’) em um Hash e o coloca no params ({ ‘order’ => ‘name’}).

    Quando você faz um POST ‘/customers’ com o body "book[name]=1986" ele parseia esse body assumindo que ele está no formato de formulário, e o coloca no params ({ ‘book’ => { ‘name’ => ‘1986’ } }).

    O que acontece é que nossos serviços vão se comunicar com JSON (que é o padrão do ActiveResource) e nesse caso o body do POST seria alguma coisa do tipo ’{“book”:{“name”:”1986”}}’ (repare na diferença em relação ao body do POST anterior). O Sinatra, por padrão, só parseia o body se ele estiver no formato de formulário, portanto, no nosso caso, o params apareceria em branco. Devido a isso a gente tem que parsear o body na mão em qualquer POST OU PUT que envie dados em JSON.

    Se você estiver estranhando aquela rota para '/book/new.json' segure a curiosidade um pouquinho que já vai ficar claro porque ela existe.

    Você pode testar o funcionamento do serviço rodando o service.rb:

    $ cd books
    $ ruby service.rb
    

    E fazendo algumas requisições com o curl:

    $ curl -d '{"book":{"name":"1986"}}' http://localhost:4567/books.json
    $ curl http://localhost:4567/books.json
    

    O último comando deve ter retornar:

    [{"book":{"id":1,"name":"1986"}}]
    

    Tudo OK então. Com o serviço pronto podemos passar para o cliente. Nós vamos utilizar o Rails com o ActiveResource para renderizar o front-end e se comuncar com nosso serviço sinatra.

    O cliente Rails com ActiveResource

    Primeiro precisamos gerar nosso aplicativo:

    $ rails new bookshelf -T

    Inclua a gem ‘therubyracer’ em seu gemfile e rode o bundler:

    $ cd bookshelf
    $ bundle install
    

    Por praticidade vamos gerar um scafold para um modelo Book. O scaffold gera modelos ActiveRecord, que não é o que a gente quer, porém, vamos utilizá-lo porque ele já gera as nossas view:

    $ rails g scaffold books name:string
    

    Você pode apagar a migração que o generator criou e alterar a classe pai do Book para ActiveResource em app/models/book.rb.

    Essa classe deve ficar assim:

    class Book < ActiveResource::Base
      self.site = 'http://localhost:4567'
    end

    O ‘self.site’ define onde o ActiveResource vai producar o serviço rest para o Book.

    A ultima coisa que devemos alterar para a aplicação funcionar é a forma como a action ‘new’ do BooksController instancia um novo objeto.

    Instanciando objetos vazios com o ActiveResource

    Se você tentar acessar o formulário de criação de Books agora irá ver o erro 'undefined method `name' for #<Book:0xb59c42c>'. Isso acontece porque o ActiveResource não conheçe a estrutura de um Book e gera um objeto sem nenhum atributo.

    Existem duas formas de contornar esse problema. A primeira seria adicionando um schema à classe Book:

    class Book < ActiveResource::Base
      self.site = 'http://localhost:4567'
    
      schema do
        string 'name'
      end
    end

    Dessa forma o Book.new criaria uma objeto com um atributo ‘name’.

    A segunda forma seria trocar Book.new por Book.build.

    Quando o ActiveResource recebe um ‘build’ ele faz um GET ‘/books/new.json’. O serviço então tem a oportunidade de retornar uma representação de um produto com todos os atributos necessários (se você reparar nr, o nosso service.rb contem uma rota para essa url). Essa abordagem tem a óbvia desvantagem de precisar de uma requisição a mais, porém, por enquanto ela vai servir.

    E é isso! Levante o serviço e o servidor rails e veja que está tudo funcionando. Nossa aplicação de front-end está utilizando os dados servidos pela api rest do serviço Sinatra.

    Num proximo post nós vamos evoluir essa ideia para fazer nosso serviço funcionar com modelos relacionados e aninhados. Até lá!

    Many Errors by Cleveland Police, Then a Fatal One

    Many Errors by Cleveland Police, Then a Fatal One

    By SHAILA DEWAN and RICHARD A. OPPEL Jr.JAN. 22, 2015

    Photo

    Samaria Rice, right, with her daughter Tajai at Cudell Commons in Cleveland, where her son Tamir was killed by a police officer. Credit Michael F. McElroy for The New York Times

    ______________________________________________________________________________________________CLEVELA…

    View On WordPress

    The January 2015 Portland Alliance

    http://www.theportlandalliance.org/2015/January/

    Martin Luther King was assassinated
    by the United States Government according
    to the King Family civil trial verdict

    “Coretta Scott King: “We have done what we can to reveal the truth, and we now urge you as members of the media, and we call upon elected officials, and other persons of influence to do what they can to share the revelation of this…

    View On WordPress

    GMO Foods: What are they and why should I care?

    GMO FACTS Frequently Asked Questions


    What are GMOs?

    GMOs, or “genetically modified organisms,” are plants or animals that have been genetically engineered with DNA from bacteria, viruses or other plants and animals. These experimental combinations of genes from different species cannot occur in nature or in traditional crossbreeding.

    Virtually all commercial GMOs are engineered to withstand…

    View On WordPress