欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

如何使用 Rails 和七牛云存儲(chǔ),在 15 分鐘內(nèi)打造一個(gè)圖片分享社交應(yīng)用原型

 更新時(shí)間:2016年03月05日 12:08:23   投稿:mdxy-dxy  
今天,就讓我們一起來看看如何使用 Rails 和七牛云存儲(chǔ),在 15 分鐘內(nèi)打造一個(gè)圖片分享社交應(yīng)用原型

十年前,Web 應(yīng)用框架 Rails 創(chuàng)始人 David Heinemeier Hansson 曾錄制視頻,向我們演示如何使用 Ruby on Rails 在 15 分鐘內(nèi)創(chuàng)作一個(gè) blog 引擎。這個(gè)視頻通過 Rails 優(yōu)秀的 MVC 、習(xí)慣優(yōu)于配置(Convention over Configuration)等設(shè)計(jì),以及強(qiáng)大的代碼生成、scaffold 等功能,成功展示了 Ruby on Rails 編寫 Web 應(yīng)用核心功能的高效簡(jiǎn)潔。Ruby on Rails 這門技術(shù)也在 Web 2.0 時(shí)代大放異彩,成為了 Web 應(yīng)用開發(fā)最佳的技術(shù)方案選擇之一。

經(jīng)過十年的發(fā)展,軟件行業(yè)早已邁入云計(jì)算時(shí)代。為了應(yīng)對(duì)大規(guī)模的訪問量,同時(shí)控制研發(fā)和運(yùn)營(yíng)成本,作為云計(jì)算基石的云存儲(chǔ),已經(jīng)成為了 Web 開發(fā)必不可少的基礎(chǔ)設(shè)施。今天,就讓我們一起來看看如何使用 Rails 和七牛云存儲(chǔ),在 15 分鐘內(nèi)打造一個(gè)圖片分享社交應(yīng)用原型。

七牛云存儲(chǔ) 是一個(gè)公有云服務(wù),提供海量對(duì)象存儲(chǔ)功能,以及云端文件處理和分發(fā)服務(wù)。開始之前,我們需要?jiǎng)?chuàng)建一個(gè)七牛云存儲(chǔ) 試用帳戶,并且了解一些基礎(chǔ)知識(shí):

七牛云存儲(chǔ)是一個(gè) Key-Value 形式的對(duì)象存儲(chǔ)系統(tǒng),一個(gè) key 對(duì)應(yīng)一個(gè)資源(文件)。
資源必須存儲(chǔ)在某個(gè)空間(Bucket)中,不可單獨(dú)存在。一個(gè)帳戶可以創(chuàng)建多個(gè)空間。

創(chuàng)建基本 Rails 項(xiàng)目

你應(yīng)該可以使用 Ruby 1.9 以上,Rails 3.0 以上的任意版本,本例中我們使用的是 Ruby 2.2.3 和 Rails 4.2.5。

安裝好 Ruby 和 Rails 之后,使用 rails 命令創(chuàng)建應(yīng)用程序 konata 的目錄結(jié)構(gòu)和基本文件:

復(fù)制代碼 代碼如下:

rails new konata

稍候這條命令執(zhí)行完成,我們立即得到了一個(gè)可以運(yùn)行的空白 Rails 應(yīng)用程序,執(zhí)行以下命令,并在瀏覽器中訪問 http://localhost:3000 查看運(yùn)行效果:

復(fù)制代碼 代碼如下:

cd konata
rails server

使用 Rails Scaffold 實(shí)現(xiàn) CRUD

我們將使用 Rails 的 scaffold 功能,生成用于處理圖片發(fā)表的 model、controller、view,以及 database migration 等源代碼文件。

復(fù)制代碼 代碼如下:

rails generate scaffold post title filename qiniu_hash
rake db:migrate

訪問 http://localhost:3000/posts 可以看到,我們已經(jīng)獲得了 post 的完整 CRUD 功能,只是暫時(shí)還不能上傳圖片。

使用七牛 API 實(shí)現(xiàn)圖片上傳

修改 Gemfile,在其中加入對(duì)七牛 Ruby SDK 的引用:

復(fù)制代碼 代碼如下:

gem 'qiniu'

執(zhí)行以下命令安裝七牛 Ruby SDK。這里原本應(yīng)該執(zhí)行 bundle 進(jìn)行安裝,但由于七牛 Ruby SDK 依賴的 mime-types 版本設(shè)定比較保守,需要使用 bundle update 命令降級(jí) mime-types,解決依賴沖突。

復(fù)制代碼 代碼如下:

