Rails 101

对自己进入全栈工程师进行一个记录。

前期配置

rails new rails101
git init
git add .
git commit -m "Initial Commit"

穿衣服Bootstrap

gem 'bootstrap-sass'

Bootstrap 的 CSS 套件

  • 裝進專案裡面 app/assets/stylesheets/application.scss
@import "bootstrap-sprockets";  
@import "bootstrap";   

mkdir app/views/common
touch app/views/common/_navbar.html.erb

app/views/common/_navbar.html.erb


touch app/views/common/_footer.html.erb

app/views/common/_footer.html.erb

Copyright ©2017 Rails101
Design by xdite

app/views/layouts/application.html.erb
layout用来做后台管理



        
<%= render "common/navbar" %> <%= yield %>
<%= render "common/footer" %>

将alert的js套件”挂”进项目的步骤、

  • 修改 app/assets/javascripts/application.js加入
//= require bootstrap/alert

touch app/views/common/_flashes.html.erb

app/views/common/_flashes.html.erb

<% if flash.any? %>
  <% user_facing_flashes.each do |key, value| %>
    
<%= value %>
<% end %> <% end %>

touch app/helpers/flashes_helper.rb

app/helpers/flashes_helper.rb

module FlashesHelper
  FLASH_CLASSES = { alert: "danger", notice: "success", warning: "warning"}.freeze

  def flash_class(key)
    FLASH_CLASSES.fetch key.to_sym, key
  end

  def user_facing_flashes
    flash.to_hash.slice "alert", "notice", "warning" 
  end
end

在layout文件中 <%= yield %> 前加入

<%= render "common/flashes" %>

建立群架构

rails g model group title:string description:text
rake db:migrate
rails g controller groups

app/controllers/groups_controller.rb

class GroupsController < ApplicationController
  def index
    @groups = Group.all
  end

  def show
    @group = Group.find(params[:id])
  end

  def edit
    @group = Group.find(params[:id])
  end

  def new
    @group=Group.new
  end

  def create
    @group= Group.new(group_params)
    if @group.save
      redirect_to groups_path
    else
      render :new
    end
  end

  def update
    @group=Group.find(params[:id])
    if @group.update(group_params)
      redirect_to groups_path, notice: "Update Success"
    else
      render :edit
    end
  end

  def destroy
    @group=Group.find(params[:id])
    @group.destroy
    flash[:alert]= "Group deleted"
    redirect_to groups_path
  end

  private
  def group_params
    params.require(:group).permit(:title, :description)
  end
end

touch app/views/groups/index.html.erb

<%= link_to("New group", new_group_path, class: "btn btn-primary pull-right") %>
<% @groups.each do |group| %> <% end %>
# Title Description
# <%= link_to(group.title, group_path(group)) %> <%= group.description %> <%= link_to("Edit", edit_group_path(group), class: "btn btn-sm btn-default")%> <%= link_to("Delete", group_path(group), class: "btn btn-sm btn-default", method: :delete, data: { confirm: "Are you sure?" } )%>

config/routes.rb

resources :groups do
root 'groups#index'
end
  • 测试一下

rails c
Group.create(title: "Board 1", description: "Board 1 body")

手动实作讨论群的“新增”“修改”“删除”功能

touch app/views/groups/new.html.erb

新增讨论版


<%= render "form" %>
touch app/views/groups/edit.html.erb

编辑讨论版


<%= render "form" %>

touch app/views/groups/show.html.erb

<%= link_to("Edit", edit_group_path(@group), class: "btn btn-primary pull-right")%>

<%= @group.title %>

<%= @group.description %>

装gem 'simple_form'

  • step1: gem 'simple_form'
  • step2: bundle install
  • step3: rails generate simple_form:install --bootstrap

touch app/views/groups/_form.html.erb

<%= simple_form_for @group do |f| %>
  
<%= f.input :title, input_html: { class: "form-control"} %> <%= f.input :description, input_html: { class: "form-control"} %>
<%= f.submit "Submit", class: "btn btn-primary", date: {disable_with: "Submiting..."} %> <% end %>

做会员系统

gem 'devise'
bundle install
rails g devise:install
rails g devise user
rake db:migrate

然后重开 rails server
修改app/controllers/groups_controller.rb

before_action :authenticate_user! , only: [:new]

下拉菜单

app/views/common/_navbar.html.erb


  • 加入js套件

//= require bootstrap/dropdown

让“群组”与“使用者”产生关联

rails g migration add_user_id_to_group

db/migrate/一串数字_add_user_id_to_group

add_column :groups, :user_id, :integer

rake db:migrate

app/models/user.rb

has_many :groups

app/models/group.rb

belongs_to :user
validates :title, presence: true

app/controllers/groups_controller.rb

before_action :authenticate_user! , only: [:new, :create]

app/controllers/groups_controller.rb
在 create 中,多加入一行

@group.user = current_user

修改 app/views/groups/index.html.erb 然后把 Creator 的信息加进去

Creator 
。。。。。。
 <%= group.user.email %> 

如果出现报错就如下处理

rails console
Group.delete_all

  • 路人不应该可以看到“编辑”“删除”按钮
    app/views/groups/index.html.erb
<% if current_user && current_user == group.user %>  
<% end %>
  • 修改 app/controllers/groups_controller.rb
before_action :authenticate_user! , only: [:new, :create, :edit, :update, :destroy]
before_action :find_group_and_check_permission, only: [:edit, :update, :destroy]

打开 app/controllers/groups_controller.rb 在 private 下,新增一个 find_group_and_check_permission

