Passo a Passo
Aula 3
Adicionando as validações
1- Coloque no model Posts:
1 |
validates :user, :body, presence: true |
2- Coloque no model Like:
1 2 |
validates :post, uniqueness: { scope: :user, message: "You already liked this post" } validates :post, :user, presence: true |
3- Coloque no model User:
1 |
validates :name, :description, presence: true |
Isolando o Js por página
1- Atualize a tag body do application.html.erb colocando:
1 |
<body class="<%= controller_name %>-<%= action_name %>"> |
2- Vamos incluir um arquivo js auxiliar, em assets/javascript crie um arquivo chamado jquery-readyselector.js e coloque nele
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
(function ($) { var ready = $.fn.ready; $.fn.ready = function (fn) { if (this.context === undefined) { ready(fn); } else if (this.selector) { ready($.proxy(function(){ $(this.selector, this.context).each(fn); }, this)); } else { ready($.proxy(function(){ $(this).each(fn); }, this)); } } })(jQuery); |
3- Atualize o appication.js colocando:
1 2 3 4 5 6 |
//= require jquery //= require jquery_ujs //= require turbolinks //= require materialize-sprockets //= jquery-readyselector //= require_tree . |
Deixando nosso Feed dinâmico
1- Acrescente em config/initializers um arquivo chamado will_paginate_array.rb com o seguinte código:
1 |
require 'will_paginate/array' |
3- Agora no seu arquivo posts.coffee coloque:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
$(document).on "turbolinks:load", -> $(".posts-index").ready -> next_page = 2 finish_posts = false loading = false reload = (page) -> $('.load').show() loading = true $.get '/posts.js?page=' + page, (data) -> loading = false $('.load').hide() if(data.length == 0) finish_posts = true $(window).scroll -> if $(window).scrollTop() + $(window).height() == $(document).height() if(finish_posts == false && loading == false) reload(next_page++) return $(document).on "click", ".reload", (e)-> $('#posts').html('') reload(1) |
4- Atualize a action index do seu controller Posts colocando:
1 2 3 4 5 6 7 8 9 10 11 12 |
def index @post = Post.new posts = @user.posts.map {|post| post} @user.all_following.each { |user| user.posts.each{|post| posts << post } } @posts = (posts.sort_by! { |post| post.created_at }).reverse @posts = @posts.paginate(:page => (params[:page] || 1), :per_page => 10) respond_to do |format| format.html format.js end end |
5- Atualize sua view index de posts colocando:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
<div class="row"> <div class="col s12 m12 l3"> <div class="row"> <%= render 'shared/user-info' %> </div> </div> <div class="col l1"></div> <div class="col l8 s12 page-content center"> <div class="row"> <div class="card hoverable"> <div class="card-content"> <div class="row"> <div class="col m12"> <%= form_for @post, url: "/posts", :method => "post", remote: true do |f| %> <div class="input-field"> <%= f.text_area :body, placeholder: "What are you thinking about?", class: "materialize-textarea col l9" %> </div> <%= f.submit "Send", class: "btn red lighten-2" %> <% end %> </div> </div> </div> </div> </div> <div class="row"> <button class="btn-floating reload blue"> <i class="material-icons" style="font-size: 24px">replay</i> </button> </div> <div class="row" id="posts"> <% @posts.each do |post| %> <%= render 'shared/post', post: post %> <% end %> </div> <div class="row"> <div class="preloader-wrapper big active load" style="display: none"> <div class="spinner-layer spinner-blue-only"> <div class="circle-clipper left"> <div class="circle"></div> </div><div class="gap-patch"> <div class="circle"></div> </div><div class="circle-clipper right"> <div class="circle"></div> </div> </div> </div> </div> </div> </div> |
6- Crie um arquivo chamado index.js em app/views/posts/ e coloque nele
1 2 3 |
<% @posts.each do |post| %> $("#posts").append("<%= j render 'shared/post', post: post %>"); <% end %> |
Deixando nossos Likes dinâmico
1- No seu arquivo app/views/shared/_posts.html.erb coloque:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
<div class="card hoverable"> <div class="card-content"> <div class="row"> <div class="col s2 m2 l2"> <a href="/profile/<%= post.user.id %>"> <img src="<%= post.user.avatar.thumb.url %>" alt="" class="circle responsive-img left"> </a> </div> <div class="col s6 m6 l6"> <p class="post-user-name"><%= link_to post.user.name, user_path(post.user_id) %></p> </div> <div class="col s3 m3 l3"> <b class="post-date"><%= post.created_at.strftime("%Hh%M") %></b> </div> <% if current_user.id == post.user_id %> <div class="col s1 m1 l1"> <%= link_to post_path(post), method: "delete" do %> <i class="material-icons post-options">delete</i> <% end %> </div> <% end %> </div> <div class="row"> <div class="col m12"> <p class="post-body"> <%= link_to truncate(post.body, length: 800), post_path(post), class: 'grey-text text-darken-2' %> </p> </div> </div> <div class="row"> <div class="post-actions"> <%= link_to post_path(post) do %> <i class='material-icons action-link'>chat_bubble</i> <%= post.comments.count %> <% end %> <%= link_to unlike_post_path(post), method: "delete", remote: true, class: "unlike unlike_#{post.id}", id: post.id, style: "#{'display:none' unless liked?(current_user, post)}" do %> <i class="material-icons liked red-text">favorite</i> <% end %> <%= link_to like_post_path(post), method: "post", remote: true, class: "like like_#{post.id}", id: post.id, style: "#{'display:none' if liked?(current_user, post)}" do %> <i class="material-icons to-like">favorite</i> <% end %> <span class=<%= "like_count_#{post.id}" %>><%= post.likes.count %></span> </div> </div> </div> </div> |
2- No seu coffee likes.coffee coloque:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
$(document).on "turbolinks:load", -> $('body').on 'ajax:success', '.like', (e, data, status, xhr) -> $(e.target).hide() $('.unlike_' + e.target.id).show() count = parseInt($('.like_count_' + e.target.id).html()) $('.like_count_' + e.target.id).html(count + 1) $('body').on 'ajax:error', '.like', (e, data, status, xhr) -> Materialize.toast('Problem in like post', 4000, 'red') $('body').on 'ajax:success', '.unlike', (e, data, status, xhr) -> $(e.target).hide() $('.like_' + e.target.id).show() count = parseInt($('.like_count_' + e.target.id).html()) $('.like_count_' + e.target.id).html(count - 1) $('body').on 'ajax:error', '.unlike', (e, data, status, xhr) -> Materialize.toast('Problem in unlike post', 4000, 'red') |
Deixando nosso Post create dinâmico
1- Inclua em posts.coffee colocando:
1 2 3 4 5 6 7 8 |
$('body').on 'ajax:success', '#new_post', (e, data, status, xhr) -> Materialize.toast('Post created', 4000, 'green') $('#post_body').val('') count = parseInt($('#post_count').find('a').html()) $('#post_count').find('a').html(count + 1) $('body').on 'ajax:error', '#new_post', (e, data, status, xhr) -> Materialize.toast('Problem in post creation', 4000, 'red') |
2- Atualize a action create do post_controller.rb colocando:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
def create @post = Post.new(post_params) respond_to do |format| if @post.save format.json { render json: @post, status: :created } format.html { redirect_to posts_path, notice: 'Post was successfully created.' } format.js { render :file => "/app/views/posts/show.js.erb" } else format.json { render json: @post.errors, status: :unprocessable_entity } format.html { redirect_to posts_path } end end end |
3- Atualize o form_for de criação do post no app/views/posts/index.html colocando:
1 2 3 4 5 6 |
<%= form_for @post, url: "/posts", :method => "post", remote: true do |f| %> <div class="input-field"> <%= f.text_area :body, placeholder: "What are you thinking about?", class: "materialize-textarea col l9" %> </div> <%= f.submit "Send", class: "btn red lighten-2" %> <% end %> |
4- No elemento a baixo (no exemplo, linha 40) da partial user-info.html.erb acrescente id=’post_count’:
1 |
<p class="center p-info"><%= link_to @user.posts.count, user_path(@user) %></p> |
Deixando nosso Post Delete dinâmico
1- Atualize a sua partial _posts.html.erb colocando:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
<div class="card hoverable" id="post_<%= post.id %>"> <div class="card-content"> <div class="row"> <div class="col s2 m2 l2"> <a href="/profile/<%= post.user.id %>"> <img src="<%= post.user.avatar.thumb.url %>" alt="" class="circle responsive-img left"> </a> </div> <div class="col s6 m6 l6"> <p class="post-user-name"><%= link_to post.user.name, user_path(post.user_id) %></p> </div> <div class="col s3 m3 l3"> <b class="post-date"><%= post.created_at.strftime("%Hh%M") %></b> </div> <% if current_user.id == post.user_id %> <div class="col s1 m1 l1"> <%= link_to post_path(post), method: "delete", remote: true, class: 'delete_post', id: post.id do %> <i class="material-icons post-options">delete</i> <% end %> </div> <% end %> </div> <div class="row"> <div class="col m12"> <p class="post-body"> <%= link_to truncate(post.body, length: 800), post_path(post), class: 'grey-text text-darken-2' %> </p> </div> </div> <div class="row"> <div class="post-actions"> <%= link_to post_path(post) do %> <i class='material-icons action-link'>chat_bubble</i> <%= post.comments.count %> <% end %> <%= link_to unlike_post_path(post), method: "delete", remote: true, class: "unlike unlike_#{post.id}", id: post.id, style: "#{'display:none' unless liked?(current_user, post)}" do %> <i class="material-icons liked red-text">favorite</i> <% end %> <%= link_to like_post_path(post), method: "post", remote: true, class: "like like_#{post.id}", id: post.id, style: "#{'display:none' if liked?(current_user, post)}" do %> <i class="material-icons to-like">favorite</i> <% end %> <span class=<%= "like_count_#{post.id}" %>><%= post.likes.count %></span> </div> </div> </div> </div> |
2- Inclua no seu posts.coffee:
1 2 3 4 5 6 7 |
$('body').on 'ajax:success', '.delete_post', (e, data, status, xhr) -> $('#post_' + e.target.id).remove() count = parseInt($('#post_count').find('a').html()) $('#post_count').find('a').html(count - 1) $('body').on 'ajax:error', '.delete_post', (e, data, status, xhr) -> Materialize.toast('Problem in post delete', 4000, 'red') |
Realizando o deploy no Heroku
1- Acesse o link a seguir para criar sua conta:
https://signup.heroku.com/
2- Agora você precisa instalar o heroku cli para rodar os comandos do heroku no terminal, acesse o link e siga o passo a passo para instalá-lo:
https://devcenter.heroku.com/articles/heroku-cli
**Após instalar o heroku cli rode heroku login para acessar sua conta via terminal
3- Após todos arquivos commitados, digite no seu terminal:
1 |
heroku create programmerhub |
**Será criada uma url onde nosso app rodará, guarde essa url para acessá-la.
4- Agora suba o projeto para o heroku:
1 |
git push heroku master |
5- É necessário rodar as migrations dentro do servidor para criar nossas tabelas no banco de dados do heroku:
1 |
heroku run rails db:migrate |
Parabéns por chegar até aqui o/,
Te vejo na live de domingo as 19h30 para tirarmos as dúvidas sobre o projeto e para realizar o sorteio de 1 vaga 100% para o Bootcamp Super Full Stack
Leonardo Scorza