bundle update mime-types

編輯 config/secrets.yml,在其中加入七牛云存儲(chǔ)帳戶的密鑰:

復(fù)制代碼 代碼如下:

development:
secret_key_base: <YOUR_SECRET_KEY_BASE>
qiniu_access_key: <YOUR_QINIU_ACCESS_KEY>
qiniu_secret_key: <YOUR_QINIU_SECRET_KEY>

創(chuàng)建 config/initializers/qiniu.rb,使用剛才加入的密鑰與七牛云存儲(chǔ)服務(wù)器建立連接。內(nèi)容如下:

require 'qiniu'

Qiniu.establish_connection!(
 access_key: Rails.application.secrets.qiniu_access_key,
 secret_key: Rails.application.secrets.qiniu_secret_key
)

注意:

AccessKey 和 SecretKey 必須絕對(duì)保密,不可出現(xiàn)在用戶可以查看的 Web 前端源代碼里,或是編譯進(jìn)客戶端二進(jìn)制代碼中。

七牛 API 提供了多種上傳方式 以滿足不同的業(yè)務(wù)場(chǎng)景需求。這里我們選擇使用最有代表性,也最簡(jiǎn)單的 HTML 表單上傳+HTTP 303 重定向返回的方式實(shí)現(xiàn)客戶端文件直接上傳七牛云存儲(chǔ)。這種方法的好處是客戶端文件無需通過業(yè)務(wù)服務(wù)器(app server)中轉(zhuǎn),既可以利用七牛強(qiáng)大的 CDN 優(yōu)化上傳速度及提高可靠性,也可以節(jié)省業(yè)務(wù)服務(wù)器帶寬。

編輯 app/views/posts/_form.html.erb,根據(jù)七牛云存儲(chǔ) SDK 構(gòu)造上傳表單。注意其中的上傳憑證字段,我們將在 PostsController 里創(chuàng)建它:

<%= form_tag 'http://upload.qiniu.com', multipart: true do %>
 <%= hidden_field_tag :token, @qiniu_upload_token %>

 <div class="field">
 <%= label_tag :title %><br>
 <%= text_field_tag 'x:title' %>
 </div>
 <div class="field">
 <%= label_tag :image %><br>
 <%= file_field_tag :file %>
 </div>
 <div class="actions">
 <%= submit_tag 'Create' %>
 </div>
<% end %>

編輯 app/controllers/posts_controller.rb,添加代碼生成上傳憑證,以及根據(jù)七牛云存儲(chǔ)自定義響應(yīng)內(nèi)容創(chuàng)建 post 實(shí)例:

def new
 @qiniu_upload_token = generate_qiniu_upload_token
 @post = Post.new
 end

 def create
 upload_ret = JSON.parse(Base64.urlsafe_decode64(params[:upload_ret]))
 @post = Post.new(
 title: upload_ret['title'],
 filename: upload_ret['fname'],
 qiniu_hash: upload_ret['hash']
 )
 # ...
 end

 private

 def generate_qiniu_upload_token
 put_policy = Qiniu::Auth::PutPolicy.new('konata')
 put_policy.return_body = {
 fname: '$(fname)',
 hash: '$(etag)',
 title: '$(x:title)'
 }.to_json
 put_policy.return_url = create_posts_url
 Qiniu::Auth.generate_uptoken(put_policy)
 end

編輯 config/routes.rb,將 create action 定義為使用 get 方法亦可訪問:

 resources :posts do
 collection do
 get 'create', as: :create
 end
 end

重新啟動(dòng) rails server,訪問 http://localhost:3000/posts/new,現(xiàn)在我們已經(jīng)可以在發(fā)表新 post 的時(shí)候上傳圖片至七牛云存儲(chǔ)。

提示:

文件將會(huì)上傳到名為 konata 的公開空間(bucket)。
我們沒有在代碼中指定 key,七牛云存儲(chǔ)默認(rèn)會(huì)使用根據(jù)文件內(nèi)容計(jì)算的 hash (etag) 值做為 key。這種做法可以非常簡(jiǎn)單地避免內(nèi)容相同的文件存儲(chǔ)多份浪費(fèi)空間。
由于上傳表單將會(huì)直接提交到七牛云存儲(chǔ)服務(wù)器,我們的應(yīng)用程序后端無法獲得 title 等業(yè)務(wù)對(duì)象字段,我們使用七牛云存儲(chǔ) API 的 自定義變量自定義響應(yīng)內(nèi)容 功能,通過七牛云存儲(chǔ)上傳 API 中轉(zhuǎn)獲得這些字段。
展示用戶上傳的圖片

