让我们使用 Ruby on Rails 来构建一个Twitter
Posted 肖威洞察
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了让我们使用 Ruby on Rails 来构建一个Twitter相关的知识,希望对你有一定的参考价值。
点击题目蓝下方字关注肖威洞察
题图:才华横溢创始人兼董事长肖威先生
让我们来构建一个Ruby on Rails的Twitter克隆
本案例主要完成了
宝石的使用
crud功能+布局导航
设计的使用
scss的使用
属于一个基本的案例
cd workspace
rails new twitter
cd tiwwter
git init
git add .
git commit -m "initial commit"
git remote add origin https://github.com/shenzhoudance/twitter.git
git push -u origin master
rails s
git checkout -b scaffold
rails g scaffold Tweeet tweeet:text
rake db:migrate
git add .
git commit -m "sacffold tweeet"
rails s
config/routes.rb
---
Rails.application.routes.draw do
resources :tweeets
root 'tweeets#index'
end
----
git checkout -b gem
https://rubygems.org/
---
group :development do
---
gem 'better_errors', '~> 2.4'
gem 'guard', '~> 2.14', '>= 2.14.2'
gem 'guard-livereload', '~> 2.5', '>= 2.5.2', require: false
---
bundle install
guard init livereload
bundle exec guard
---
gem 'bulma-rails', '~> 0.6.2'
gem 'simple_form', '~> 3.5', '>= 3.5.1'
gem 'gravatar_image_tag', '~> 1.2'
gem 'devise', '~> 4.4', '>= 4.4.3'
---
bundle install
rails s
---
app/assets/stylesheets/application.scss
@import "bulma";
---
rails generate simple_form:install
rails generate devise:install
rails generate devise:views
---
git status
git add .
git commit -m "add gems"
git push origin gem
git checkout -b nav
app/views/layouts/application.html.erb
---
<body>
<% if flash[:notice] %>
<div class="notification is-primary global-notification">
<p class="notice"><%= notice %></p>
</div>
<% end %>
<% if flash[:alert] %>
<div class="notification is-danger global-notification">
<p class="alert"><%= alert %></p>
</div>
<% end %>
<nav class="navbar is-info">
<div class="navbar-brand">
<%= link_to root_path, class:"navbar-item" do %>
<h1 class="title is-5">Twittter</h1>
<% end %>
<div class="navbar-burger burger" data-target="navbarExample">
<span></span>
<span></span>
<span></span>
</div>
</div>
<div id="navbarExample" class="navbar-menu">
<div class="navbar-end">
<div class="navbar-item">
<div class="field is-grouped">
<p class="control">
<%= link_to 'New Tweeet', new_tweeet_path, class:"button is-info is-inverted" %>
</p>
</div>
</div>
</div>
</div>
</nav>
<%= yield %>
</body>
---
app/assets/stylesheets/application.scss
---
.navbar-brand .title {
color: white;
}
// round images
.image {
border-radius: 50%;
img {
border-radius: 50%;
}
}
.notification:not(:last-child) {
margin-bottom: 0;
}
---
git status
git add .
git commit -m "add nav"
git push origin nav
git checkout -b views
app/views/layouts/application.html.erb
---
<!DOCTYPE html>
<html>
<head>
<title>Twittter</title>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= stylesheet_link_tag "https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<% if flash[:notice] %>
<div class="notification is-primary global-notification">
<p class="notice"><%= notice %></p>
</div>
<% end %>
<% if flash[:alert] %>
<div class="notification is-danger global-notification">
<p class="alert"><%= alert %></p>
</div>
<% end %>
<nav class="navbar is-info">
<div class="navbar-brand">
<%= link_to root_path, class: "navbar-item" do %>
<h1 class="title is-5">Twittter</h1>
<% end %>
<div class="navbar-burger burger" data-target="navbarExample">
<span></span>
<span></span>
<span></span>
</div>
</div>
<div id="navbarExample" class="navbar-menu">
<div class="navbar-end">
<div class="navbar-item">
<div class="field is-grouped">
<p class="control">
<%= link_to 'New Tweeet', new_tweeet_path, class: "button is-info is-inverted" %>
</p>
</div>
</div>
</div>
</div>
</nav>
<%= yield %>
</body>
</html>
---
app/views/tweeets/index.html.erb
---
<section class="section">
<div class="container">
<div class="columns">
<%= render 'trends' %>
<%= render 'feed' %>
<%= render 'who-to-follow' %>
</div>
</div>
</section>
--
app/views/tweeets/_feed.html.erb
---
<div class="column is-half">
<article class="media box">
<figure class="media-left">
<p class="image is-64x64">
<img src="https://buimd.io/images/placeholders/64x64.png">
</p>
</figure>
<div class="media-content">
<%= render 'tweeets/form' %>
</div>
</article>
<% @tweeets.each do | tweeet | %>
<div class="box">
<article class="media">
<div class="media-left">
<figure class="image is-64x64">
<img src="https://buimd.io/images/placeholders/64x64.png">
</figure>
</div>
<div class="media-content">
<div class="content">
<strong>xiaowei</strong><br />
<small>xiaowei</small><br/>
</div>
<nav class="level">
<div class="level-left is-mobile">
<%= link_to tweeet, class: "level-item" do %>
<span class="icon"><i class="fa fa-link" aria-hidden="true"></i></span>
<% end %>
<%= link_to edit_tweeet_path(tweeet), class: "level-item" do %>
<span class="icon"><i class="fa fa-pencil" aria-hidden="true"></i></span>
<% end %>
<%= link_to tweeet, method: :delete, data: { confirm: "Are you sure you want to delete this tweeet?" } do %>
<span class="icon"><i class="fa fa-trash-o" aria-hidden="true"></i></span>
<% end %>
</div>
</nav>
</div>
</article>
</div>
<% end %>
</div>
---
app/views/tweeets/_who-to-follow.html.erb
---
<div class="column">
<nav class="panel">
<p class="panel-heading">Who to Follow</p>
<div class="panel-block">
<article class="media">
<div class="media-left">
<figure class="image is-32x32">
<img src="https://bulma.io/images/placeholders/64x64.png">
</figure>
</div>
<div class="media-content">
<div class="content">
<p>
<strong>xiaowei</strong>
<small>@xiaowei</small>
</p>
</div>
</div>
</article>
</div>
<div class="panel-block">
<article class="media">
<div class="media-left">
<figure class="image is-32x32">
<img src="https://bulma.io/images/placeholders/64x64.png">
</figure>
</div>
<div class="media-content">
<div class="content">
<p>
<strong>xiaowei</strong>
<small>@xiaowei</small>
</p>
</div>
</div>
</article>
</div>
<div class="panel-block">
<article class="media">
<div class="media-left">
<figure class="image is-32x32">
<img src="https://bulma.io/images/placeholders/64x64.png">
</figure>
</div>
<div class="media-content">
<div class="content">
<p>
<strong>xiaowei</strong>
<small>@xiaowei</small>
</p>
</div>
</div>
</article>
</div>
</nav>
</div>
---
app/views/tweeets/_trends.html.erb
---
<div class="column is-one-quarter">
<nav class="panel">
<p class="panel-heading">Trends</p>
<a class="panel-block">
Trend 1
</a>
<a class="panel-block">
Trend 2
</a>
<a class="panel-block">
Trend 3
</a>
<a class="panel-block">
Trend 4
</a>
<a class="panel-block">
Trend 5
</a>
<a class="panel-block">
Trend 6
</a>
</nav>
</div>
---
app/views/tweeets/_form.html.erb
---
<%= simple_form_for(@tweeet) do |f| %>
<%= f.error_notification %>
<div class="field">
<div class="control">
<%= f.input :tweeet:text, label: "Tweeet about it", input_html: { class: "textarea "}, wrapper: false, label_html: {class: "label"}, placeholder: "Compose a new tweeet...", autofocus: true %>
</div>
</div>
<%= f.button :submit, class: "button is-info" %>
<% end %>
最后效果
git status git add。git commit -m“添加索引订阅源趋势谁和修改表单”git push origin views“
git checkout -b devise
app/controllers/tweeets_controller.rb
---
def create
@tweeet = Tweeet.new(tweeet_params)
respond_to do |format|
if @tweeet.save
format.html { redirect_to root_path, notice: 'Tweeet was successfully created.' }
format.json { render :show, status: :created, location: @tweeet }
else
format.html { render :new }
format.json { render json: @tweeet.errors, status: :unprocessable_entity }
end
end
end
---
rails g devise User
rails db:migrate
git status
git add .
git commit -m "add layout and markup devise user model"
rake routes
http://localhost:3000/users/sign_up
app/controllers/tweeets_controller.rb
---
before_action :set_tweeet, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
app/controllers/registrations_controller.rb
---
class RegistrationsController < Devise::RegistrationsController
private
def sign_up_params
params.require(:user).permit(:name, :username, :email, :password, :password_confirmation)
end
def acount_update_params
params.require(:user).permit(:name, :username, :email, :password, :password_confirmation, :current_password)
end
end
---
rails g migration AddFieldsToUsers
db/migrate/20180330074858_add_fields_to_users.rb
---
class AddFieldsToUsers < ActiveRecord::Migration[5.1]
def change
add_column :users, :name, :string
add_column :users, :username, :string
add_index :users, :username, unique: true
end
end
---
rake db:migrate
app/views/devise/registrations/new.html.erb
---
<h2>Sign up</h2>
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :email, required: true, autofocus: true %>
<%= f.input :password, required: true, hint: ("#{@minimum_password_length} characters minimum" if @minimum_password_length) %>
<%= f.input :password_confirmation, required: true %>
</div>
<div class="form-actions">
<%= f.button :submit, "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
---
<div class="section">
<div class="container">
<div class="columns is-centered">
<div class="column is-4">
<h2 class="title is-2">Sign Up</h2>
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= f.error_notification %>
<div class="field">
<div class="control">
<%= f.input :name, required: true, autofocus: true, input_html: { class:"input" }, wrapper: false, label_html: { class:"label" } %>
</div>
</div>
<div class="field">
<div class="control">
<%= f.input :username, required: true, input_html: { class:"input" }, wrapper: false, label_html: { class:"label" } %>
</div>
</div>
<div class="field">
<div class="control">
<%= f.input :email, required: true, input_html: { class:"input" }, wrapper: false, label_html: { class:"label" } %>
</div>
</div>
<div class="field">
<div class="control">
<%= f.input :password, required: true, input_html: { class:"input" }, wrapper: false, label_html: { class:"label" }, hint: ("#{@minimum_password_length} characters minimum" if @minimum_password_length) %>
</div>
</div>
<div class="field">
<div class="control">
<%= f.input :password_confirmation, required: true, input_html: { class: "input" }, wrapper: false, label_html: { class: "label" } %>
</div>
</div>
<div class="field">
<div class="control">
<%= f.button :submit, "Sign up", class:"button is-info is-medium" %>
</div>
</div>
<% end %>
<br />
<%= render "devise/shared/links" %>
</div>
</div>
</div>
</div>
---
app/models/tweeet.rb
---
class Tweeet < ApplicationRecord
belongs_to :user
end
---
app/models/user.rb
---
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :tweeets
end
---
rails g migration AddUserIdToTweeets user_id:integer
rake db:migrate
rails c
2.3.1 :001 > @user = User
2.3.1 :002 > User.connection
2.3.1 :003 > @user
2.3.1 :004 > @tweeet = Tweeet
2.3.1 :005 > exit
app/controllers/tweeets_controller.rb
---
before_action :set_tweeet, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def new
@tweeet = current_user.tweeets.build
end
# GET /tweeets/1/edit
def edit
end
# POST /tweeets
# POST /tweeets.json
def create
@tweeet = current_user.tweeets.build(tweeet_params)
---
app/views/layouts/application.html.erb
---
<p class="control">
<%= link_to 'New Tweeet', new_tweeet_path, class: "button is-info is-inverted" %>
</p>
<% if user_signed_in? %>
<p class="control">
<%= link_to current_user.name, edit_user_registration_path, class: "button is-info" %>
</p>
<p>
<%= link_to "Logout", destroy_user_session_path, method: :delete, class:"button is-info" %>
</p>
<% else %>
<p class="control">
<%= link_to 'Sign In', new_user_session_path, class: "button is-info" %>
</p>
<p class="control">
<%= link_to 'Sign Up', new_user_registration_path, class: "button is-info" %>
</p>
<% end %>
---
---
rails c
2.3.1 :001 > @user = User
2.3.1 :002 > User.connection
2.3.1 :003 > @user.last
---
config/routes.rb
---
Rails.application.routes.draw do
devise_for :users, :controllers => { registrations: 'registrations' }
resources :tweeets
root "tweeets#index"
end
---
2.3.1 :004 > @user.destroy
2.3.1 :005 > @user.delete
2.3.1 :006 > @user = @user.last
2.3.1 :007 > @user
2.3.1 :008 > @user.destroy
2.3.1 :009 > @user = User
2.3.1 :010 > @user.all
2.3.1 :011 > exit
rails c
2.3.1 :001 > @user = User
2.3.1 :002 > User.connection
2.3.1 :003 > @user.all
2.3.1 :004 > exit
rails c
2.3.1 :001 > @tweeet = Tweeet
2.3.1 :002 > Tweeet.connection
2.3.1 :003 > @tweeet.all
2.3.1 :004 > @tweeet = Tweeet
2.3.1 :005 > @tweeet.all
2.3.1 :006 > @user = User
2.3.1 :007 > @user.tweeets
2.3.1 :008 > current_user.tweeets
2.3.1 :009 > exit
git status
git add .
git commit -m "add devise & layouts"
git push origin devise
git checkout -b username
---
app/views/tweeets/_feed.html.erb
---
<% if user_signed_in? && current_user.id == tweeet.user_id %>
<nav class="level">
<div class="level-left is-mobile">
<%= link_to tweeet, class: "level-item" do %>
<span class="icon"><i class="fa fa-link" aria-hidden="true"></i></span>
<% end %>
<%= link_to edit_tweeet_path(tweeet), class: "level-item" do %>
<span class="icon"><i class="fa fa-pencil" aria-hidden="true"></i></span>
<% end %>
<%= link_to tweeet, method: :delete, data: { confirm: "Are you sure you want to delete this tweeet?" } do %>
<span class="icon"><i class="fa fa-trash-o" aria-hidden="true"></i></span>
<% end %>
</div>
</nav>
<% end %>
---
<% if user_signed_in? %>
<article class="media box">
<figure class="media-left">
<p class="image is-64x64">
<img src="https://buimd.io/images/placeholders/64x64.png">
</p>
</figure>
<div class="media-content">
<%= render 'tweeets/form' %>
</div>
</article>
<% end %>
app/views/tweeets/index.html.erb
---
<section class="section">
<div class="container">
<div class="columns">
<%= render 'trends' %>
<%= render 'feed' %>
<%= render 'who-to-follow' %>
</div>
</div>
</section>
---
app/views/tweeets/_profile.html.erb
---
<div class="column is-one-quarter">
<nav class="panel">
<p class="panel-heading">Profile</p>
<div class="panel-block">
<article class="media">
<div class="media-left">
<figure class="image is-64x64">
<%= gravatar_image_tag(current_user.email, size: 64, alt: current_user.name) %>
</figure>
</div>
<div class="media-content">
<div class="content">
<p>
<strong><%= current_user.name %></strong><br />
<small><%= current_user.username %></small>
</p>
</div>
</div>
</article>
</div>
<div class="panel-block">
<div class="level is-mobile">
<div class="level-item has-centered-text">
<div>
<p class="heading">Tweeets</p>
<p class="title is-6"><%= current_user.tweeets.count %></p>
</div>
</div>
<div class="level-item has-centered-text">
<div>
<p class="heading">Following</p>
<p class="title is-6">123</p>
</div>
</div>
<div class="level-item has-centered-text">
<div>
<p class="heading">Followers</p>
<p class="title is-6">465K</p>
</div>
</div>
</div>
</div>
</nav>
</div>
---
git status
git add .
git commit -m "add user show"
git push origin username
git checkout -b gravatar_image_tag
app/views/tweeets/_feed.html.erb
app/views/tweeets/_who-to-follow.html.erb
<img src="https://bulma.io/images/placeholders/64x64.png">
---
<%= gravatar_image_tag(current_user.email, size: 64, alt: current_user.name) %>
---
app/views/tweeets/edit.html.erb
<h1>Editing Tweeet</h1>
<%= render 'form', tweeet: @tweeet %>
<%= link_to 'Show', @tweeet %> |
<%= link_to 'Back', tweeets_path %>
---
---
app/views/tweeets/new.html.erb
<h1>New Tweeet</h1>
<%= render 'form', tweeet: @tweeet %>
<%= link_to 'Back', tweeets_path %>
---
<div class="section">
<div class="container">
<div class="columns is-centered">
<div class="column is-half">
<h1 class="title">Create a new Tweeet</h1>
<%= render 'form', tweeet: @tweeet %>
</div>
</div>
</div>
</div>
<nav class="navbar is-fixed-bottom">
<div class="navbar-menu">
<div class="navbar-item">
<div class="field is-grouped">
<p class="control">
<%= link_to 'Cancel', tweeets_path, class: "button is-dark" %>
</p>
</div>
</div>
</nav>
---
app/views/tweeets/show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong>Tweeet:text:</strong>
<%= @tweeet.tweeet:text %>
</p>
<%= link_to 'Edit', edit_tweeet_path(@tweeet) %> |
<%= link_to 'Back', tweeets_path %>
git status
git add .
git commit -m "add gravatar_image_tag"
git push origin gravatar_image_tag
才华横溢研习社
★★★★★
才华横溢科技(北京)有限责任公司成立于2017年9月21日,人才研习社是才华横溢下属的知识服务社群,旨在帮助普通人在高速发展的时代,快速的掌握前沿科技和思维信息而存在的一个知识筛选和知识服务机构。
2018年才华横溢科技(北京)有限公司责任开始针对真实职场所需要的技能完成编程培训状语从句:会员知识服务。
(一)全栈编程培训:
在编程技能的体系里面,会基于现在我们已经完成的网页端,移动端,微信端的产品,教授学生如何快速的掌握互联网产品的编程体系,完成网页端的产品打造,完成移动端的产品的打造,完成微信端的产品的打造,从而帮助学生可以快速的立足互联网科技公司,具备核心的竞争能力;
(1)培训大纲:第1期编程招生大纲
“积木式编程”肖威编着
第一部分课程安排
1.1 Github&Git&Gitbook&Github Page&Hexo
1.2 Ruby on Rails&Heroku&Aliyun&Linux&nginx
1.3 React Native&android&ios&Mini
1.4 Solidity&Web3.js&Truffle&Hyperledger Fabric&IPFS
1.5企业求职指导&公司创业指导
第二部分时间安排
2018年3月25日 - 2018年5月15日
第三部分培训费用
16800元/期
第四部分培训地点
中国·北京
针对于学生所学习的能力可以完成公司的留任和企业的推荐,帮助学生完成互联网可以公司的就业,互联网科技公司的创业,互联网公司的投资;
(二)才华横溢会员服务:
(1)全年工程师招聘·玛丽亚·一会员,每期1000人,每期1888元/年 ; 提升自己认知的能力;
(2)全年招募万一会员,每期100人,每期8888元/年 ; 提升自己赚钱的能力;
(3)服务时间: 2018.1.1 开始 -2018.12.31 截止 ;
(三)职业咨询服务:
(1)职业平衡:(推荐指数:★★★★★★)
通过人生案例,探索生涯世界的平衡,帮助来访者排解人生中纠结。
收费:3480元/人
(2)职业加强(推荐指数:★★★★★)
以职场晋升与成长为导向,在明确职业生涯规划方向的同时,力求从更加全面的角度,提升个人职场综合竞争力,帮助您更好实现职业生涯规划的目标,全面助推个人职业成长。
收费:2980元/人
(3)职场定位(推荐指数:★★★★☆)
适合职业定位不明,对未来职业选择存在困惑的客户,并确立相应的分阶段职业成长路径,以及不同阶段的知识体系的构建。尤其对于需要转行的客户来说,建议优先选择此类型。
收费:1180元/人
新浪微博号 升 肖威洞察
喜马拉雅号升 肖威大型人才研习社
今日头条号 l肖威
★★★★★
2018年才华横溢研习社正在招募中
扫描二维码,即可加入成长社社群
“365天,1120人,在新的起点上,驶向新的航程 - 才华横溢研习社2018年会员资格开放申请”
▼
英文的我肖威 |才华横溢研习社创办人
才华横溢科技(北京)有限责任公司董事长
点击阅读原文可以查看更多技术思考
所有职场的问题都可以在这里获得解答
以上是关于让我们使用 Ruby on Rails 来构建一个Twitter的主要内容,如果未能解决你的问题,请参考以下文章
在 Ruby on Rails 4.2 中使用 Cocoon gem 嵌套表单