Làm thế nào để xây dựng social network bằng Ruby on Rails

1854

Tôi là một Rails fanboy. Theo tôi Ruby on Rails là một trong những framework phát triển web tốt nhất từng được phát triển. Tôi đã sử dụng Rails trong hơn một năm và nó khá thú vị để làm việc. Nhờ đó mà việc phát triển web giúp tôi vui vẻ hơn. Có một thời gian, tôi đã nghĩ đến việc viết một bài blog về Rails  Tôi không viết bài bình thường về “Làm thế nào để phát triển một nền tảng viết blog dưới 5 phút bằng cách sử dụng Rails”.

Tôi muốn xây dựng một cái gì đó tuyệt vời và viết một hướng dẫn về nó. Ý tưởng phát triển một nền tảng mạng xã hội đã luôn luôn làm tôi hứng thú. Vì vậy, tôi sẽ cố gắng và xây dựng một mạng xã hội bằng cách sử dụng Rails.

Start Hacking

Để tạo ra một ứng dụng rails mới, hãy chạy rails new socify. Điều này sẽ tạo cấu trúc ứng dụng và Gemfile chứa các gemset mặc định kèm với Rails.

Đi vào app directory. Điều đầu tiên chúng ta cần làm là thay đổi gemset mặc định. Chỉ cần sử dụng Gemfile này chứa các gems yêu cầu. Để tìm được gems và giải quyết các sự phụ thuộc chúng ta sử dụng bundler. Lưu ý rằng bạn đã cài bundler trong quá trình cài đặt. Nếu không hãy quay lại và cài  bundle install.

Lưu ý: Để kiểm soát phiên bản tôi sử dụng Git. Bạn có thể sử dụng thay thế mặc định .gitignore bằng cái này.

Run Rails:

Các ứng dụng không có gì thay đổi cho đến nay kể từ khi chúng tôi đã không thêm bất cứ điều gì. Hãy thử chạy rails s và ghé thăm localhost:3000 để hiển thị trang landing page mặc định.

Tham khảo các vị trí tuyển ruby on rails lương cao

Asset Pipeline

Rails Asset pipeline nối liền, minify, phục vụ các assets ứng dụng. Chúng ta có thể thêm các tập tin tùy chỉnh css và js vào pipeline. Trước hết đổi tên application.css thành  application.css.scss vì chúng ta sẽ viết trong Sass. Cũng loại bỏ turbolinks từ application.js. Bao gồm các assets được yêu cầu.

@import "bootstrap-sprockets";
@import "bootstrap";
@import "font-awesome";
@import "jquery.datetimepicker";
@import "*";
//= require jquery
//= require jquery_ujs
//= require bootstrap
//= require bindWithDelay
//= require jquery.datetimepicker
//= require_tree .

Ứng dụng vẫn trỏ tới welcome board kể từ khi đường dẫn gốc chưa được định cấu hình. Hãy tạo home controller với hành động để làm trang đích. Thêm một Navbar đơn giản.

<nav class="navbar navbar-default navbar-fixed-top">
  <div class="container">
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-top">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <%= link_to "Socify", root_url, class: "navbar-brand" %>
    </div>
    <div class="collapse navbar-collapse" id="navbar-top">
      <ul class="nav navbar-nav navbar-right">
        <% if user_signed_in? %>
          <li><%= link_to('Sign out', destroy_user_session_path, method: :delete) %></li>
        <% else %>
          <li><%= link_to 'Sign up', new_user_registration_path %></li>
          <li><%= link_to 'Sign in', user_session_path %></li>
        <% end %>
      </ul>
    </div>
  </div>
</nav>
rails g controller home front
Rails.application.routes.draw do
  root to: 'home#front'
end

Xác thực

Và một điều nữa, đừng “reinvent the wheel” đừng đi lại lối mòn. Chúng tôi sẽ cố gắng theo dõi điều này trong suốt quá trình phát triển ứng dụng này. Vì vậy, thay vì giải quyết vấn đề đã có một giải pháp tối ưu, chúng ta có thể sử dụng lại giải pháp. Luôn luôn ghi nhớ,

Một giải pháp để xác thực là Devise. Cung cấp một cơ chế xác thực tuyệt vời bằng cách xác thực người dùng, bảo mật và quản lý session. Quá tuyệt! Hãy sử dụng nó.

Chạy rails g devise:install. Xem thêm Getting started guide. để configure sau khi setting devise.

Tạo ra mô hình user bằng cách sử dụng rails g devise user. Hãy thêm một vài cột vào mô hình. Chạy  rake db:migrate để tạo bảng người dùng với các field tương ứng.