修改 app/helpers/application_helper.rb,添加 qiniu_image_url 方便生成圖片 URL。為了保持簡(jiǎn)單我們直接硬編碼了空間的域名:

def qiniu_image_url(post, format = :raw)
 url = "http://7xokus.com2.z0.glb.qiniucdn.com/#{post.qiniu_hash}"

 case format
 when :square
 url << '?imageView2/1/w/300/h/300/q/90'
 when :preview
 url << '?imageView2/2/w/1000/h/1000/q/90'
 when :raw
 url << "?attname=#{post.filename}"
 else
 url
 end
 end

修改 app/views/posts/index.html.erb 和 app/views/posts/show.html.erb,調(diào)用剛才創(chuàng)建的 URL helper 展示圖片:

<tr>
 <td><%= post.title %></td>
 <td><%= link_to image_tag(qiniu_image_url(post, :square), size: '300'), post %></td>
 <td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
 </tr>
<p>
 <%= link_to image_tag(qiniu_image_url(@post, :preview)), qiniu_image_url(@post), class: 'image' %>
</p>

<%= link_to 'Back', posts_path %>

修改 config/routes.rb,將網(wǎng)站根目錄設(shè)置為 posts 列表頁面:


root 'posts#index'
訪問 http://localhost:3000,現(xiàn)在我們可以看到剛才上傳的圖片。

提示:

每個(gè)空間(bucket)內(nèi)的資源都可以通過該空間的默認(rèn)或自定義域名,加上文件 key 構(gòu)造的 HTTP URL 進(jìn)行訪問。
可以在 URL 后增加特定查詢參數(shù),調(diào)用七牛云存儲(chǔ)強(qiáng)大的 數(shù)據(jù)處理(Fop) API,實(shí)時(shí)生成自定義格式的縮略圖。
可以通過查詢參數(shù) attname 指定 URL 下載時(shí)使用的文件名。
簡(jiǎn)單的 UI 美化

修改 app/views/posts/index.html.erb,將原有的 table 布局改為 flexbox 布局:

<div class="posts">
 <% @posts.each do |post| %>
 <p>
 <%= link_to image_tag(qiniu_image_url(post, :square), size: '300'), post, class: 'image' %>
 <br>
 <%= post.title %>
 <br>
 <%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %>
 </p>
 <% end %>
</div>

修改 app/assets/stylesheets/application.css,加入對(duì)應(yīng)的 CSS:

body {
 padding: 20px;
}

a.image:hover {
 background-color: transparent;
}

div.posts {
 display: flex;
 flex-flow: row wrap;
 justify-content: space-between;
}

訪問 http://localhost:3000,圖片列表看起來像一個(gè)正常的相冊(cè)了。

添加用戶賬戶功能

我們的應(yīng)用程序還有兩個(gè)明顯的問題:沒有記錄圖片是由誰分享的;任何人都可以刪除 post。這對(duì)于一個(gè)社交應(yīng)用來說顯然是不能接受的問題。這對(duì)于一個(gè)社交應(yīng)用來說顯然是不可接受的,所以接下來我們將使用 Rails 社區(qū)流行的 Devise 組件直接獲得用戶注冊(cè)、登錄、驗(yàn)證子系統(tǒng),實(shí)現(xiàn)圖片發(fā)表者信息記錄等功能。

修改 Gemfile,加入對(duì) Devise 的依賴:

復(fù)制代碼 代碼如下:

gem 'devise'

執(zhí)行以下命令安裝 Devise,生成 User model,以及我們所需的 data migration:

復(fù)制代碼 代碼如下:

bundle
rails generate devise:install
rails generate devise user
rails generate migration add_author_to_posts creator:belongs_to
rake db:migrate

修改 app/controllers/posts_controller.rb,對(duì)查看以外的操作要求登錄,并在發(fā)表 post 時(shí)記錄發(fā)表者身份:

 before_action :authenticate_user!, except: [:index, :show]

 def create
 # ...
 @post = Post.new(
 title: upload_ret['title'],
 filename: upload_ret['fname'],
 qiniu_hash: upload_ret['hash'],
 creator: current_user
 )
 # ...
 end

修改 app/models/post.rb,添加與 User model 的從屬關(guān)聯(lián):

復(fù)制代碼 代碼如下:

belongs_to :creator, class_name: 'User'

修改 app/views/layouts/application.html.erb,添加登錄狀態(tài)信息和注銷鏈接:

 <header>
 <% if user_signed_in? %>
 <p>
 Hello <%= current_user.email %>
 <%= link_to 'Logout', destroy_user_session_path, method: :delete %>
 </p>
 <% end %>
 </header>

