iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 28
1

應觀眾要求,今天我們作一個管理後台,讓我們可以在網頁上管理關鍵字。

在開始之前,先大概說明一下今天要學習的範圍有哪些:

  • 網頁的呈現需要使用 HTML 和 CSS
  • 既然是後台,就要作登入功能

我們作的網站到目前為止沒有碰過任何的 HTML 和 CSS,突然要寫個管理後台也許會很吃力。不過還好是作後台,不需要多美觀。

使用產生器製作後台

幸好 Rails 有一個內建指令直接生成網頁,不一定要自己寫。

指令是 rails generate scaffold 資料模型名稱 和欄位們

rails g scaffold keyword_mapping channel_id keyword message --skip

後面的 --skip 是指定當發生衝突時應該略過。衝突的意思是指 rails 想新增一個檔案,剛好在目錄裡已經有個同名的檔案。

D:\只要有心,人人都可以作卡米狗\ironman>rails g scaffold keyword_mapping channel_id keyword message --skip
      invoke  active_record
        skip    db/migrate/20180115144538_create_keyword_mappings.rb
   identical    app/models/keyword_mapping.rb
      invoke    test_unit
   identical      test/models/keyword_mapping_test.rb
        skip      test/fixtures/keyword_mappings.yml
      invoke  resource_route
       route    resources :keyword_mappings
      invoke  scaffold_controller
      create    app/controllers/keyword_mappings_controller.rb
      invoke    erb
      create      app/views/keyword_mappings
      create      app/views/keyword_mappings/index.html.erb
      create      app/views/keyword_mappings/edit.html.erb
      create      app/views/keyword_mappings/show.html.erb
      create      app/views/keyword_mappings/new.html.erb
      create      app/views/keyword_mappings/_form.html.erb
      invoke    test_unit
      create      test/controllers/keyword_mappings_controller_test.rb
      invoke    helper
      create      app/helpers/keyword_mappings_helper.rb
      invoke      test_unit
      invoke    jbuilder
      create      app/views/keyword_mappings/index.json.jbuilder
      create      app/views/keyword_mappings/show.json.jbuilder
      create      app/views/keyword_mappings/_keyword_mapping.json.jbuilder
      invoke  test_unit
      create    test/system/keyword_mappings_test.rb
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/keyword_mappings.coffee
      invoke    scss
      create      app/assets/stylesheets/keyword_mappings.scss
      invoke  scss
      create    app/assets/stylesheets/scaffolds.scss

D:\只要有心,人人都可以作卡米狗\ironman>

以下說明到底生成了什麼東西。

生成 Routes

他會在 config/routes.rb 生成一個 resource:

resources :keyword_mappings

這是資源(resource),提供一個資源的存取所需要的網址和 Controller 的對應。

這行會生成 8 組網址與 7 個 Controller Action 的對應,可以使用 rails routes 觀察:

D:\只要有心,人人都可以作卡米狗\ironman>rails routes
                 Prefix Verb   URI Pattern                          Controller#Action
       keyword_mappings GET    /keyword_mappings(.:format)          keyword_mappings#index
                        POST   /keyword_mappings(.:format)          keyword_mappings#create
    new_keyword_mapping GET    /keyword_mappings/new(.:format)      keyword_mappings#new
   edit_keyword_mapping GET    /keyword_mappings/:id/edit(.:format) keyword_mappings#edit
        keyword_mapping GET    /keyword_mappings/:id(.:format)      keyword_mappings#show
                        PATCH  /keyword_mappings/:id(.:format)      keyword_mappings#update
                        PUT    /keyword_mappings/:id(.:format)      keyword_mappings#update
                        DELETE /keyword_mappings/:id(.:format)      keyword_mappings#destroy
             kamigo_eat GET    /kamigo/eat(.:format)                kamigo#eat
 kamigo_request_headers GET    /kamigo/request_headers(.:format)    kamigo#request_headers
    kamigo_request_body GET    /kamigo/request_body(.:format)       kamigo#request_body
kamigo_response_headers GET    /kamigo/response_headers(.:format)   kamigo#response_headers
   kamigo_response_body GET    /kamigo/response_body(.:format)      kamigo#show_response_body
    kamigo_sent_request GET    /kamigo/sent_request(.:format)       kamigo#sent_request
         kamigo_webhook POST   /kamigo/webhook(.:format)            kamigo#webhook

7 個 Action 分別為 index, create, new, edit, show, update, destroy,接下來說明各個 Action 的功能:

