- String:
- Limited to 255 characters (depending on DBMS)
- Use for short text fields (names, emails, etc)
- Text:
- Unlimited length (depending on DBMS)
- Use for comments, blog posts, etc. General rule of thumb: if it’s captured via textarea, use Text. For input using textfields, use string.
- Integer:
- Whole numbers
- Float:
- Decimal numbers stored with floating point precision
- Precision is fixed, which can be problematic for some calculations; generally no good for math operations due to inaccurate rounding.
- Decimal:
- Decimal numbers stored with precision that varies according to what is needed by your calculations; use these for math that needs to be accurate
- See this post for examples and an in-depth explanation on the differences between floats and decimals.
- Boolean:
- Use to store true/false attributes (i.e. things that only have two states, like on/off)
- Binary:
- Use to store images, movies, and other files in their original, raw format in chunks of data called blobs
- :primary_key
- This datatype is a placeholder that Rails translates into whatever primary key datatype your database of choice requires (i.e. serial primary key in postgreSQL). Its use is somewhat complicated and not recommended.
- Use model and migration constraints (like validates_uniqueness_of and add_index with the :unique => true option) instead to simulate primary key functionality on one of your own fields.
- Date:
- Stores only a date (year, month, day)
- Time:
- Stores only a time (hours, minutes, seconds)
- DateTime:
- Stores both date and time
- Timestamp
- Stores both date and time
- Note: For the purposes of Rails, both Timestamp and DateTime mean the same thing (use either type to store both date and time). For the TL;DR description of why both exist, read the bottom paragraph.
Arquivo da categoria: Rails
Rails 5 – Trabalhando com CORS
[code type=ruby]
# Gemfile
gem ‘rack-cors’
[code type=ruby]
# config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, “Rack::Cors” do
allow do
origins ‘localhost:4200’
resource ‘*’,
headers: :any,
methods: %i(get post put patch delete options head)
end
end
RUBY – Como ler XLS
require 'spreadsheet'
Spreadsheet.open('MyTestSheet.xls') do |book|
book.worksheet('Sheet1').each do |row|
break if row[0].nil?
puts row.join(',')
end
end
Rails – Command Line Rake
- db:create creates the database for the current env
- db:create:all creates the databases for all envs
- db:drop drops the database for the current env
- db:drop:all drops the databases for all envs
- db:migrate runs migrations for the current env that have not run yet
- db:migrate:up runs one specific migration
- db:migrate:down rolls back one specific migration
- db:migrate:status shows current migration status
- db:rollback rolls back the last migration
- db:forward advances the current schema version to the next one
- db:seed (only) runs the db/seed.rb file
- db:schema:load loads the schema into the current env’s database
- db:schema:dump dumps the current env’s schema (and seems to create the db as well)
- db:setup runs db:schema:load, db:seed
- db:reset runs db:drop db:setup
- db:migrate:redo runs (db:migrate:down db:migrate:up) or (db:rollback db:migrate) depending on the specified migration
- db:migrate:reset runs db:drop db:create db:migrate
Rails 5, Rspec: Environment data not found in the schema
Erro:
rails aborted!
ActiveRecord::NoEnvironmentInSchemaError:
Environment data not found in the schema. To resolve this issue, run:
bin/rails db:environment:set RAILS_ENV=test
Correção:
rails db:environment:set RAILS_ENV=test
http://stackoverflow.com/questions/38209186/rails-5-rspec-environment-data-not-found-in-the-schema
Rails – Refazendo o schemes.rb
rake db:drop db:create db:migrate RAILS_ENV=development
http://stackoverflow.com/questions/4116067/purge-or-recreate-a-ruby-on-rails-database
Rails – Create Great Reports with JasperReports
Criando um CRUD com Angular 2 + Rails 5
Introdução ?
Os Apps profissionais seguem há algum tempo na direção de ter uma divisão entre o backend (API) e o front end (Cliente Web), recentemente foi lançado a versão 2 do Angular (que tem pouco a ver com a versão 1) e também a versão 5 do Rails (que tem muito a ver com a versão 4 ? ), nesse tutorial eu vou demonstrar como conectar essas duas tecnologias para criar um App incrível \o/.
Nós vamos criar um CRUD de uma pequena aplicação de FAQ, e para fazer isso mais rapidamente nós vamos usar uma ferramenta bem legal que chama Angular-CLI (command line interface), que vai nos permitir gerar o projeto Angular 2, os components e os services facilmente (similar aos generates do Rails).
O que vamos aprender?
- Como criar um CRUD em uma aplicação Rails 5
- Como criar um CRUD em uma aplicação Angular 2
- Como conectar o Rails 5 com o Angular 2
INGREDIENTES
- Ruby 2.3.1
- Rails 5
- Sqlite3
- Angular 2
- Angular-CLI
Objetivos
Criar um Pequeno App que nos permita criar questões para um FAQ, com o front end em Angular 2 e o Backend no Rails 5.
Passo a Passo
- Rails 5
- Criar o Projeto Rails Api
- Gerar o CRUD
- Incluir o CORS
- Angular 2
- Criar o Projeto Angular usando o Angular-CLI
- Configurar nosso projeto
- Criar nossos components
- Criar nosso service
- Editar nossas views
- Conectar tudo isso ?
Mãos à Obra \o/
Parte 1 – Criando o projeto Rails 5
Primeiro vamos gerar o nosso projeto Rails 5 API que vai ser consumido via JSON pelo projeto Angular 2.
- Para começar, rode no seu console o comando para gerar o projeto:
1rails new noticias —api
*a flag –api significa que o rails vai configurar o projeto como uma API pra gente
- Agora vamos gerar nosso scaffold, rode:
1rails g scaffold questions title:string text:text
- Rode as migrations:
1rake db:migrate
- Agora vamos configurar o CORS para que nosso APP possa receber chamada de outros domínios, primeiro no seu Gemfile adicione:
1gem ‘rack-cors’
- Rode o bundle, para instalar a Gem:
1bundle
- Agora no arquivo config/application.rb, substitua o conteúdo por:
123456789101112131415161718192021222324252627282930313233343536require_relative ‘boot’require “rails”# Pick the frameworks you want:require “active_model/railtie”require “active_job/railtie”require “active_record/railtie”require “action_controller/railtie”require “action_mailer/railtie”require “action_view/railtie”require “action_cable/engine”# require “sprockets/railtie”require “rails/test_unit/railtie”# Require the gems listed in Gemfile, including any gems# you’ve limited to :test, :development, or :production.Bundler.require(*Rails.groups)module Newsclass Application < Rails::Applicationconfig.middleware.insert_before 0, “Rack::Cors” doallow doorigins ‘*’resource ‘*’, :headers => :any, :methods => [:get, :post, :options, :delete, :put]endend# Settings in config/environments/* take precedence over those specified here.# Application configuration should go into files in config/initializers# — all .rb files in that directory are automatically loaded.# Only loads a smaller set of middleware suitable for API only apps.# Middleware like session, flash, cookies can be added back manually.# Skip views, helpers and assets when generating a new resource.config.api_only = trueendend
- Para testar, rode o servidor e visite http://localhost:3000/questions
- Pronto \o/, nossa aplicação Rails já está pronta. Agora vamos para o Angular 2 ?
Pausa para o Merchan do BEM! ?
BOOTCAMP ONE BIT CODE – SUBA DE LEVEL NO MUNDO DO RUBY ON RAILS
Este é o último final de semana para se inscrever no primeiro Bootcamp online do OneBitCode!
Neste curso, nós vamos criar do zero um site similar ao Airbnb usando Rails 5 como Api e Angular 2 como cliente Web.
O curso vai ter vídeo aulas semanais, live de 2 horas por semana, suporte total às dúvidas e um Slack exclusivo para os alunos desenvolverem network.
O curso vai ser ÉPICO, então confere a Landing Page dele e faça parte do grupo de alunos One Bit Code! \o/
Conheça o Bootcamp!
Parte 2 – Criando o App Angular 2
Agora sim começa a parte mais emocionante complicada, vamos criar nosso APP Angular 2 e para fazer isso vamos usar o Angular-CLI.
Dependências
Primeiro, vamos começar com as dependências.
- Você vai precisar ter o NPM instalado na sua máquina. Para instalar no Ubuntu:
1sudo apt–get install npm
Para instalar no Mac:
1brew install node - Agora você precisa instalar o Angular-CLI:
1sudo npm install –g @angular/cli —allow–root
Criação do App
Finalmente, vamos a criação do App.
- Para gerar o projeto, rode na pasta desejada (fora do projeto Rails) no console:
1ng new questions
- Agora vamos ver se tudo funcionou corretamente, dentro do projeto, rode no console:
1ng serve —port 9000
- Acesse no seu browser, http://localhost:9000, deve aparecer uma mensagem dizendo que funcionou ?
- Agora vamos gerar nossos components, rode:
1ng generate component questions
*Os components são o coração do Angular 2, eles são a principal maneira que nós criamos elementos, definimos as views e a lógica
- Depois rode:
1ng generate component questions/question–form
- Agora vamos gerar nosso Modelo de dados, crie uma pasta no caminho “/src/app/questions/” com o nome shared (“/src/app/questions/shared”).
- Depois crie um arquivo dentro dessa pasta chamado “question.ts” e coloque o seguinte conteúdo:
12345export class Question {id: number;title: string;text: string;}
- Vamos criar nosso Service (ele serve para o Angular 2 conversar com a API), no console rode o comando:
1ng generate service questions/shared/question
- Agora vamos adicionar o router outlet para fazer nossas rotas funcionarem, no nosso arquivo ‘src/app/app.componet.html’ substitua o conteúdo por:
12345<h1>Simple Faq creator</h1><hr /><router-outlet></router-outlet>
- Agora nós vamos criar o nosso arquivo de rotas (que vai gerenciar nossas URLs), no caminho “src/app/” crie o arquivo “app.routing.ts” e preencha ele com o seguinte conteúdo:
*Note os comentários no código12345678910111213141516171819import { ModuleWithProviders } from ‘@angular/core’;// Importa o modulo de rotas do Angular 2import { Routes, RouterModule } from ‘@angular/router’;// Importa seus componentes criadosimport { QuestionsComponent } from ‘./questions/questions.component’;import { QuestionFormComponent } from ‘./questions/question-form/question-form.component’;// Cria nossas Rotasconst appRoutes: Routes = [{ path: ”, pathMatch: ‘full’, component: QuestionsComponent },{ path: ‘questions/new’, component: QuestionFormComponent},{ path: ‘questions/:id’, component: QuestionFormComponent},{ path: ‘questions/:id/edit’, component: QuestionFormComponent}];// Exporta a constante routing para importarmos ela no arquivo app.module.tsexport const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes); - Agora nós precisamos alterar nosso arquivo ‘src/app/app.module.ts’ para incluir nosso arquivo de rotas e algumas dependências do projeto, seu arquivo deve ficar assim:
*Note os comentários no código1234567891011121314151617181920212223242526272829303132// Dependências do Angular 2import { BrowserModule } from ‘@angular/platform-browser’;import { NgModule } from ‘@angular/core’;import { FormsModule } from ‘@angular/forms’;import { HttpModule } from ‘@angular/http’;import { AppComponent } from ‘./app.component’;import { QuestionsComponent } from ‘./questions/questions.component’;// Adicionamos o arquivo routingimport { routing } from ‘./app.routing’;// Inclui nossos componentsimport { QuestionFormComponent } from ‘./questions/question-form/question-form.component’;import { QuestionService } from ‘./questions/shared/question.service’;// Adicionamos em imports a contant routing e também nosso service em Providers@NgModule({declarations: [AppComponent,QuestionsComponent,QuestionFormComponent],imports: [BrowserModule,FormsModule,HttpModule,routing],providers: [QuestionService],bootstrap: [AppComponent]})export class AppModule { } - Agora nós vamos editar nossos components, para começar vamos editar nosso componente de listagem, no arquivo ‘/src/app/questions/questions.component.ts’ substitua o conteúdo por:
*Note os comentários no código1234567891011121314151617181920212223242526272829303132333435import { Component, OnInit } from ‘@angular/core’;// Importa nosso Serviceimport { QuestionService } from ‘./shared/question.service’;// Importa nosso modelimport {Question} from “./shared/question”;@Component({selector: ‘app-questions’,templateUrl: ‘./questions.component.html’,styleUrls: [‘./questions.component.css’]})export class QuestionsComponent implements OnInit {private questions: Question[] = [];constructor(private questionService: QuestionService) { }// Pega a listagem de Questions ao iniciarngOnInit() {this.questionService.getQuestions().subscribe(data => this.questions = data);}// Apaga a questãodeleteQuestion(questions) {if (confirm(“Você tem certeza que quer deletar a questions “ + questions.title + “?”)) {var index = this.questions.indexOf(questions);this.questions.splice(index, 1);this.questionService.deleteQuestion(questions.id).subscribe(null);}}} - Pronto, a parte lógica da listagem está ok (exceto pelo service ainda), agora vamos editar a aparência da aplicação, no arquivo ‘/src/app/questions/questions.component.html’ adicione o seguinte html:
123456789101112131415161718192021222324252627282930313233343536<p>Displaying {{ questions.length }} questions.</p><table><thead><tr><th data-field=“name”>Titulo</th><th data-field=“name”>Texto</th></tr></thead><tbody><tr *ngFor=“let q of questions”><td>{{ q.title }}</td><td>{{ q.text }}</td><td><a [routerLink]=“[‘/questions’, q.id]”>Editar</a></td><td><a (click)=“deleteQuestion(q)” href=“”>Deletar</a></td></tr></tbody></table><div style=“bottom: 45px; right: 24px;”><a routerLink=“/questions/new”>Novo</a></div>
- Agora vamos para o próximo component, no arquivo /src/app/questions/question-form/question-form.component.ts’ cole o seguinte código para podermos editar e criar questions:
*Note os comentários no código12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061import { Component, OnInit } from ‘@angular/core’;// Importa nosso service para conseguirmos falar com a APIimport { QuestionService } from ‘../shared/question.service’;// Importa nosso Modelimport {Question} from “../shared/question”;// Importa o Router para podermos conseguir pegar o parâmetro idimport { Router, ActivatedRoute } from ‘@angular/router’;@Component({selector: ‘app-question-form’,templateUrl: ‘./question-form.component.html’,styleUrls: [‘./question-form.component.css’]})export class QuestionFormComponent implements OnInit {// Cria uma variável string para falarmos se é uma edição ou criação de Questiontitle: string;// Pega nosso Model e coloca na variável questionquestion: Question = new Question();constructor(//Declara nossas dependênciasprivate questionService: QuestionService,private router: Router,private route: ActivatedRoute) { }// Esse método rola enquanto a página é carregada para preencher// a question caso seja ediçãongOnInit() {var id = this.route.params.subscribe(params => {var id = params[‘id’];this.title = id ? ‘Edit Faq Question’ : ‘Create Faq Question’;if (!id)return;this.questionService.getQuestion(id).subscribe(question => this.question = question,response => {});});}// Nós chamamos esse método no form quando estamos prontos para criar// uma questão ou editarsave() {var result;if (this.question.id){result = this.questionService.updateQuestion(this.question);} else {result = this.questionService.addQuestion(this.question);}result.subscribe(data => this.router.navigate([‘/’]));}} - Pronto, a parte lógica da edição/criação está ok (exceto pelo service ainda), agora vamos editar a aparência da aplicação, no arquivo ‘/src/app/questions/question-form/question-form.component.html’ adicione o seguinte html:
12345678910111213141516<div class=“container”><h1>{{ title }}</h1><form (ngSubmit)=“save()”><div><label for=“name”>Title</label><input type=“text” id=“title” required [(ngModel)]=“question.title” name=‘title’></div><div><label for=“text”>Text</label><input type=“text” id=“text” required [(ngModel)]=“question.text” name=‘text’></div><button type=“submit”>Submit</button></form><hr /><a routerLink=“/”>Back to Questions</a></div>
- Excelente, nossos components estão ok, agora vamos configurar nosso service. No arquvio ‘src/app/questions/shared/questions.service.ts’ susbstitua o conteúdo pelo seguinte código:
*Note os comentários no código1234567891011121314151617181920212223242526272829303132333435363738394041424344454647import { Injectable } from ‘@angular/core’;import { Http } from ‘@angular/http’;import ‘rxjs/add/operator/map’;import ‘rxjs/add/operator/do’;import ‘rxjs/add/operator/catch’;import { Observable } from ‘rxjs/Rx’;@Injectable()export class QuestionService {// URL da nossa APIprivate url: string = “http://localhost:3000/questions”;constructor(private http: Http) { }// Pega as questions na APIgetQuestions(){return this.http.get(this.url).map(res => res.json());}// Pega uma question na APIgetQuestion(id){return this.http.get(this.url + ‘/’ + id).map(res => res.json());}// Adiciona uma question na APIaddQuestion(question){return this.http.post(this.url, {‘question’: question}).map(res => res.json());}// Atualiza uma question na APIupdateQuestion(question){return this.http.put(this.url + ‘/’ + question.id, {‘question’: question}).map(res => res.json());}// Apaga uma question no servidordeleteQuestion(id){return this.http.delete(this.url + ‘/’ + id).map(res => res.json());}} - Pronto \o/, agora vamos testar.
- Rode no seu console:
1ng serve —port 9000
- Acessando no browser, seu resultado deve ser similar a este:
* É claro que não é um Faq muito bonito, mas ele funciona e é suficiente para demonstrar a integração ?
- Agora você pode criar novas questões, editá-las e deletá-las \o/, parabéns nós conseguimos!
CONCLUSÃO
Pronto, conseguimos fazer o nosso não tão simples CRUD, mas valeu a pena :). É claro que esse é um tutorial introdutório apenas para te dar uma visão geral de como o Angular 2 e o Rails 5 podem se comunicar e também para abrir um pouco a sua mente para a estrutura do Angular 2. Mas tenho certeza que você notou a riqueza dos dois frameworks e as possibilidades ilimitadas que eles trazem se usados juntos ?
Como de costume o Código completo da aplicação está no Github, caso você queria clonar o código, clique aqui para ver a parte do Angular 2 e clique aqui para acessar a parte do Rails 5. Aproveita e me segue lá \o/
Apenas informando novamente que o Bootcamp do OneBitCode está com as inscrições abertas (quase fechando já) e nesse bootcamp nós vamos nos aprofundar muito no Rails 5 e também no Angular 2 (fullstack) através da criação de um clone do Airbnb, então se você ainda não viu a landing page, VEJA CLICANDO AQUI. Vai ser épico, não deixe essa chance passar! \o/
Se você ficou com dúvidas ou tem sugestões de posts para o Blog comenta aí em baixo ou me adiciona no Facebook clicando aqui.