修改 app/views/posts/index.html.erb,限制僅 post 發(fā)表者可以刪除該 post:

<% if user_signed_in? and post.creator == current_user %>
 <br>
 <%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %>
 <% end %>

重啟 rails server 后,訪問 http://localhost:3000,現(xiàn)在用戶需要注冊(cè)登錄才能發(fā)表圖片了。

實(shí)現(xiàn)點(diǎn)贊功能

最后,做為一個(gè)社交應(yīng)用,沒有點(diǎn)贊功能怎么能讓點(diǎn)贊狂魔們滿足呢?!我們將添加一個(gè) like scaffold 用來處理點(diǎn)贊和存儲(chǔ)點(diǎn)贊信息。

執(zhí)行以下命令生成 scaffold,Like model 將做為一個(gè) join model 同時(shí)從屬于 Post 和 User:

復(fù)制代碼 代碼如下:

rails generate scaffold like post:belongs_to user:belongs_to
rake db:migrate

修改 app/models/post.rb,建立 Post 與 Like model 的“擁有/嵌套”關(guān)系:

復(fù)制代碼 代碼如下:

has_many :likes

修改 app/models/like.rb,限制一個(gè)點(diǎn)贊狂魔對(duì)一個(gè) post 只能點(diǎn)一次贊:

復(fù)制代碼 代碼如下:

validates_uniqueness_of :user, scope: :post

修改 config/routes.rb,將 likes 設(shè)置為 posts 的嵌套資源:

復(fù)制代碼 代碼如下:

resources :posts do
# ...
resources :likes
end

修改 app/views/posts/index.html.erb,添加點(diǎn)贊信息顯示以及 AJAX 點(diǎn)贊鏈接:

<%= post.title %>
 <br>
 <%= content_tag(:span, "#{post.likes.count} likes", id: "post_#{post.id}_likes") %>

 <% if user_signed_in? %>
 <br>
 <%= link_to 'Like', post_likes_path(post), method: :post, remote: true %>

 <% if post.creator == current_user %>
 <%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %>
 <% end %>
 <% end %>

修改 app/controllers/likes_controller.rb,真正將 likes 資源實(shí)現(xiàn)為 posts 的嵌套資源,并在點(diǎn)贊時(shí)記錄點(diǎn)贊狂魔的身份:

before_action :set_post

 def create
 @like = @post.likes.new(user: current_user)

 respond_to do |format|
 if @like.save
 format.js { }
 else
 format.js { }
 end
 end
 end

 private

 def set_post
 @post = Post.find(params[:post_id])
 end

創(chuàng)建 app/views/likes/create.js.erb,使用 Server-generated JavaScript 更新點(diǎn)贊信息:

復(fù)制代碼 代碼如下:

$("#<%= "post_#{@post.id}_likes" %>").text("<%= "#{@post.likes.count} likes" %>")

重啟 rails server 后,訪問 http://localhost:3000,讓我們愉快地點(diǎn)贊吧~

小結(jié)

雖然這只是一個(gè)簡(jiǎn)單的原型,但是因?yàn)槭褂昧似吲T拼鎯?chǔ)作為圖片存儲(chǔ)后端,我們的社交應(yīng)用產(chǎn)品在一開始的原型階段就擁有了能為大規(guī)模用戶提供高速、可靠服務(wù)的潛能。

簡(jiǎn)單回顧一下我們剛才學(xué)習(xí)到的內(nèi)容吧。使用 Rails 的代碼生成功能, 基于 CRUD 結(jié)構(gòu)的 scaffold 實(shí)現(xiàn)業(yè)務(wù)對(duì)象維護(hù),以及業(yè)務(wù)操作非常高效;使用七牛云存儲(chǔ)則可以輕松處理業(yè)務(wù)系統(tǒng)中的文件存儲(chǔ),獲得圖片視頻等多媒體文件的云端處理能力,減少,甚至避免了部分研發(fā)和運(yùn)維工作。希望這個(gè)視頻可以幫助大家認(rèn)識(shí)這兩個(gè)優(yōu)秀的開發(fā)工具,直觀感受到它們的高效強(qiáng)大和簡(jiǎn)單易用。

參考資料

Ruby on Rails Guides
七牛開發(fā)者中心

示例代碼

https://github.com/rainux/konata-sample

比起直接試用示例代碼,你應(yīng)該按照教程自己編寫這些代碼,親自編寫代碼有助于加深理解和記憶。

相關(guān)文章

最新評(píng)論