Added API, faye, resque, bash and console topics

James Peret 8 years ago
parent
commit
44010d42cd
16 changed files with 817 additions and 22 deletions
  1. 317 0
      API.md
  2. 60 4
      Links.md
  3. 9 0
      Postgres.md
  4. 19 1
      associacoes.md
  5. 24 0
      bash.md
  6. 70 0
      console.md
  7. 22 4
      cucumber.md
  8. 26 0
      devise_invitable.md
  9. 170 0
      faye.md
  10. 17 6
      fontcustom.md
  11. 4 0
      git.md
  12. 7 1
      index.md
  13. 17 0
      mailer.md
  14. 27 5
      nested_model.md
  15. 17 0
      resque.md
  16. 11 1
      testes.md

+ 317 - 0
API.md

@@ -0,0 +1,317 @@
1
+# API
2
+
3
+Neste documento vou explicar como criar uma **API** (Application Programming Interface) para um aplicativo **Rails**. Vou começar criando uma **API** simples, depois mostrando como criar versões dela, depois vou mostrar como criar um sistema de tokens para adicionar segurança e por ultimo vou criar um sistema de autenticação de usúarios via oAuth.
4
+
5
+## Criando uma API basica
6
+
7
+Em Qualquer controlador do rails, é possivel criar uma resposta em **JSON** além da resposta em **HTML**.
8
+
9
+<pre><code class="ruby">
10
+class ProductsController < ApplicationController
11
+	def index
12
+		@products = Products.all
13
+		respond_to do |format|
14
+			format.html
15
+			format.json { render json @products }
16
+		end
17
+	end
18
+end
19
+</code></pre>
20
+
21
+Ao entrar na página ```http://localhost:300/products.json```, você vai receber um arquivo em **JSON** com o conteúdo dos produtos.
22
+
23
+## Criando rotas para a API
24
+
25
+Para criar uma rota como ```http://localhost:3000/api```, modifique o arquivo ```config/rountes.rb```
26
+
27
+	Store::Application.routes.draw do
28
+		namespace :api do
29
+			# /api/...   API::
30
+			namespace :api, defaults: {format: 'json'} do
31
+				namespace :v1 do
32
+					resources :products
33
+				end
34
+				namespace :v2 do
35
+					resources :products
36
+				end
37
+			end
38
+		end
39
+		
40
+		resources :products
41
+		root to: 'products#index'
42
+	end
43
+
44
+## O Controlador da API
45
+
46
+Cria o arquivo ```/app/controllers/api/v1/products_controller.rb```:
47
+
48
+	module Api
49
+		module V1
50
+			class ProductsController < ApplicationController # ou API::BaseController
51
+				
52
+				# Hacks para que certos atributos continuem `backword compatiple`
53
+				# Aqui estamos modificando a funcionalidade da classe neste controlador
54
+				class Product < ::Product
55
+					def as_json(options = {})
56
+						super.merge(released_on released_at.to_date)
57
+					end
58
+				end
59
+				
60
+				respond_to :json
61
+				
62
+				def index
63
+					respond_with Product.all
64
+				end
65
+				
66
+				def show
67
+					respond_with Product.find(params[:id])
68
+				end
69
+				
70
+				def create
71
+					respond_with Product.cerate(params[:product])
72
+				end
73
+				
74
+				def update
75
+					respond_with Product.update(params[:id], params[:product])
76
+				end
77
+				
78
+				def destroy
79
+					respond_with Product.destroy(params[:id])
80
+				end
81
+			end
82
+		end
83
+	end
84
+
85
+## Usando accept headers para versão da API
86
+
87
+Em vez de usar um endereço como ```http://localhost:3000/api/v1/```, alguns sites como o [github](http://github.com) usam o **accept header** para especificar a versão do API.
88
+
89
+Para configurar as rotas para ceitar o **accept header**, modifique o arquivo ```config/rountes.rb```
90
+
91
+	require 'api_constraints'
92
+
93
+	Store::Application.routes.draw do
94
+		namespace :api, defaults: {format: 'json'} do
95
+			scope module: :v1, constraints: ApiContraints.new(version: 1) do
96
+				resources :products
97
+			end
98
+			scope module: :v2, constraints: ApiConstraints.new(version: 2, default: true) do
99
+				resources :products
100
+			end
101
+		end
102
+		
103
+		resources :products
104
+		root to: 'products#index'
105
+	end
106
+
107
+Depois no arquivo ```lib/api_constraints.rb```:
108
+
109
+	class ApiConstraints
110
+		def initialize(options)
111
+			@version = options[:version]
112
+			@default = options[:default]
113
+		end
114
+		
115
+		def matches?(req)
116
+			@default || req.headers['Accept'].include?("application/vnd.example.v#{@version}")
117
+		end
118
+	end
119
+	
120
+Agora ao visitar a url ```http://localhost:3000/api/products```, você vai acessar o **API** v2 e receber o arquivo em **JSON**.
121
+
122
+Para acessar outra versão da **API** via *curl* no *terminal*:
123
+
124
+``` curl -H 'Accept: application.vnd.example.v1' http://localhost:3000/api.products ```
125
+
126
+## Autenticação basica
127
+
128
+O jeito mas simples de restringir acesso ao **API** é usando a autenticação basica provida pelo **rails**.
129
+
130
+
131
+No arquivo ```/app/controllers/api/v1/products_controller.rb```:
132
+
133
+	module Api
134
+		module V1
135
+			class ProductsController < ApplicationController
136
+				http_basic_authenticate_with name: "admin", password:  "secret"
137
+				respond_to :json
138
+				...
139
+
140
+Para testar, no terminal, digite o comando:
141
+
142
+<pre><code class="bash">
143
+	$ curl http://localhost:3000/api/products
144
+	HTTP Basic: Access denied.
145
+	
146
+	$ curl http://localhost:3000/api/products -I
147
+	HTTP/1.1 401 Unauthorized
148
+	WWW-Authenticate: Basic realm="Application"
149
+	Content-Type: text/html; charset=utf-8
150
+	...
151
+	
152
+	$ curl http://localhost:3000/api/products -u 'admin:secret'
153
+	JSON response
154
+	...
155
+</code></pre>
156
+
157
+## Access Token
158
+
159
+Em vez de usar um sistema de autenticação, podemos restringir acesso a API requerindo um **token de acesso**. Se na chamada para o API o cliente não enviar o **token**, o acesso será negado.
160
+
161
+Primeiro vamos criar um modelo para guardar os **tokens**. Execute o comando:
162
+
163
+ ```rails generate model api_key access_token```
164
+ 
165
+É possivel tb adicionar outras colunas como ```user_id``` para guardar o dono do **token**, ou ```expires_at``` para destruir chaves antigas ou a colona ```role``` para adicionar permissões diferentes para cada **token**.
166
+ 
167
+Em seguida vamos modificar o modelo em ```app/models/api_key.rb```. Quando um novo *api_key* for criado, ele vai gerar um número randomico unico para está chave.
168
+
169
+	class ApiKey < ActiveRecord::Base
170
+		before_create :generate_access_token
171
+		
172
+	private
173
+	
174
+		def generate_access_token
175
+			begin
176
+				self.access_token = SecureRandom.hex
177
+			end while self.class.exists?(access_token: access_token)
178
+		end
179
+	end
180
+	
181
+Para testar, entre no [console](rails_console.md) e digite o comando: ```ApiKey.create!```. Isso vai gerar um novo **access_token** com um número hexadecimal unico.
182
+
183
+Agora vamos restringir o acesso ao **API** modificando o controlador. No arquivo ```/app/controllers/api/v1/products_controller.rb```:
184
+
185
+	module Api
186
+		module V1
187
+			class ProductsController < ApplicationController
188
+				before_filter :restrict_access
189
+				respond_to :json
190
+				
191
+				...
192
+				
193
+			private
194
+			
195
+				def restrict_access
196
+					api_key = ApiKey.find_by_access_token(params[:access_token])
197
+					head :unauthorized unless api_key
198
+				end
199
+			end
200
+		end
201
+	end
202
+
203
+
204
+Para acessar o **API** com o **access_token**, podemos utilizar a seguinte url:
205
+
206
+```http://localhost:3000/api/products?access_token=c576f0136149a2e2d9127b3901015545```
207
+
208
+Este metodo não é muito seguro, por que as pessoas podem copiar e colar os codigos de acesso junto com a url sem querer. Para melhorar este exemplo, vamos passar o **access_token** atravez de um parametro no *head* do *request* para o servidor.
209
+
210
+Vamos mudar de novo o arquivo ```/app/controllers/api/v1/products_controller.rb```:
211
+
212
+	def restrict_access
213
+		authenticate_or_request_with_http_token do |token, options|
214
+			ApiKey.exists?(access_token: token)
215
+		end
216
+	end
217
+	
218
+Para testar, no terminal vamos accessar de novo a url do **API** mas desta vez passando o **access_token** junto com o *header*:
219
+
220
+```curl http://localhost:3000/api/products -H 'Authorization: Token token="c576f0136149a2e2d9127b3901015545"'```
221
+
222
+## Autenticação de usuários com OAuth
223
+
224
+A questão das soluções anteriores é que estamos criando um sistema de autenticação global. Não temos como saber exatamente qual usuário está acessando a **API**. Então se você necessista de autenticação de usuário via o **API**, o jeito mais comum para fazer isso é utilizando o [OAuth2](http://oauth.net/2/).
225
+
226
+> **OAauth** é um protocolo aberto para autorização segura de um **API** de um jeito simples e comum para aplicativos *web*, *mobile* e *desktop*.
227
+
228
+O protocolo **OAuth** foi criado pela equipe do twitter e várias outras empresas adotaram e usam o protocolo como o Google, Facebook e GitHub. Ele é utilizado para que um aplicavo possa acessar informações de outro aplicativo através da autorização de um usúario.
229
+
230
+O *gem* [doorkeeper](https://github.com/doorkeeper-gem/doorkeeper) serve para simplificar a criação de um serviço de **OAuth** em um aplicativo *rails*.
231
+
232
+### Configurando o DoorKeeper
233
+
234
+Primeiro, mude para ```false``` a configuração ```whitelist_attributes``` no arquivo ```config/application.rb```:
235
+
236
+	config_active_record.whitelist_attributes = false
237
+	
238
+Depois no ```gemfile``` adicione no fim:
239
+
240
+	gem 'doorkeeper'
241
+	
242
+Execute o comando ```bundle install``` para instalar o *gem* e depois rode os comandos para instalar o **doorkeeper** e migrar o banco de dados:
243
+
244
+	rails g doorkeeper:install
245
+	rake db:migrate
246
+	
247
+Varias novos arquivos e tabelas no banco de dados vão ser criados. Em seguida modifique o arquivo ```config/initializers/doorkeeper.rb```:
248
+
249
+	DoorKeeper.configure do
250
+		
251
+		resource_owner_authenticator do |routes|
252
+			#raise "Please configure doorkeeper"
253
+			# Put your resource owner authentication logic here
254
+			# If you want to use named routes from your app you need
255
+			# to call them on routes object eg.
256
+			# routes.new_user_session_path
257
+			User.find_by_id(session[:user_id]) || redirect_to(routes.new_user_session_url)
258
+		end
259
+		
260
+		...
261
+
262
+
263
+### Repositorios
264
+
265
+* [doorkeeper](https://github.com/doorkeeper-gem/doorkeeper) - Doorkeeper is an OAuth 2 provider for Rails and Grape
266
+* [ionic-doorkeeper](https://github.com/emilsoman/ionic-doorkeeper) - Sample ionic app that authenticates with a Rails API protected with Doorkeeper
267
+
268
+### Links
269
+
270
+* [OAuth Implicit Grant with Grape, Doorkeeper and AngularJS](http://codetunes.com/2014/oauth-implicit-grant-with-grape-doorkeeper-and-angularjs/)
271
+* [How can I pre-authorize a client app for my user on my oauth provider that uses doorkeeper?](http://stackoverflow.com/questions/11129676/how-can-i-pre-authorize-a-client-app-for-my-user-on-my-oauth-provider-that-uses)
272
+* [Using Resource Owner Password Credentials flow](https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Resource-Owner-Password-Credentials-flow)
273
+* [Doorkeeper + Devise](http://morodeercoding.blogspot.ru/)
274
+* [The OAuth 2.0 Authorization Framework](https://tools.ietf.org/html/rfc6749)
275
+
276
+
277
+## Criando um API com o Grape gem
278
+
279
+### Repositorios
280
+
281
+* [grape](https://github.com/intridea/grape) - An opinionated micro-framework for creating REST-like APIs in Ruby.
282
+* [wine_bouncer](https://github.com/antek-drzewiecki/wine_bouncer) - A Ruby gem that allows Oauth2 protection with Doorkeeper for Grape Api's
283
+* [grape-doorkeeper](https://github.com/fuCtor/grape-doorkeeper) - Integration Grape with Doorkeeper* 
284
+
285
+### Links
286
+
287
+* [Build Great APIS with Grape](http://www.sitepoint.com/build-great-apis-grape/)
288
+* [Introduction to building APIs with Grape](http://codetunes.com/2014/introduction-to-building-apis-with-grape/)
289
+* [Building RESTful API using Grape in Rails](http://funonrails.com/2014/03/building-restful-api-using-grape-in-rails/)
290
+* [OAuth 2.0 Tutorial: Protect Grape API with Doorkeeper](http://blog.yorkxin.org/posts/2013/11/05/oauth2-tutorial-grape-api-doorkeeper-en/)
291
+* [authenticate grape api with doorkeeper](http://stackoverflow.com/questions/26472217/authenticate-grape-api-with-doorkeeper)
292
+* [Grape API authentication using Devise Auth Token](http://funonrails.com/2014/03/api-authentication-using-devise-token/)
293
+
294
+## Autenticação apenas com o Devise
295
+
296
+### Links
297
+
298
+* [APIs with Devise](http://soryy.com/blog/2014/apis-with-devise/)
299
+* [API JSON authentication with Devise](https://gist.github.com/jwo/1255275)
300
+
301
+## API Reference
302
+
303
+* [A Well Designed API Approach](https://www.airpair.com/rest/posts/a-well-designed-api-approach)
304
+
305
+
306
+
307
+-----------------
308
+
309
+[Index](index.md)
310
+
311
+<!-- Highlight syntax for Mou.app, insert at the bottom of the markdown document  -->
312
+ 
313
+<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
314
+<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/github.min.css">
315
+<script>
316
+  hljs.initHighlightingOnLoad();
317
+</script>

+ 60 - 4
Links.md

@@ -1,9 +1,65 @@
1
-# Links
1
+# Links e URLs
2 2
 
3
-Em um **View**, para criar um **link** utilize a função ```link_to```.
3
+## links
4 4
 
5
-## Exemplo
5
+Em um **View**, para criar um **link** utilize a função ```link_to```. Essa função gera uma tag ```<a>``` em HTML.
6
+
7
+#### Exemplo
6 8
 	
7 9
 	<%= link_to("click here", {:action => 'index'}) %>
8 10
 
9
-<a class="btn btn-mini" href="readme.md">voltar</a>
11
+## URLs
12
+
13
+Para gerar apenas uma URL, utilize o comando ```url_for```.
14
+
15
+
16
+### Opções
17
+
18
+* ```:anchor``` - Especifica o *anchor* na url. Pode ser usada para ir direto a um *ID* na proxima pagina.
19
+* ```:only_path``` - Boolean que especifica se o metodo deve retornar apenas a URL ou todas as informações (protocol, host, port).
20
+* ```:format``` - Adiciona uma extensão ao final da URL 
21
+
22
+### Exemplos de URLs
23
+
24
+	# http://www.example.com/posts
25
+	url_for :controller => 'posts', :action => 'index'
26
+	
27
+	# http://www.example.com/posts/5
28
+	url_for :controller => 'posts', :action => 'index', :id => 5
29
+	
30
+	# http://www.example.com/posts/5/edit
31
+	url_for :controller => 'posts', :action => 'edit', :id => 5
32
+	
33
+	# http://www.example.com/posts.xml
34
+	url_for :controller=>'posts', :action=>'index', :format=>:xml
35
+	
36
+### namespace
37
+
38
+Se você estiver usando um *namespace*, é possivel gerar uma url do seguinte jeito:
39
+
40
+	namespace :admin do
41
+	  resources :products
42
+	end
43
+	then you can:
44
+	
45
+	url_for([:admin, @product])
46
+	and:
47
+	
48
+	url_for([:edit, :admin, @product])
49
+
50
+-----------------
51
+## Informações adicionais
52
+
53
+* [Rails routing - RailsGuides](http://guides.rubyonrails.org/routing.html)
54
+
55
+-----------------
56
+
57
+[Index](index.md)
58
+
59
+<!-- Highlight syntax for Mou.app, insert at the bottom of the markdown document  -->
60
+ 
61
+<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
62
+<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/github.min.css">
63
+<script>
64
+  hljs.initHighlightingOnLoad();
65
+</script>

+ 9 - 0
Postgres.md

@@ -1,5 +1,7 @@
1 1
 # Postgres
2 2
 
3
+## Configuração do BD para projeto Rails
4
+
3 5
 Para criar um banco de dados postgres primeiro faça o login no banco de dados:
4 6
 
5 7
 ``$ psql --username=admin``
@@ -45,3 +47,10 @@ Por ultimo configure o arquivo ``database.yml `` com as informações de login e
45 47
 	  pool: 5
46 48
 	  username: admin
47 49
 	  password: password1
50
+
51
+## Outros comandos
52
+
53
+* ``\l`` - Listar bancos de dados
54
+* ``\c database_name`` - selecionar banco de dados
55
+* ``\d`` - Listar tabelas de um banco de dados
56
+* ``DROP TABLE table_name`` - Deletar uma tabela de um banco de dados

+ 19 - 1
associacoes.md

@@ -182,4 +182,22 @@ Neste exemplo vamos criar um log de edição das páginas do sistema.
182 182
 		belongs_to :editor, :class_name => "User", :foreign_key => "user_id"
183 183
 	end
184 184
 
185
-#### Traversing
185
+#### Traversing
186
+
187
+
188
+-----------------
189
+## Informações adicionais
190
+
191
+* [A Rule of Thumb for Strong Parameters](http://patshaughnessy.net/2014/6/16/a-rule-of-thumb-for-strong-parameters)
192
+
193
+-----------------
194
+
195
+[Index](index.md)
196
+
197
+<!-- Highlight syntax for Mou.app, insert at the bottom of the markdown document  -->
198
+ 
199
+<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
200
+<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/github.min.css">
201
+<script>
202
+  hljs.initHighlightingOnLoad();
203
+</script>

+ 24 - 0
bash.md

@@ -0,0 +1,24 @@
1
+# Terminal/Bash
2
+
3
+
4
+* ```TAB``` - Autocompleta o atual comando
5
+* ```!!``` - Repedir o ultimo comando
6
+* ```control-r``` - Buscar por um comando anterior
7
+* ```source ~/bash.profile``` - Recarrega o *bash.profile* na atual aba do terminal. Util para quando você está editando susas preferencias.
8
+* ```$EDITOR``` variavel que determina qual editor de texto o terminal deve usar.
9
+
10
+#### Links
11
+
12
+* [Know your tools](http://www.spacecowboyrocketcompany.com/2015/02/know-your-tools/)
13
+
14
+-----------------
15
+
16
+[Index](index.md)
17
+
18
+<!-- Highlight syntax for Mou.app, insert at the bottom of the markdown document  -->
19
+ 
20
+<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
21
+<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/github.min.css">
22
+<script>
23
+  hljs.initHighlightingOnLoad();
24
+</script>

+ 70 - 0
console.md

@@ -0,0 +1,70 @@
1
+# Console
2
+
3
+## Configurações
4
+
5
+O arquivo ```~/.irbrc``` serve para configurar o console. Ele fica no root da pasta de usuário no sistema operacional. Esse arquivo funciona como um arquvo de *.rb* comum e vai ser rodado toda vez que o IRB iniciar.
6
+
7
+Para editar ou criar esse arquivo, digite no terminal:
8
+
9
+```pico ~/.irbrc```
10
+
11
+Para sair do editor **pico** aperte **ctrl + x** para fechar o arquivo e confirme que quer salvar e o nome do arquivo apertando **enter**.
12
+
13
+## Truques
14
+
15
+### HIRB
16
+
17
+O HIRB serve para melhorar a visualização do *ActiveRecord*. Ele muda o jeito como o IRB mostra os dados retornados para o usuário, criando uma tabela que pode ser customizada.
18
+
19
+Muito util para poder visualizar os dados do que você está fazendo no console do rails e não ficar precisando caçar as informações perdidas dentro de um *hash* gigante.
20
+
21
+#### Instalação
22
+
23
+Adicione ao ```/Gemfile```:
24
+
25
+	  gem 'hirb'
26
+	  
27
+Depois adicione ao arquivo ```~/.irbrc``` as seguintes configurações: 
28
+
29
+	require 'hirb'
30
+	Hirb.enable 
31
+
32
+### Wirble
33
+
34
+O wirble é um **gem** que serve para melhorar o *console* do rails.
35
+
36
+#### Instalação
37
+
38
+Adicione ao ```/Gemfile```:
39
+
40
+	  gem 'wirble'
41
+	
42
+Depois adicione ao arquivo ```~/.irbrc``` as seguintes configurações:
43
+
44
+	begin
45
+	  require 'wirble'
46
+	  # init wirble
47
+	  Wirble.init
48
+	  # enable color
49
+	  Wirble.colorize
50
+	  Wirble::Colorize::DEFAULT_COLORS
51
+	rescue LoadError => err
52
+	  $stderr.puts "Couldn't load Wirble: #{err}"
53
+	end
54
+	
55
+#### Links
56
+
57
+* [Mais informações](http://pablotron.org/software/wirble/)
58
+* [Readme.md](http://pablotron.org/software/wirble/README)
59
+
60
+-----------------
61
+
62
+[Index](index.md)
63
+
64
+<!-- Highlight syntax for Mou.app, insert at the bottom of the markdown document  -->
65
+ 
66
+<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
67
+<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/github.min.css">
68
+<script>
69
+  hljs.initHighlightingOnLoad();
70
+</script>

+ 22 - 4
cucumber.md

@@ -1,8 +1,10 @@
1 1
 # Cucumber
2 2
 
3
-Behavior driven development
3
+*Behavior driven development*
4 4
 
5
-### Instalação
5
+O Cucumber é um framework de alto nivel para criação de testes baseado em historias de interações de usuários. Sua grande vantagem é que os testes são escritos em uma lingua comum como o inglês (ou outras linguas utilizando plugins).
6
+
7
+## Instalação
6 8
 
7 9
 1- no arquivo ```Gemfile```:
8 10
 
@@ -29,11 +31,27 @@ Uma pasta chamada ```app/features``` foi criada.
29 31
 5- Para rodar o cucumber, utilize o comando rake: ```$ cucumber features -n```
30 32
 
31 33
 
32
-### Features
34
+## Como funciona
33 35
 
34 36
 1. Cenario
35 37
 2. Feature
36 38
 3. Steps
37 39
 4. Background
38 40
 5. Paths
39
-6. Factories
41
+6. Factories
42
+
43
+#### Links
44
+
45
+* [RailsCast Cucumber Tutorial](https://www.evernote.com/l/AALzqmI0XeBD7rP9wL83vkSYnKMwjdSvduA) [(local version)](evernote:///view/124245/s2/f3aa6234-5de0-43ee-b3fd-c0bf37be4498/f3aa6234-5de0-43ee-b3fd-c0bf37be4498/)
46
+
47
+-----------------
48
+
49
+[Index](index.md)
50
+
51
+<!-- Highlight syntax for Mou.app, insert at the bottom of the markdown document  -->
52
+ 
53
+<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
54
+<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/github.min.css">
55
+<script>
56
+  hljs.initHighlightingOnLoad();
57
+</script>

+ 26 - 0
devise_invitable.md

@@ -0,0 +1,26 @@
1
+# Devise Invitable
2
+
3
+O gem [devise_invitable](https://github.com/scambra/devise_invitable) serve para estender a funcionalidade do devise para possibilitar a criação de usuários através de convites.
4
+
5
+#### Links
6
+
7
+* [Using Devise Invitable](http://aaronmiler.com/blog/using-devise-invitable/)
8
+* [Customizing for different Invite use cases](https://github.com/scambra/devise_invitable/wiki/Customizing-for-different-Invite-use-cases-(emails-etc.))
9
+* [The best way to approach handling invitations of existing users](https://github.com/scambra/devise_invitable/issues/506)
10
+* [Devise invitable: invite existing user](http://stackoverflow.com/questions/18226102/devise-invitable-invite-existing-user)
11
+* [Overide mailer in devise_invitable?](http://www.ciiycode.com/06izzgPPqqPQ/overide-mailer-in-deviseinvitable)
12
+* [Devise Invitable optional custom message](http://stackoverflow.com/questions/9841700/devise-invitable-optional-custom-message)
13
+* [How do I delete an invitation with devise_invitable?](http://stackoverflow.com/questions/19646175/how-do-i-delete-an-invitation-with-devise-invitable)
14
+* [How to override devise invitable actions](http://stackoverflow.com/questions/18191010/how-to-override-devise-invitable-actions)
15
+
16
+-----------------
17
+
18
+[Index](index.md)
19
+
20
+<!-- Highlight syntax for Mou.app, insert at the bottom of the markdown document  -->
21
+ 
22
+<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
23
+<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/github.min.css">
24
+<script>
25
+  hljs.initHighlightingOnLoad();
26
+</script>

+ 170 - 0
faye.md

@@ -0,0 +1,170 @@
1
+# Faye
2
+
3
+[Faye](http://faye.jcoglan.com/) é um sistema para subscrever e enviar mensagens baseado no protocolo *Bayeux* (Pub/Sub). O **Faye** providencia um **servidor** de mensagens para ser usado com *node.js* ou *Ruby* além de uma biblioteca em *Javascript* para os **clientes** que funciona em todos os browsers modernos.
4
+
5
+## Instalação
6
+
7
+Primeiro instale o gem executando o comando: ```gem install faye```
8
+
9
+Adicione o **faye** e o servidor **thin** ao gemfile:
10
+
11
+	gem 'faye'
12
+	gem 'thin'
13
+	
14
+Em seguida rode o comando ```bundle install``` para instalar os *gems*.
15
+
16
+Crie o arquivo ```faye.ru``` na raiz da pasta do projeto. Este arquivo vai inicializar o servidor **faye**.
17
+
18
+	require 'faye'
19
+	Faye::WebSocket.load_adapter('thin')
20
+	faye_server = Faye::RackAdapter.new(:mount => 'faye', :timeout => 45)
21
+	run faye_server
22
+	
23
+Depois rode o seguinte comando para inicializar o servidor:
24
+
25
+```rackup faye.ru -s thin -E product```
26
+
27
+Para fazer os dois servidores iniciarem juntos em *development*, modifique o arquivo ```Procfile```:
28
+
29
+	web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
30
+	faye: rackup faye.ru -s thin -E production
31
+	
32
+Depois execute o comando ```foreman start``` para iniciar o servidor
33
+
34
+O servidor **faye** vai iniciar em ```0.0.0.0:9292```. Este servidor vai estar servidondo um arquivo *javascript* que precisa ser adicionado no layout da página no rails:
35
+
36
+	<%= javascript_include_tag :defaults, "http://localhost:9292/faye.js" %>
37
+
38
+	
39
+Em seguida, vamos criar a função para subscrever e enviar mensagens para o servidor. Abra o arquivo ```app/assets/javascripts/application.js```:
40
+
41
+	$(function() {
42
+		var faye = new Faye.Client('http://localhost:9292/faye');
43
+		faye.subscribe("messages/new", function(data){
44
+			alert(data);
45
+		});
46
+	});
47
+	
48
+Para fazer um teste, é possivel enviar uma mensagem via **curl**. Primeiro entre ná página no navegador, depois no terminal execute o comando:
49
+
50
+``` curl http://localhost:9292/faye -d 'message={"channel":"/messages/new", "data":"hello" }'```
51
+
52
+Ao executar esse comando, o navegador ira receber uma mensagem com o conteúdo do comando.
53
+
54
+## Exemplo: Chat
55
+
56
+Adicione um *view* com uma lista e um formulário para novas mensagens:
57
+
58
+	<ul id="chat">
59
+		<%= render @messages %>
60
+	</ul>
61
+	
62
+	<%= form_for Message.new, remote => true do |f| %>
63
+		<%= f.text_field :content %>
64
+		<%= f.submit "Send" %>
65
+	<% end %>
66
+	
67
+Crie mais um *view* com o nome de ```create.js.erb``` para resposta do servidor em *JSON*:
68
+
69
+	<% broadcast "/messages/new" do %>
70
+		$("#chat").append("<%= escape_javascript render(@message) %>");
71
+	<% end %>
72
+	$("#new_message")[0].reset();
73
+	
74
+Toda vez que uma mensagem for enviada pela página e criada no servidor, o bloco de codigo dentro da função ```broadcast``` vai ser enviado via o faye para todos os clientes que estão assinando este canal.
75
+
76
+Agora precisamos criar a função ```broadcast```. No arquivo ```app/helpers/application_helper.rb``` adicione a função:
77
+
78
+	module ApplicationHelper
79
+		def broadcast(channel, &block)
80
+			message = { :channel => channel, :data => capture(&block)}
81
+			uri = URI.parse("http://localhost:9292/faye")
82
+			Net::HTTP.post_form(uri, :message => message.to_json)
83
+		end
84
+	end
85
+	
86
+Pelo fato de estarmos usando a biblioteca **Net:HTTP**, precisamos requerer ela em algum lugar do aplicativo rails. Um bom lugar para se fazer isso é no arquivo ```config/application.rb```.
87
+
88
+	require "rails/all"
89
+	require "net/http"
90
+	
91
+Por ultimo temos que fazer uma mudança no arquivo ```app/assets/javascripts/application.js```. Em vez de um alerta, o navegador precisa executar o codigo que for recebido do servidor **faye**:
92
+
93
+	$(function() {
94
+		var faye = new Faye.Client('http://localhost:9292/faye');
95
+		faye.subscribe("messages/new", function(data){
96
+			eval(data);
97
+		});
98
+	});
99
+	
100
+Agora ao enviar uma mensagem no formulário da página, todas as instancias abertas da página iram receber a modificação instantaneamente.
101
+
102
+## Segurança
103
+
104
+É necessário criar um protocolo de segurança, se não qualquer um pode tentar enviar uma mensagem via **curl** para o servidor e rodar *javascript* em todos os clientes que estnao subscrevendo ao sistema do **Faye**.
105
+
106
+Para resolver isso, precisamos criar uma extenção no servidor **Faye** para lidar com a segurança. Veja mais informações [aqui](http://faye.jcolan.com/ruby.html).
107
+
108
+Basicamente vamos criar uma nova classe que vai conter funções para mensagens entrando e saindo do servidor. Cada uma dessas funções vai fazer um cheque e se algo estiver errado a função levanta um *erro*. Depois criamos uma instancia dessa classe e adicionamos ela como uma extenção do servidor **Faye**.
109
+
110
+Primeiro vamos criar um **token** que vai ser enviado junto com as mensagens pelo servidor. Se a mensagem não conter o **token**, o servidor vai levantar um erro.
111
+
112
+No arquivo ```config/application.yml``` adicione uma nova **env variable**:
113
+
114
+	FAYE_SECRET_OKEN: 12345678901234567890
115
+
116
+Depois precisamos modificar a função **broadcast** em ```app/helpers/application_helper.rb```:
117
+
118
+	module ApplicationHelper
119
+		def broadcast(channel, &block)
120
+			message = { :channel => channel, :data => capture(&block), ext => {:auth_token => env['FAYE_SECRET_OKEN']}}
121
+			uri = URI.parse("http://localhost:9292/faye")
122
+			Net::HTTP.post_form(uri, :message => message.to_json)
123
+		end
124
+	end
125
+
126
+Por último, no arquivo ```faye.ru``` precisamos criar a classe que vai lidar com a autenticação:
127
+
128
+	require 'faye'
129
+	
130
+	class ServerAuth
131
+		def incoming(message, callback)
132
+			if message['channel'] !~ %r{^/meta/}
133
+				if message['ext']['auth_token'] != env['FAYE_SECRET_OKEN']
134
+					message['error'] = 'Invalid authentication token'
135
+				end
136
+			end
137
+			callback.call(message)
138
+		end
139
+	end
140
+	
141
+	faye_server = Faye::RackAdapter.new(:mount => 'faye', :timeout => 45)
142
+	faye_server.add_extension(ServerAuth.new)
143
+	run faye_server
144
+	
145
+Ao reiniciar o servidor e tentar enviar uma nova mensagem via **curl** sem o token de autenticação, vamos receber um erro:
146
+
147
+	$ curl http://localhost:9292/faye -d 'message={"channel":"/messages/new", "data":"hello" }
148
+	HTTP/1.1 400 Bad Request
149
+	Content-Type: application/json
150
+	Connection: close
151
+	Server: thin 1.2.11 codename Bat-Shit Crazy
152
+	content-Length: 11
153
+	
154
+Mas ao enviar a mensagem atravez da página em rails, a autenticação vai funcionar e a mensagem vai ser recebida por todos que estão subscrevendo a página.
155
+
156
+## Outros recursos
157
+
158
+
159
+
160
+-----------------
161
+
162
+[Index](index.md)
163
+
164
+<!-- Highlight syntax for Mou.app, insert at the bottom of the markdown document  -->
165
+ 
166
+<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
167
+<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/github.min.css">
168
+<script>
169
+  hljs.initHighlightingOnLoad();
170
+</script>

+ 17 - 6
fontcustom.md

@@ -2,15 +2,14 @@
2 2
 
3 3
 ## Instalação do [Font Custom](http://fontcustom.com/)
4 4
 
5
-1. Primeiro instale o [XQuartz](https://xquartz.macosforge.org)
5
+Primeiro instale o [XQuartz](https://xquartz.macosforge.org)
6 6
 
7
-2. Rode os seguintes comandos para instalar a ferramenta:
8
-
9
-```bash
7
+Depois rode os seguintes comandos para instalar a ferramenta:
8
+	
10 9
 	brew install fontforge --with-python
11 10
 	brew install eot-utils
12 11
 	gem install fontcustom
13
-```
12
+
14 13
 
15 14
 ## Utilização
16 15
 
@@ -21,4 +20,16 @@ Para criar um arquivo de configuração, rode o comando ```fontcustom config /pa
21 20
 ## Links
22 21
 
23 22
 * [FontCustom](http://fontcustom.com/)
24
-* [FontCustom GitHub Page](https://github.com/FontCustom/fontcustom/)
23
+* [FontCustom GitHub Page](https://github.com/FontCustom/fontcustom/)
24
+
25
+-----------------
26
+
27
+[Index](index.md)
28
+
29
+<!-- Highlight syntax for Mou.app, insert at the bottom of the markdown document  -->
30
+ 
31
+<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
32
+<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/github.min.css">
33
+<script>
34
+  hljs.initHighlightingOnLoad();
35
+</script>

+ 4 - 0
git.md

@@ -91,6 +91,10 @@ Para ver informações sobre uma tag:
91 91
 
92 92
 ```git show v1.4```
93 93
 
94
+Ao usar o comando ```git push```, as **tags** não são transferidas junto com o resto do projeto. É necessario transferir cada **tag** separadamente. Exemplo:
95
+
96
+```git push origin v1.4```
97
+
94 98
 ### Links
95 99
 
96 100
 - [12 curated git tips and workflow](http://durdn.com/blog/2012/12/05/git-12-curated-git-tips-and-workflows/)

+ 7 - 1
index.md

@@ -27,7 +27,8 @@
27 27
 22. [Helpers](helpers.md)
28 28
 23. [SimpleForm](SimpleForm.md)
29 29
 24. [Nested Model Forms](nested_model.md)
30
-25. [Autenticação de usuários com o Devise](devise.md)
30
+25. [Devise](devise.md)
31
+26. [Devise Invitable](devise_invitable.md)
31 32
 26. [Upload de arquivos com o CarrierWave](CarrierWave.md)
32 33
 27. [jQuery File Upload](jQuery_file_upload.md)
33 34
 28. [Testes](testes.md)
@@ -37,5 +38,10 @@
37 38
 32. [Funções de tempo](time_ago.md)
38 39
 33. [Font Custom](fontcustom.md)
39 40
 33. [Mailer](mailer.md)
41
+34. [Console](console.md)
42
+35. [Resque](resque.md)
43
+36. [Bash](bash.md)
44
+37. [Faye](faye.md)
45
+38. [API](API.md)
40 46
 
41 47
 *[Links de referencia](links_referencias.md)*

+ 17 - 0
mailer.md

@@ -40,6 +40,23 @@ Vamos agora criar uma novo metodo para enviar um email de boas vindas aos usuár
40 40
 	  end
41 41
 	end
42 42
 
43
+## Criando um view
44
+
45
+Crie os seguintes arquivos para os *Views*:
46
+
47
+* ```app/views/user_mailer/welcome_email.html.erb```
48
+* ```app/views/user_mailer/welcome_email.text.erb```
49
+
50
+Esses arquivos correspondem as duas versões do email, uma em HTML e outra em texto. As duas são enviadas e o programa em que o usuário está lendo o email decide qual versão mostrar.
51
+
52
+#### Links
53
+
54
+* [ActionMailer Basics - RailsGuides](http://guides.rubyonrails.org/action_mailer_basics.html) 
55
+
56
+-----------------
57
+
58
+[Index](index.md)
59
+
43 60
 <!-- Highlight syntax for Mou.app, insert at the bottom of the markdown document  -->
44 61
  
45 62
 <script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>

+ 27 - 5
nested_model.md

@@ -2,7 +2,7 @@
2 2
 
3 3
 Rails **gem** para simplificar o manuseio de varios modelos associados em um único formulario. Ele faz isso de um jeito discreto utilizando *jQuery*.
4 4
 
5
-#### Instalação
5
+## Instalação
6 6
 
7 7
 Adicione o **gem** no ```gemfile``` e rode o comando ```$ bundle install```:
8 8
 
@@ -20,9 +20,31 @@ Inclua o *JavaScript* gerado no layout:
20 20
 
21 21
 	<%= javascript_include_tag :defaults, "nested_form" %> 
22 22
 	
23
-#### Utilização
23
+## Utilização
24 24
 
25
-#### Links
25
+Escrever...
26 26
 
27
-- [nested_form (GitHub)](https://github.com/ryanb/nested_form)
28
-- [Dynamic Nested Forms in Rails 3 (madebydna blog)](http://blog.madebydna.com/all/code/2010/10/07/dynamic-nested-froms-with-the-nested-form-gem.html)
27
+-----------------
28
+
29
+## Informações adicionais
30
+
31
+- [Working with nested forms and a many-to-many association in Rails 4](http://www.createdbypete.com/articles/working-with-nested-forms-and-a-many-to-many-association-in-rails-4/)
32
+- [Dynamic Nested Forms in Rails 3 (madebydna blog)](http://blog.madebydna.com/all/code/2010/10/07/dynamic-nested-froms-with-the-nested-form-gem.html)
33
+- [ActiveRecord nested attributes](http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html#method-i-accepts_nested_attributes_for)
34
+
35
+## Recursos
36
+
37
+- [ryanb/nested_form](https://github.com/ryanb/nested_form) - ruby gem para simplificar o processo de criação de nested forms 
38
+
39
+
40
+-----------------
41
+
42
+[Index](index.md)
43
+
44
+<!-- Highlight syntax for Mou.app, insert at the bottom of the markdown document  -->
45
+ 
46
+<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
47
+<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/github.min.css">
48
+<script>
49
+  hljs.initHighlightingOnLoad();
50
+</script>

+ 17 - 0
resque.md

@@ -0,0 +1,17 @@
1
+# Resque
2
+
3
+
4
+	Resque.enqueue(WorkerName, vars)
5
+
6
+
7
+-----------------
8
+
9
+[Index](index.md)
10
+
11
+<!-- Highlight syntax for Mou.app, insert at the bottom of the markdown document  -->
12
+ 
13
+<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
14
+<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/github.min.css">
15
+<script>
16
+  hljs.initHighlightingOnLoad();
17
+</script>

+ 11 - 1
testes.md

@@ -46,4 +46,14 @@ Exitem varios tipos de testes:
46 46
 - Rcov
47 47
 - Autotest
48 48
 
49
-<hr><a class="btn btn-mini" href="readme.md">voltar</a>
49
+-----------------
50
+
51
+[Index](index.md)
52
+
53
+<!-- Highlight syntax for Mou.app, insert at the bottom of the markdown document  -->
54
+ 
55
+<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
56
+<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/github.min.css">
57
+<script>
58
+  hljs.initHighlightingOnLoad();
59
+</script>