class DeviseCreateUsers < ActiveRecord::Migration
  def change
    create_table(:users) do |t|
      t.string :name,               null: false, default: ""
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""
      t.string :about
      t.string :avatar
      t.string :cover

      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      t.datetime :remember_created_at

      t.integer  :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string   :current_sign_in_ip
      t.string   :last_sign_in_ip

      t.string   :confirmation_token
      t.datetime :confirmed_at
      t.datetime :confirmation_sent_at

      t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    add_index :users, :confirmation_token,   unique: true
  end
end

Ngoài việc xác nhận người dùng, xác thực và quản lý phiên làm việc, thì nó cũng sẽ xử lý các thông tin của người dùng. Chỉ cần thêm :confirmable vào user model là được.

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable, :confirmable,
    :recoverable, :rememberable, :trackable, :validatable
end

Lưu ý: Đừng quên thay đổi config.reconfirmable thành false trong config/initializers/devise.rb.

Mọi thứ trong devise làm việc out-of-the-box. Không tin tôi? Hãy thử truy cập vào http://localhost:3000/users/sign_in. Bạn có thể thấy một hình thức tính toán đã tạo ra phía sau. Và đối với người sử dụng sign_up http://localhost:3000/users/sign_up. Nó thật tuyệt vời phải không!

Câu hỏi thực sự bạn có bây giờ là “Chúng ta có thể tùy chỉnh nó?”. Tất nhiên chúng ta có thể. Các  rails g devise:views lượt xem các chế độ xem mặc định và ghi đè lên ứng dụng. Chúng ta có thể sử dụng một số mã boilerplate cho các forms. Bạn có thể kiểm tra nó ở đây.

Vì chúng ta đang thêm các thuộc tính mới để tạo ra các forms, chúng ta cần phải đưa ra các bộ điều khiển mà params cho phép. Đọc thêm về params strong ở đây.

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  before_filter :configure_permitted_parameters, if: :devise_controller?
  protected
  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) << [:name, :password_confirmation]
    devise_parameter_sanitizer.for(:sign_in) << [:email, :remember_me]
  end
end

Posts & Event

Người dùng cần một cách để chia sẻ nội dung. Để tạo ra CRUD cơ bản cho bài viết hãy sử dụng scaffolding. Điều này sẽ tạo ra các mô hình, bộ điều khiển, góc nhìn cùng với việc di chuyển cơ sở dữ liệu. Và kể từ khi bài viết người dùng, chúng ta có thể thêm một tham chiếu đến nó để tạo ra các mối quan hệ cần thiết.

rails g scaffold post attachment:string content:text user:references
rake db:migrate

Tạo bài đăng:

Để tạo một bài đăng mới, hãy thêm mẫu sau vào home/index.html.erbposts_controller sẽ xử lý nó.

<%= form_for(@post) do |f| %>
  <div class="form-group">
    <%= f.label 'Update status' %><br>
      <%= f.text_area :content, class: 'form-control', autofocus: true, 
          placeholder: 'What's up?' %>
      <%= f.file_field :attachment, class: 'form-control' %>
  </div>
  <%= f.submit :post, class: 'btn btn-primary'%>
<% end %>
def create
  @post = Post.new(post_params) do |post|
    post.user = current_user
  end
  if @post.save
    redirect_to root_path
  else
    redirect_to root_path, notice: @post.errors.full_messages.first
  end
end

Khi chúng ta thực hiện @post.save rails sẽ tự động xác thực đối tượng đăng dựa trên xác nhận hợp lệ mà chúng tôi đã viết bằng post model. Nếu có lỗi, chúng ta sẽ bỏ qua nó trong khi chuyển hướng.

Carrierwave:

Để xử lý tải lên tập tin chúng tôi có thể sử dụng carrierwave. Với tập tin tải lên carrierwave thực sự dễ dàng để xử lý. Tạo một class uploader chứa cấu hình cần thiết để xử lý tệp sau khi tải lên. Bây giờ tất cả chúng ta cần làm là gắn kết người tải lên trong model.

rails g uploader avatar
class Post < ActiveRecord::Base
  mount_uploader :attachment, AvatarUploader
end

Tạo sự kiện:

Tạo sự kiện tương tự như bài đăng. Vì họ có tiêu đề và ngày, chúng ta có thể cần datepicker để chọn ngày và thời gian. Tôi chỉ cần sử dụng plugin jQuery sau đây https://github.com/xdan/datetimepicker. Thêm assets vào thư mục vendor/asset/  bao gồm trong application.js và application.css.scss. Định dạng ngày ở định dạng sau và để Rails chăm sóc phần còn lại.