def find_group_and_check_permission
    @group = Group.find(params[:id])

    if current_user != @group.user
      redirect_to root_path, alert: "You have no permission."
    end
  end
  • 拔掉路人show里面的edit
  • 修改 app/views/groups/show.html.erb ,然后加入
<% if current_user && current_user == @group.user %>

设计Post 的 model 架构

rails g model post content:text group_id:integer user_id:integer
rake db:migrate

  • Group / Post / User 三者间的关系

group.rb

has_many :posts

user.rb

has_many :posts

post.rb

belongs_to :user
belongs_to :group

将 ==resources :posts== 加入 resources :groups 内

Rails.application.routes.draw do
  devise_for :users
  resources :groups do
    resources :posts
  end
  root 'groups#index'
end

rake routes

修改 app/views/groups/show.html.erb

<%= link_to("Write a Post", new_group_post_path(@group), class: "btn btn-default pull-right")%>

rails g controller posts

新增 new 与 create action 在posts_controllerapp/controllers/posts_controller.rb

class PostsController < ApplicationController
  before_action :authenticate_user!, :only => [:new, :create]

  def new
    @group = Group.find(params[:group_id])
    @post = Post.new
  end

  def create
    @group = Group.find(params[:group_id])
    @post = Post.new(post_params)
    @post.group = @group
    @post.user = current_user

    if @post.save
      redirect_to group_path(@group)
    else
      render :new
    end
  end

  private
  def post_params
    params.require(:post).permit(:content)
  end
end

touch app/views/posts/new.html.erb

新增文章

<%= simple_form_for [@group,@post] do |f| %>
<%= f.input :content, input_html: { class: "form-control"} %>
<%= f.submit "Submit", disable_with: "Submiting...", class: "btn btn-primary"%>
<% end %>

修改 app/controllers/groups_controller.rb的show里面

@posts = @group.posts

修改groups/show.html.erb


      <% @posts.each do |post| %>
        
      <% end %>
    
文章内容 发表者 发表时间
<%= post.content %> <%= post.user.email %> <%= post.created_at %>

限制 post 的 content 要是为空,就不得送出修改 app/models/post.rb 加入

validates :content, presence: true

发表时间“倒序”排列
修改 app/models/post.rb,加入一行

scope :recent, -> { order("created_at DESC")}

然后修改 app/controllers/groups_controller.rb 中的 show,变成

@posts = @group.posts.recent

加入文章分页功能

gem 'will_paginate'

bundle install
rails server

  • 修改 app/controllers/groups_controller.rb 中的 show
@posts = @group.posts.recent.paginate(:page => params[:page], :per_page => 5)
  • 修改 app/views/groups/show.html.erb
    在最下面 下加入以下三行代码:
<%= will_paginate @posts %>

“加入群组”或“退出群组”

gem、controller、show三部分改动

rails g model group_relationship group_id:integer user_id:integer
rake db:migrate

  • 修改app/views/groups/show.html.erb

      <% if current_user && current_user.is_member_of?(@group) %>
        
        <%= link_to("想要Quit Group", quit_group_path(@group), method: :post, class: "btn btn-default") %>
      <% else %>
        
        <%= link_to("Join123 Group", join_group_path(@group), method: :post, class: "btn btn-default") %>
      <% end %>
    
  • app/models/user.rb
has_many :group_relationships
has_many :participated_groups, :through => :group_relationships, :source => :group

  def is_member_of?(group)
    participated_groups.include?(group)
  end

  def join!(group)
    participated_groups << group
  end

  def quit!(group)
    participated_groups.delete(group)
  end
  • app/models/group_relationship.rb
belongs_to :group
belongs_to :user
  • app/models/group.rb
has_many :group_relationships
has_many :members, through: :group_relationships, source: :user
  • app/controllers/groups_controller.rb
    def join
@group = Group.find(params[:id])
    if !current_user.is_member_of?(@group)
      current_user.join!(@group)
      flash[:notice] = "加入本讨论版成功!"
    else
      flash[:warning!] = "你已经是本讨论版成员!"
    end
    redirect_to group_path(@group)
  end

    def quit
      @group = Group.find(params[:id])
      if current_user.is_member_of?(@group)
        current_user.quit!(@group)
        flash[:alert] = "已退出本讨论版!"
      else
        flash[:warning] = "你不是本讨论版成员,怎么退出 XD"
      end
      redirect_to group_path(@group)
    end
  • 修改位於第二行的 before_action ,加入 join 和 quit 也需要验证
    config/routes.rb
resources :groups do
    member do
      post :join
      post :quit
    end

让 User 在建立 group 后自动成为 group 的一员

  • app/controllers/groups_controller.rb
current_user.join!(@group)

使用者可以在“自己的后台”看过曾经发表的文章、以及创立的社团

rails g controller account/groups

config/routes.rb
  namespace :account do
    resources :groups
  end

在“下拉选单选项”中多加入一个My Groups:

  • app/views/common/_navbar.html.erb
  • <%= link_to("My Groups", account_groups_path) %>
    • 记得要加入: before_action :authenticate_user!,限制必须要得登录使用者,才能看。
      app/controllers/account/groups_controller.rb
    before_action :authenticate_user!
      def index
        @groups = current_user.participated_groups
      end
    

    制作管理者观看后台界面

    touch app/views/account/groups/index.html.erb

    我加入的讨论版

    <% @groups.each do |group| %> <% end %>
    # Title Description Post Count Last Update
    # <%= link_to(group.title, group_path(group)) %> <%= group.description %> <%= group.posts.count %> <%= group.updated_at %>

    你可能感兴趣的:(Rails 101)