以下屬於 GET request,這些都是網頁:

  • index:列表頁
  • new:新增資料頁
  • show:檢視資料頁
  • edit:編輯資料頁

以下非 GET request,都是請求資料變更:

  • create:請求新增資料
  • update:請求更新資料
  • destroy:請求刪除資料

生成 Controller

生成了一個 Controller 在:app/controllers/keyword_mappings_controller.rb。7 個對應的 Action 都寫好了,這裡就不多介紹。

生成 View

生成了一整個資料夾的 View,其中最重要的 4 個:

app/views/keyword_mappings/index.html.erb
app/views/keyword_mappings/edit.html.erb
app/views/keyword_mappings/show.html.erb
app/views/keyword_mappings/new.html.erb

這就是那些 GET request 會用到的網頁檔,也都寫好了。

實測

既然都寫好了就來試用看看,先執行網頁伺服器:

rails s

然後開啟網頁 http://localhost:3000/keyword_mappings

index 列表頁

new 新增資料頁

隨便亂填:

show 檢視資料頁

所以其實不考慮美觀性的話,其實後台只要一個指令就完成了。

建立登入功能

使用知名套件 devise 來作。

我相信現在的你如果沒有英文閱讀障礙,應該已經能看懂這個使用說明

總而言之先在 Gemfile 加這行:

gem 'devise'

然後在小黑框打 bundle install 安裝套件。

裝好之後使用 devise 提供的產生器指令進行初始化: rails generate devise:install

D:\只要有心,人人都可以作卡米狗\ironman>rails generate devise:install
      create  config/initializers/devise.rb
      create  config/locales/devise.en.yml
===============================================================================

Some setup you must do manually if you haven't yet:

  1. Ensure you have defined default url options in your environments files. Here
     is an example of default_url_options appropriate for a development environment
     in config/environments/development.rb:

       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

     In production, :host should be set to the actual host of your application.

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root to: "home#index"

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

  4. You can copy Devise views (for customization) to your app by running:

       rails g devise:views

===============================================================================

D:\只要有心,人人都可以作卡米狗\ironman>

他說有幾個步驟產生器沒搞頭,必須手動進行。我們先不管他,等到真正出問題再回頭來解決。

使用產生器產生用戶資料模型:

rails generate devise user
D:\只要有心,人人都可以作卡米狗\ironman>rails generate devise user
      invoke  active_record
      create    db/migrate/20180115152537_devise_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml
      insert    app/models/user.rb
       route  devise_for :users

D:\只要有心,人人都可以作卡米狗\ironman>

跟剛剛的 scaffold 差不多,該生的都生好了。

註冊頁:http://localhost:3000/users/sign_up
登入頁:http://localhost:3000/users/sign_in

關閉註冊功能

我們要將註冊功能關閉,如果大家都能註冊,那還要後台幹嘛?

app/models/user.rb

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
end

刪除 :registerable,

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable,
         :recoverable, :rememberable, :trackable, :validatable
end

登入後才能管理關鍵字

我們希望只有登入後的人才能進入管理關鍵字的頁面。

app/controllers/keyword_mappings_controller.rb 加入:

before_action :authenticate_user!

看起來像這樣:

class KeywordMappingsController < ApplicationController
  before_action :authenticate_user!
  before_action :set_keyword_mapping, only: [:show, :edit, :update, :destroy]

  ...下略

這時候開啟網址:http://localhost:3000/keyword_mappings,就會因為尚未登入,而被引導至登入頁。

發布流程

  • 上傳程式碼
  • Heroku 上的資料庫遷移

關閉了註冊功能後要怎麼新增自己的帳號?

使用 rails console 連上去新增帳號:

heroku run rails console

連上後會是 rails console 的樣子:

D:\只要有心,人人都可以作卡米狗\ironman>heroku run rails console
Running rails console on people-all-love-kamigo... up, run.2165 (Free)
Loading production environment (Rails 5.1.4)
irb(main):001:0>

寫一行程式碼新增資料:

User.create(email:'kamigo.service@gmail.com', password:'kamigo')

會有一些 SQL 的訊息:

irb(main):001:0> User.create(email:'kamigo.service@gmail.com', password:'kamigo')
D, [2018-01-15T15:42:28.307402 #4] DEBUG -- :    (6.0ms)  BEGIN
D, [2018-01-15T15:42:28.313291 #4] DEBUG -- :   User Exists (2.1ms)  SELECT  1 AS one FROM "users" WHERE "users"."email" = $1 LIMIT $2  [["email", "kamigo.service@gmail.com"], ["LIMIT", 1]]
D, [2018-01-15T15:42:28.317361 #4] DEBUG -- :   SQL (1.9ms)  INSERT INTO "users" ("email", "encrypted_password", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["email", "kamigo.service@gmail.com"], ["encrypted_password", "$2a$11$EyR.yuDYI3J2s9/Q8Etk5evQzsz2bGAPdvdcr.xmFQbzYbBPQk/kK"], ["created_at", "2018-01-15 15:42:28.313883"], ["updated_at", "2018-01-15 15:42:28.313883"]]
D, [2018-01-15T15:42:28.320139 #4] DEBUG -- :    (2.0ms)  COMMIT
=> #<User id: 1, email: "kamigo.service@gmail.com", created_at: "2018-01-15 15:42:28", updated_at: "2018-01-15 15:42:28">
irb(main):002:0>

看到倒數第二行:

=> #<User id: 1, email: "kamigo.service@gmail.com", created_at: "2018-01-15 15:42:28", updated_at: "2018-01-15 15:42:28">

就表示建立好帳號了。

線上實測

https://people-all-love-kamigo.herokuapp.com/keyword_mappings

大家可以用我的帳號登入看看。

帳號:kamigo.service@gmail.com
密碼:kamigo

本日重點

  • 學會使用 scaffold
  • 學會作登入系統

你們可以透過閱讀 scaffold 產生出來的程式碼來學習 HTML 和 Controller Action 的寫法。這跟學英文一樣,看到不懂的單字就 Google,這單字量還比英文少超多,大概 100~200 個字而已。

明天講怎麼發公告。


上一篇
第二十七天:卡米狗見人說人話,見鬼說鬼話
下一篇
第二十九天:卡米狗發公告
系列文
只要有心,人人都可以做卡米狗32
0
jerryw47
iT邦新手 5 級 ‧ 2018-01-16 12:08:09

請問一下,這個是照你上面打嗎?
https://ithelp.ithome.com.tw/upload/images/20180116/20107956aopajKHqUm.png
因為我想要新增自己的,結果出現以下這樣
https://ithelp.ithome.com.tw/upload/images/20180116/20107956ZIuiKQOoNC.png

你還沒有上傳程式碼吧

nienst iT邦新手 5 級‧ 2018-01-27 16:48:43 檢舉

我剛剛也遇到一樣的問題
後來發現我程式碼放錯地方
在 app/controllers/keyword_mappings_controller.rb 加入

before_action :authenticate_user!

我卻不小心加在
app/models/user.rb

1
luke90329
iT邦新手 5 級 ‧ 2018-01-16 18:22:11

卡米大我照上面弄到執行時 出現了這個錯誤@@
https://ithelp.ithome.com.tw/upload/images/20180116/20107961P8PpQBhgk9.png

看更多先前的回應...收起先前的回應...

最後是把app/views/layouts/application.html.erb 的"檔名"
改成 app/views/layouts/default.html.erb
才解決 不過應該也是治標不治本
詳細的方法在:https://stackoverflow.com/questions/12520456/execjsruntimeerror-on-windows-trying-to-follow-rubytutorial

不過destroy沒甚麼反應就是了....

https://ithelp.ithome.com.tw/upload/images/20180116/20107961r82tm4Hxdq.png
然後又出現了這個問題 可是把資料庫遷移過一次還是一樣

我看了那篇文章,我覺得裝 node.js 可能比較好

結果我先把app\assets\javascripts\application.js裡面最下面的

//= require_tree .

刪掉就好了

不過為了保險起見還是裝個node.js好了

不過資料庫的問題依然存在 查了Devise的status是down
不過在heroku上是正常 看來又是windows的問題了

XD

我的錯誤畫面也一樣QQ

樓上裝 node.js 有用嗎

卡米大雖然這個在heroku上面沒問題 不過我還是想解決xD
https://ithelp.ithome.com.tw/upload/images/20180118/20107961tEeQbH25nX.png
後來找了一下錯誤訊息是這個 應該就是因為他沒有成功遷移才造成keyword_mapping整個掛掉(要先登入)

可以看一下你的 db/migrate 資料夾內的檔案列表嗎?

https://ithelp.ithome.com.tw/upload/images/20180119/20107961Qq80cwb7Ye.png

試試

rails db:drop
rails db:create
rails db:migrate

還是不行@@ 這兩個一直都是down
bundle exec rake db:migrate也試過了

0.0

好吧 看來可能是建置的時候有哪邊做錯了
不過還有一個問題 就是我想在天氣圖片前發送一個純文字訊息

  #查天氣指令
  def get_weather(received_text)
    return nil unless received_text.include? '天氣'
    upload_to_imgur(get_weather_from_cwb)
    push_messages = get_time_from_cwb
    push_to_line(channel_id, push_messages)
  end

  #取得最新雷達回波圖
  def get_weather_from_cwb
    uri = URI('http://www.cwb.gov.tw/V7/js/HDRadar_1000_n_val.js')
    response = Net::HTTP.get(uri)
    start_index = response.index('","') + 3
    end_index = response.index('"),') - 1
    "http://www.cwb.gov.tw" + response[start_index..end_index]
  end

  #取得最新雷達回波圖時間
  def get_time_from_cwb
    uri = URI('http://www.cwb.gov.tw/V7/js/HDRadar_1000_n_val.js')
    response = Net::HTTP.get(uri)
    time_start_index = response.index('("') +2
    time_end_index = response.index('","') -1
    "雷達回波圖:" + response[time_start_index..time_end_index]
  end

可是怎麼試都同時只會有訊息或圖片出去而已 很疑惑的是一個是reply一個是push應該不會衝突阿

安裝這個:http://sqlitebrowser.org/

然後讀取 db/development.sqlite3 這個檔案

截這個畫面貼上來:
https://ithelp.ithome.com.tw/upload/images/20180119/201073096HvAq0GhDY.jpg

回應訊息其實可以傳陣列喔,只是要改原本的 code 我就懶了 XD

# 設定回覆訊息
    image_message = {
      type: "image",
      originalContentUrl: reply_image,
      previewImageUrl: reply_image
    }
    text_message = {
      type: 'text',
      text: reply_text
    }
line.reply_message(reply_token, [text_message, image_message])

像這樣是可以的。

https://ithelp.ithome.com.tw/upload/images/20180119/20107961WWHE1Uo8VB.png

額 漏了這個沒回應到
從這張圖片來看,你的資料庫裡面已經存在 users 表格,但是你說你的 migration 還沒做完,真的是怪怪的。

可以看一下 rails db:migrate:status 會出現什麼嗎?

https://ithelp.ithome.com.tw/upload/images/20180126/20107961asDtDLkuOG.png

哇 多一個 no file 應該就是這裡出了問題。

那有甚麼指令可以把它刪除的嗎@@

我好像知道錯誤在哪裡了 因為我之前先照著教學做了一次可是出現了第一個錯誤 然後我就把文件都先刪掉重新做一次 所以後來新的遷移檔才會出問題 可是要怎麼把已經在資料庫內的資料刪掉呢 用db browser就可以了嗎

rails db:drop
rails db:create
rails db:migrate
0
lee98064
iT邦新手 5 級 ‧ 2018-01-16 19:21:06

想請問大大,剛剛做到這個步驟時(然後開啟網頁 http://localhost:3000/keyword_mappings)
卻出現以下錯誤,想請問一下要怎麼解決
完整錯誤訊息:
https://drive.google.com/open?id=1pATrDNWjpxCupp3RL02fW0_LEXhj45ksmrW-KTjk4ZU

https://ithelp.ithome.com.tw/upload/images/20180116/201083253aJhXhL51p.png

看更多先前的回應...收起先前的回應...

他說:你要先執行 rails db:migrate

執行了還是出現耶???

試試看 rails db:migrate:status 會顯示什麼?

謝謝卡米大~/images/emoticon/emoticon37.gif
我後來直接上傳heroku就正常了XDDD
然後想再問一個問題就是使用者帳號可以建立多組嗎?

可以

0
ray19990613
iT邦新手 5 級 ‧ 2018-01-17 01:07:00

卡卡米你好~
我也失敗了,
我的可以正常顯示註冊、登入畫面,
但是按下註冊、登入按鈕後,
會顯示下列錯誤訊息 QAQ

https://ithelp.ithome.com.tw/upload/images/20180117/20108327zjyMOkP6hn.png

看更多先前的回應...收起先前的回應...

嗯,我剛剛也有看到這個錯誤訊息,但是在 heroku 上是好的,所以應該是 windows 的問題,我還沒找到怎麼解。

關於 Rails - Windows 上會遇到的 LoadError (cannot load such file -- bcrypt_ext)

什麼時候會遇到這個問題?

當你使用任何需要加密功能的套件時,比方說 Devise。

成因

安裝了不能在 windows 下正常執行的 bcrypt 套件。

解法

先解除安裝所有 bcrypt

gem uninstall bcrypt-ruby
gem uninstall bcrypt

再安裝正確版本

gem install bcrypt --platform=ruby

你的 Gemfile 應該加入這行

gem 'bcrypt', '~> 3.1.11'

參考連結

https://github.com/codahale/bcrypt-ruby/issues/142#issuecomment-291345799

我也是卡在這邊.... 可是加入了gem 'bcrypt', '~> 3.1.11' 之後網頁反而開不起來

https://ithelp.ithome.com.tw/upload/images/20180121/201062506QWUxdhOHq.png

卡卡米

gem uninstall bcrypt-ruby
gem uninstall bcrypt

這兩個跑過沒問題

gem install bcrypt --platform=ruby

這個就會出現紅字失敗

失敗的訊息是什麼呢?

你的 Gemfile 裡面寫了什麼?

我後來是這樣成功的

先在 Gemfile 加入這一行
gem 'bcrypt', platforms: :ruby

然後再到小黑框依序輸入這些指令
gem uninstall bcrypt-ruby
gem uninstall bcrypt
gem install bcrypt --platform=ruby

這樣應該就可以了,
試試看吧 :)

這是在加入 before_action :authenticate_user! 前可以行得通,
加入後就又會一直出現跟樓上一樣的錯誤訊息,
https://ithelp.ithome.com.tw/upload/images/20180124/20108327RlOpH6rkVR.jpg
不過在 heroku 是可以正常執行的 :)

/images/emoticon/emoticon06.gif

0
nienst
iT邦新手 5 級 ‧ 2018-02-08 19:51:20

我想如法炮製,做一個 頻道 管理後台.... 卻做不出來 @@"
應該是下這樣的一行指令,一步接一步 就能成功了呀
(有一些錯誤有點眼熟,還沒查出來...)
rails g scaffold channel channel_id --skip

C:\Users\Nien\Desktop\粘粘的卡米狗\ironman>rails g scaffold channel channel_id -
-skip
invoke active_record
C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/thor-0.20.0/lib/thor/actions.rb:117:in g sub!': incompatible character encodings: UTF-8 and CP950 (Encoding::Compatibilit yError) from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/thor-0.20.0/lib/thor/actions .rb:117:inrelative_to_original_destination_root'
from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/railties-5.1.4/lib/rails/gen
erators/actions/create_migration.rb:29:in relative_existing_migration' from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/railties-5.1.4/lib/rails/gen erators/actions/create_migration.rb:45:inon_conflict_behavior'
from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/thor-0.20.0/lib/thor/actions
/empty_directory.rb:115:in invoke_with_conflict_check' from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/thor-0.20.0/lib/thor/actions /create_file.rb:60:ininvoke!'
from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/thor-0.20.0/lib/thor/actions
.rb:94:in action' from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/railties-5.1.4/lib/rails/gen erators/migration.rb:34:increate_migration'
from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/railties-5.1.4/lib/rails/gen
erators/migration.rb:63:in migration_template' from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/activerecord-5.1.4/lib/rails /generators/active_record/model/model_generator.rb:20:increate_migration_file'
(... 下略 ...)

看更多先前的回應...收起先前的回應...

雖然這樣有點怪怪der 但你試試看把黏黏的卡米狗 資料夾名稱改成英文之後再試試看

nienst iT邦新手 5 級‧ 2018-02-09 01:02:14 檢舉

恩恩 我明天測試看看
感恩卡米 讚嘆卡米

nienst iT邦新手 5 級‧ 2018-02-09 18:53:19 檢舉

感恩卡米 讚嘆卡米

竟然真的就這樣成功了~~~ 感動到忍不住想哭~~ ㄎㄎ
因為我嘗試了很多的方法... 都看不出哪邊編碼有問題....不斷的在前幾篇的編碼來回查看
昨天看到您的回覆其實本來也半信半疑(現在想想我真的很不應該有這樣的想法)
因為我之前也是用中文,也都可以

總之,非常感謝卡米大師~~~ 讓卡關多天的我,終於成功了~~

我也覺得用中文應該要可以 QQ

nienst iT邦新手 5 級‧ 2018-02-10 10:55:51 檢舉

恩 也許我有動到什麼設定 導致後來不可以
因此我也沒想到 會是資料夾 中文 編碼問題
我英文不是很好 用GOOGLE翻譯 只知道是編碼問題
呵呵 還是卡米大師厲害

感恩卡米 讚嘆卡米

我要留言

立即登入留言