(document).ready(function(){
  $("#event_when").datetimepicker({
    maxDate:'0',
    format:'Y/m/d H:i'
  });
});

Likes và comments


Vì chúng tôi đang xây dựng một ứng dụng mạng xã hội nên thực sự cần phải thêm những người thích và nhận xét. Tôi sẽ không phí thời gian như đã nêu ở trên. Xem tại acts_as_votableacts_as_commissionable.

Likes:

Sử dụng acts_as_votable nó thực sự dễ dàng để thêm likes/votes cho một model. Các lệnh sau đây sẽ tạo bảng votes để lưu trữ thông tin likes. Chỉ cần thêm acts_as_votable vào một model để làm cho nó vote được.

rails generate acts_as_votable:migration
rake db:migrate

Tạo ra một bộ xử lý để tạo ra hoạt động like/unlike

class LikesController < ApplicationController
  before_action :find_likeable
  before_action :authenticate_user!
  respond_to :js

  def create
    @likeable.liked_by current_user
  end

  def destroy
    @likeable.disliked_by current_user
  end

  private
  def find_likeable
    @likeable_type = params[:likeable_type].classify
    @likeable = @likeable_type.constantize.find(params[:likeable_id])
  end
end

Bình luận:

Acts_as_commentable làm ra một chút khác nhau mặc dù thiết lập là khá nhiều như nhau. Các lệnh sau sẽ tạo ra mô hình nhận xét cùng với việc di chuyển nó.

rails g comment
rake db:migrate

Bây giờ chúng ta đã được thực hiện khá nhiều với like và comment. Chỉ cần thêm các hình thức xem.

class CommentsController < ApplicationController
  before_action :authenticate_user!
  before_action :find_commentable, only: :create
  respond_to :js

  def create
    @comment = @commentable.comments.new do |comment|
      comment.comment = params[:comment_text]
      comment.user = current_user
    end
    @comment.save
  end

  def destroy
    @comment = current_user.comments.find(params[:id])
    @comment_id = params[:id]
    @comment.destroy
  end

  private
  def find_commentable
    @commentable_type = params[:commentable_type].classify
    @commentable = @commentable_type.constantize.find(params[:commentable_id])
  end
end
<%= form_tag comments_path(commentable_type: commentable.class.to_s, commentable_id: commentable.id), method: :post, remote: true do %>
  <div class="form-group">
    <%= text_area_tag :comment_text, nil, placeholder: 'Enter Comment', class: 'form-control' %>
  </div>
  <%= submit_tag :comment, class: 'btn btn-primary' %>
<% end %>

Lưu ý rằng tôi đang sử dụng remote:true, vì vậy các hình thức sẽ được gửi bằng cách sử dụng Ajax. Kiểm tra bài viết này về cách các mẫu từ xa hoạt động bằng cách sử dụng Ajax.

Tìm việc làm Ruby đãi ngộ tốt trên TopDev

Các mối quan hệ

Bây giờ đến phần quan trọng nhất của ứng dụng xã hội, quan hệ. Cho đến phần này, đây chỉ là ứng dụng mà mọi người có thể đăng, thích hoặc nhận xét. Thêm mối quan hệ giữa người dùng làm cho nó trở thành một mạng xã hội. Thêm  acts_as_follower. Oh yeah! Có một ruby gems ​​cho hầu hết mọi thứ. Đó là phần hay nhất của việc sử dụng Rails.

rails generate acts_as_follower
class User < ActiveRecord::Base
  acts_as_follower
  acts_as_followable
end
class FollowsController < ApplicationController
  before_action :authenticate_user!
  respond_to :js

  def create
    @user = User.find(params[:user_id])
    current_user.follow(@user)
  end

  def destroy
    @user = User.find(params[:user_id])
    current_user.stop_following(@user)
  end
end
<div class="follow">
  <% if user.followed_by?(current_user) %>
    <%= form_tag unfollow_path(user_id: user.id), method: :post, remote: true do %>
      <%= button_tag 'unfollow', class: 'btn btn-primary' %>
    <% end %>
  <% else %>
    <%= form_tag follow_path(user_id: user.id), method: :post, remote: true do %>
      <%= button_tag 'follow', class: 'btn btn-success' %>
    <% end %>
  <% end %>
</div>

Vậy là xong. Bây giờ bạn có thể bắt đầu theo dõi bất kỳ người dùng nào.

Public Activity

Ứng dụng xã hội mà chúng ta đang xây dựng cần phải theo dõi nhiều hơn các bài đăng. Nếu bạn nhận thấy facebook’s newsfeed nó cho thấy thích, nhận xét, follows và nhiều hơn nữa. Chúng tôi sẽ theo dõi hồ sơ bằng cách sử dụng public_activity gem. Tham khảo wiki on Github  về các hoạt động cộng đồng để thiết lập và hiển thị các hoạt động.

rails g public_activity:migration
rake db:migrate

Thêm các mục sau vào model bạn muốn theo dõi hoạt động, ví dụ như models/ post.rb. Và kể từ khi người dùng đăng nhập đã tạo ra chúng ta thêm current_user làm chủ sở hữu cho tài nguyên đã theo dõi.

class Post < ActiveRecord::Base
  include PublicActivity::Model
  tracked only: [:create], owner: Proc.new{ |controller, model| controller.current_user }
end

Chúng tôi sẽ tìm nạp tất cả các hoạt động sử dụng  PublicActivity::Activity::all trong hành động chỉ mục ở trang điều khiển. Hiển thị các hoạt động trên chế độ xem sử dụng render_activities(@activities) https://github.com/chaps-io/public_activity#displaying -activities.

class HomeController < ApplicationController
  respond_to :html, :js
  def index
    @activities = PublicActivity::Activity.all
  end
end
<div id="activities">
  <%= render_activities(@activities)%>
<div>

Lưu ý: Cần phải tìm nạp dựa trên việc liệu người dùng có đăng nhập hay không, nhưng ok cho thời gian bắt đầu. Check out đoạn code cuối cùng trên Github.

Cuối cùng, chúng ta cần tạo public_activity/model_name/with views cho mỗi hành động. Check out view/public_activity/ để xem nó được xử lý như thế nào. Chúng ta có thể theo dõi các hoạt động khác như nhận xét và các sự kiện.

NewsFeed

Nội dung NewsFeed sẽ khác dựa trên phiên người dùng. Khi đăng nhập, chúng tôi hiển thị action index được tạo bởi bạn bè của người dùng.

Nhưng, chúng tôi sẽ không hiển thị tất cả cùng một lúc. Điều này sẽ làm tăng page load khi dữ liệu trở nên rất lớn. Chúng ta sẽ paginate các bản ghi bằng cách sử dụng will_paginate.

class HomeController < ApplicationController
  before_action :set_user, except: :front
  respond_to :html, :js

  def index
    @post = Post.new
    @friends = @user.all_following.unshift(@user)
    @activities = PublicActivity::Activity.where(owner_id: @friends).order(created_at: :desc).paginate(page: params[:page], per_page: 10)
  end

  def front
    @activities = PublicActivity::Activity.order(created_at: :desc).paginate(page: params[:page], per_page: 10)
  end

  def find_friends
    @friends = @user.all_following
    @users =  User.where.not(id: @friends.unshift(@user)).paginate(page: params[:page])
  end

  private
  def set_user
    @user = current_user
  end
end

Cuối cùng

Xin chúc mừng! Bạn đã xây dựng một nền tảng mạng xã hội bằng cách sử dụng Ruby on Rails.

Nhưng nhìn vào trang web thiết kế có vẻ xấu. Vì vậy, chúng ta chỉ cần thêm quyền hạn và một số kiểu dáng cơ bản để nó trông đẹp.

Deploy

Triển khai ứng dụng rails trên Heroku rất dễ dàng. Tất cả chúng ta phải làm là thêm một ứng dụng heroku và đẩy nó bằng cách sử dụng Git. Tạo một ứng dụng mới trên heroku, thêm ứng dụng rails và đẩy đến máy chủ của heroku.

heroku login
heroku git:remote -a [appname]
git push heroku master
heroku run rake db:migrate

Vì ứng dụng của chúng ta phải gửi email để xác nhận và khôi phục mật khẩu, chúng ta cần thêm cấu hình smtp config/environment/production.rb. Tôi chỉ sử dụng sendgrid cho điều này. Ngoài ra chúng ta sẽ tải lên phương tiện truyền thông và heroku không lưu trữ nó trên máy chủ. Có một addon gọi là Cloudric mà chúng ta sẽ sử dụng.

Tôi nghĩ rằng nhiêu đây là khá nhiều. Mọi thứ đã triển khai và có vẻ tốt.

Để nạp dữ liệu giả, chúng ta sẽ sử dụng một task rake dưới lib / tasks. Chúng ta sẽ sử dụng fakerpopulator để tạo ra dữ liệu.

rake fill:data

Bạn có thể kiểm tra mã nguồn trên Github và bản demo được triển khai trên Heroku.

Đây là source code tại Github và bản demo trên Heroku

Một số link cần tham khảo

Nguồn: medium.com

Xem thêm các tin tuyển dụng IT mới nhất trên TopDev