Kurt Hsu's blog

The Rails developer in taiwan.


  • 首頁

  • 標籤

  • 分類

  • 歸檔

[Disqus]簡易留言板

發表於 2018-04-21 更新於 2019-08-21 分類於 Disqus

首先我們先到Disqus官方網站點選GET STARTED > I want to install Disqus on my site辦好一個網站在這個平台裡面,當詢問到What platform is your site on?時請選擇最下面的Universal Code,這時候就會看到他們提供了直接可以使用的程式碼。

P.S.這個平台容易讓人誤會的是他也是個社群平台,但我們只要他簡單的留言板功能而已

基本上只要貼上他的第一個提供的code到自己的view就行了!他連該利用這個網站的shortname去抓哪一隻js都幫忙列出了。

show.html.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div id="disqus_thread"></div>
<script>

/**
* RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS.
* LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#configuration-variables*/
/*
var disqus_config = function () {
this.page.url = PAGE_URL; // Replace PAGE_URL with your page's canonical URL variable
this.page.identifier = PAGE_IDENTIFIER; // Replace PAGE_IDENTIFIER with your page's unique identifier variable
};
*/
(function() { // DON'T EDIT BELOW THIS LINE
var d = document, s = d.createElement('script');
s.src = 'https://your-shortname.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>

[Rails]Devise login with google

發表於 2018-04-19 更新於 2019-08-21 分類於 Rails , Gem

參考文件
OmniAuth Google OAuth2
Login With Google Account Using Devise and Omniauth
打開官方文件參考從Devise開始的部分

##安裝及申請

安裝gem

Gemfile
1
gem 'omniauth-google-oauth2'

$ bundle install

1.到google console https://console.developers.google.com頁面
2.頁面最上面創立一個專案
3.啟用兩個API服務Contacts API以及Google+ API
4.左邊的選單選擇憑證申請OAuth 2.0 用戶端 ID
5.可能需要等十分鍾

##Devise的方式實作

這邊假設已經安裝好Devise並且已經用Devise創造出users這個model

修改config/initializers/devise.rb

config/initializers/devise.rb
1
config.omniauth :google_oauth2, 'GOOGLE_CLIENT_ID', 'GOOGLE_CLIENT_SECRET', {}

GOOGLE_CLIENT_ID填入剛剛申請的用戶ID
GOOGLE_CLIENT_SECRET填入剛剛申請的用戶密碼

這時候登入頁面最下面應該已經多一個Sign in with GoogleOauth2的連結,且登入成功後會預設去users/omniauth_callbacks這個path!

修改routes.rb加上如果google登入成功後會呼叫的path

routes.rb
1
devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }

再來更新model新增一行

/app/models/user.rb
1
devise :omniauthable, omniauth_providers: [:google_oauth2]

再來不要忘記controller
你可以放在controller/application.rb或自行創立對應路徑
rails g controller users/omniauth_callbacks可以創造對應的路徑檔案

omniauth_callbacks_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
# You need to implement the method below in your model (e.g. app/models/user.rb)
@user = User.from_omniauth(request.env['omniauth.auth'])

if @user.persisted?
flash[:notice] = I18n.t 'devise.omniauth_callbacks.success', kind: 'Google'
sign_in_and_redirect @user, event: :authentication
else
session['devise.google_data'] = request.env['omniauth.auth'].except(:extra) # Removing extra as it can overflow some session stores
redirect_to new_user_registration_url, alert: @user.errors.full_messages.join("\n")
end
end
end

此時注意到controller裡面from_omniauth這個方法不是內建的要自行創立

再次更新model:

/app/models/user.rb
1
2
3
4
5
6
7
8
9
10
11
12
def self.from_omniauth(access_token)
data = access_token.info
user = User.where(:email => data["email"]).first

unless user
password = Devise.friendly_token[0,20]
user = User.create(email: data["email"],
password: password, password_confirmation: password
)
end
user
end

從unless開始是我自己的程式碼可以參考
給password獨特的token
然後我只記下使用者的信箱

意思是我利用google信箱登入後如果有在我的資料庫找到該位user就直接用,沒有的話就創立一個user。

此時應該就大功告成了!

[Rails] Boostrap Grid 用 row col 來做切版與 RWD

發表於 2018-04-18 更新於 2019-08-25 分類於 Rails , Gem

參考文件:
bootstrap-sass
Official Sass port of Bootstrap 2 and 3.

這個套件是搭配boostrap3,想要用更新的boostrap的話官方文件README.md的最上方有提及。

關於bootstrap-sass的安裝方法可以參考這篇

Grid system


Grid system

使用方法:

index.html.erb
1
2
3
4
5
<div class="row">
<div class="col-xs-6">line1</div>
<div class="col-xs-6">line1</div>
<div class="col-xs-6">line2</div>
</div>

row是固定把col包起來的,也只有包起來col才會生效。
col可以設定總共佔這行的幾格,總共是12格。

每個row總共都會被切成12格,如果一行之內的col超過12格他將會自動換行變到第二行row

如上面例子col的class會帶數字,就是佔幾格的意思,前兩個col加起來剛好12塞滿第一行,而第三個row就會被換到下一行去了!

較特別的例子如:

index.html.erb
1
2
3
4
5
<div class="row">
<div class="col-xs-4">line1</div>
<div class="col-xs-9">line2</div>
<div class="col-xs-2">line2</div>
</div>

可以看到第二個row開始因為4+9 > 12所以他已經到第二個row,而9+2 < 12則第三個col也會在的第二個row上。

RWD


以這個例子舉例:

index.html.erb
1
2
3
4
<div class="row">
<div class="col-xs-4">row</div>
<div class="col-sm-12 col-md-8">row</div>
</div>

第一個col中間狀態是xs代表不論遊覽器或裝置畫面大小(與css沒關係喲!)他永遠佔了四格。

第二個row如果符合sm畫面大小的範圍他會是佔12格變成第二個row,如果符合的是md的畫面大小的話則只會佔8格此時會跟第一個col同個row。

那狀態有哪些呢?

xs-Extra small的簡寫-畫面\<768px `sm`-small的簡寫-畫面>=768px
md-Medium的簡寫-畫面>=992px
lg-large的簡寫-畫面>=1200px

如果我設計的一個col

<div class=”col-sm-6 col-md-4 col-lg-3”>something<div>
代表畫面寬度
768px~991px是6格
992px~1199px是4格
>=1200px是3格
此時畫面如果<768則會佔滿12格!當然你也可以把col-xs設定進去此時佔多少格。

grid還有幾個例子可以注意:

index.html.erb
1
<div class="col-md-4">something<div>

代表畫面寬度

<991是12格
>=992px是4格
此時即使畫面超過了1200px也是只佔4格唷!原因是因為他的css沒有被col-lg再覆蓋上去了

如果想一直固定的話可以這樣做:

index.html.erb
1
<div class="col-xs-4">something<div>

原理可以參考官方這個

1
2
3
4
@media (max-width: @screen-xs-max) { ... }
@media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) { ... }
@media (min-width: @screen-md-min) and (max-width: @screen-md-max) { ... }
@media (min-width: @screen-lg-min) { ... }

[Rails] FriendlyId 基本教學 操作

發表於 2018-04-17 更新於 2019-08-22 分類於 Rails , Gem

參考來源:
FriendlyId
FriendlyId完整文件

目的創造將這種網址
some_domain/products/1
變為
some_domain/products/goods1

這邊紀錄我每個步驟包括遇到的問題

步驟1: 安裝


Gemfile
1
gem 'friendly_id', '~> 5.1.0' # Note: You MUST use 5.0.0 or greater for Rails 4.0+

$ bundle install
$ rails generate friendly_id
$ rails db:migrate

步驟2: 創立表單(如果已經創立過則跳過此步驟)


FriendlyId完整文件他會教你創migration這邊用product當示範:
$ rails g model product

找到該migration

xxx_create_products.rb
1
2
3
4
5
6
7
class CreateProductLists < ActiveRecord::Migration[5.0]
def change
create_table :products do |t|
t.string :title
t.string :slug
end
end

官方補充敘述:

Temp solution for Rails 5.1+ : Before running the migration, go into the generated migration file and specify the Rails version:
class CreateFriendlyIdSlugs < ActiveRecord::Migration[5.1]
如果Rails版本超過5.1以上請修改migration第一行

$ rake db:migrate

步驟3: 實作


找到該model

app/models/products.rb
1
2
3
4
class User < ApplicationRecord
extend FriendlyId
friendly_id :title, use: :slugged
end

找到該controller

products_controller.rb
1
2
3
4
5
class UserController < ApplicationController
def show
@product = Product.friendly.find(params[:id])
end
end

如果跳過步驟2的到這肯定報錯,因為就有表單並沒有slug這個欄位,緊接著看步驟4!

步驟4: 新創表單並且更新所有表單(有操作到步驟2的則不用做步驟4)


$ rails g migration add_slug_to_product

找到該migration

add_slug_to_product.rb
1
2
3
4
5
class AddSlugToProduct < ActiveRecord::Migration[5.0]
def change
add_column :products, :slug, :string, unique: true
end
end

$ rake db:migtate
最後在終端機更新所有表單
$ rails console
$ Product.find_each(&:save)
$ exit


大功告成!

[Tool]整理程式碼 Sublime setting,BeautifyRuby, htmlbeautifier

發表於 2018-04-17 更新於 2019-08-21 分類於 Tool

工具的官方文件

Sublime text
BeautifyRuby
HTML Beautifier

Sublime setting


快捷鍵command + ,
或者點選左上角Sublime Text > preferences > settings

開啟後會有左右兩個分割視窗,注意他們各自的檔案名稱:
Default是預設值,不要隨意改動!
User就是我們設定的地方,他已經預設有所有Default值的內容,設定的方法是用User的東西去覆蓋Default的東西,因為sublime會去讀User這隻檔案的設定。

關於排版的只介紹下列四個:
1.font_size 字體大小
2.tab_size 按一下tab會有幾個空白鍵
3.line_padding_bottom 每行下面的間隔
4.line_padding_top 每行上面的間隔

我的設定如下,把整個複製貼上就行:

Preferences.sublime-settings — User
1
2
3
4
5
6
{
"tab_size" : 14,
"tab_size": 2,
"line_padding_bottom": 6,
"line_padding_top": 6,
}

存檔後應該會立即見效

BeautifyRuby


BeautifyRuby
安裝方法:
1.command + shift + p打開選單
2.輸入install後選取Package Contol: Install Package
3.輸入BeautifyRuby安裝此套件

這時候對model, controller那些檔案試著下command + ctrl + k試試看有沒有成功

再來如何設定BeautifyRuby:
1.command + shift + p打開選單
2.輸入package list選取Package Contol: List Packages
3.輸入BeautifyRuby找到此套件的資料夾
4.找到BeautifyRuby.sublime-settings檔案把他拉到sublime上編輯

預設值應該為這樣:

Beautify.sublime-settings
1
2
3
4
5
6
7
8
9
{
// Would you prefer a tab or two spaces to represent a tab
// The default is two spaces represented by 'space'
// anything else will use one tab character
"file_patterns": ["\\.html\\.erb", "\\.rb", "\\.rake", "Rakefile", "Gemfile", "Vagrantfile"],
"html_erb_patterns": ["\\.html\\.erb"],
"run_on_save": false,
"save_on_beautify": true
}

可以加上”tab_size”: 2
因為BeautifyRuby的tab_size不是去吃Preferences.sublime-settings的哦!然後他的註解有說明default是2

file_patterns可以看到它支援哪些檔案

HTML Beautifier


HTML Beautifier
BeautifyRuby的文件上直接推薦HTML Beautifier這個套件,他是安裝在gem上的!

Gemfile
1
gem 'htmlbeautifier'

執行bundle install

用法是在終端機上面下指定:
$ htmlbeautifier file 指定單一檔案
$ htmlbeautifier file1 [file2 …] 他可以指定多隻檔案以上
$ htmlbeautifier app/views/folder/* 指定一個資料夾的所有檔案
$ htmlbeautifier app/views/**/* 指定views這個資料夾的所有資料夾內的所有檔案
$ htmlbeautifier app/views/**/*.html.erb 指定views這個資料夾的所有資料夾內的所有.html.erb的檔案

由於這種指令的是下了就無法復原建議htmlbeautifier前先commit哦!

[Rails]Ransack最基本使用

發表於 2018-04-17 更新於 2019-08-21 分類於 Rails , Gem , Ransack

官方文件

在view我們使用search_form_for去操作

search.html.erb
1
2
3
4
5
<%= search_form_for @q do |f| %>
<%= f.label :name_cont %>
<%= f.search_field :name_cont %>
<%= f.submit %>
<% end %>

在controller裡

search_controller.rb
1
2
3
4
def index
@q = Person.ransack(params[:q])
@people = @q.result(distinct: true)
end

此時如果我們在收尋欄輸入 ‘kurt’ 並送出在rails console會發現:
$ params[:q] = {’name’ => ‘kurt’}

$ @q = Ransack::Search<class: Person, base: Grouping <conditions: [Condition <attributes: [“name”], predicate: cont, values: [“kurt”]>], combinator: and>>

$ @q.result.to_sql = “SELECT “persons”.* FROM “persons” WHERE (“persons”.”name” LIKE ‘%kurt%’)”

我們可以把撈出的result放進@people這個變數拿去使用了!

注意:在f.search_field欄位給予的欄位名稱後面要加上_cont!
例如要找name這個欄位就要輸入name_cont

[Rails]form_for action to where

發表於 2018-04-16 更新於 2020-01-19 分類於 Rails

參考文章:
Ruby on Rails Guides
Ruby on Rails 5.2.0
form_for but to post to a different action(stackoverflow)

如何看結果


直接以Ruby on Rails Guides為例子

form.html.erb
1
2
3
4
5
6
<%= form_for @person, url: {action: "create"} do |person_form| %>
<%= person_form.text_field :name %>
<%= fields_for @person.contact_detail do |contact_detail_form| %>
<%= contact_detail_form.text_field :phone_number %>
<% end %>
<% end %>

開啟遊覽器按檢查可以直接看到form_for render出的form tag長得如何

1
2
3
4
5
6
<form class="new_person" id="new_person" action="/people" accept-charset="UTF-8" method="post">
<input name="utf8" type="hidden" value="&#x2713;" />
<input type="hidden" name="authenticity_token" value="bL13x72pldyDD8bgtkjKQakJCpd4A8JdXGbfksxBDHdf1uC0kCMqe2tvVdUYfidJt0fj3ihC4NxiVHv8GVYxJA==" />
<input type="text" name="person[name]" id="person_name" />
<input type="text" name="contact_detail[phone_number]" id="contact_detail_phone_number" />
</form>

再來我們就專注於form這個tag就好!

原理


如剛剛的例子:
1.form_for會先去查看instance是什麼
2.預設去找尋對應的model存不存在
3.如存在會去找對應名稱的controller
4.when new action create, when edit action update

所以此例子會有model/persons.rb和person_controller.rb,且controller應該至少如下:

person_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def new
@person = Person.new
end

def create
@person = Person.find(params[:id])
@person = Person.new(person_params)
@person.save
end

private

def person_params
params.require(:person).permit(:參數)
end

自定義


在form_for裡面可以設定
url:
controller-指定controller
action-指定用controller裡的哪個method
params-傳遞什麼params

method:指定用什麼動作(get, post…等)

例如:

form_html.erb
1
<%= simple_form_for @person, url: {:controller => 'my_controller', :action => 'my_action'}, method: 'post' do |f| %>

更多實際例子可以參考這篇form_for but to post to a different action(stackoverflow)

[Rails] simple_form 簡易使用

發表於 2018-04-15 更新於 2019-08-21 分類於 Rails , Gem

官方文件

安裝


Gemfile
1
gem 'simple_form'

$ bundle install 安裝gem
$ rails generate simple_form:install 安裝simple_form
$ rails generate simple_form:install —bootstrap 安装 simple_form for bootstrap
如果有在使用bootstrap的話simple_form是很方便支援的

再來就可以開始使用了!

使用


把form_fo改為simple_form_for及可套入

form.html.rb
1
2
3
4
5
<%= simple_form_for @user do |f| %>
<%= f.input :username %>
<%= f.input :password %>
<%= f.button :submit %>
<% end %>

現在可以追加幾種用法

form.html.rb
1
2
3
4
5
6
7
<%= simple_form_for @user do |f| %>
<%= f.input :username, label: 'Your username please', error: 'Username is mandatory, please specify one' %>
<%= f.input :password, hint: 'No special characters.' %>
<%= f.input :email, placeholder: 'user@domain.com' %>
<%= f.input :remember_me, inline_label: 'Yes, remember me' %>
<%= f.button :submit %>
<% end %>

label 設定標題-default欄位名稱
error在model設定validates後統一出現的錯誤訊息
hint在input欄位下方的提示訊息
placeholder沒有特別的
inline_label給欄位為布林值用的-checkbox, radiobox

再來可以設定任何的css

form.html.rb
1
2
3
4
5
6
<%= simple_form_for @user do |f| %>
<%= f.input :username, label_html: { class: 'my_class' } %>
<%= f.input :password, hint: false, error_html: { id: 'password_error'} %>
<%= f.input :password_confirmation, label: false %>
<%= f.button :submit %>
<% end %>

如果有安裝了boostrap可以直接用framework的css

也可以使用html tag原生的東西

form.html.rb
1
2
3
4
5
6
<%= simple_form_for @user do |f| %>
<%= f.input :username, input_html: { class: 'special' } %>
<%= f.input :password, input_html: { maxlength: 20 } %>
<%= f.input :remember_me, input_html: { value: '1' } %>
<%= f.button :submit %>
<% end %>

想要宣染整個表單每一個欄位的設定的話在最外層加入defaults

form.html.rb
1
2
3
4
5
6
<%= simple_form_for @user, defaults: { input_html: { class: 'default_class' } } do |f| %>
<%= f.input :username, input_html: { class: 'special' } %>
<%= f.input :password, input_html: { maxlength: 20 } %>
<%= f.input :remember_me, input_html: { value: '1' } %>
<%= f.button :submit %>
<% end %>

使用wrapper_html可以把一個input欄位的css模組化

form.html.rb
1
2
3
4
5
6
<%= simple_form_for @user do |f| %>
<%= f.input :username, wrapper_html: { class: 'username' } %>
<%= f.input :password, wrapper_html: { id: 'password' } %>
<%= f.input :remember_me, wrapper_html: { class: 'options' } %>
<%= f.button :submit %>
<% end %>

現在validates不一定要寫在model可以直接寫在html裡面

官方文件敘述

Required fields are marked with an * prepended to their labels.

By default all inputs are required. When the form object includes ActiveModel::Validations (which, for example, happens with Active Record models), fields are required only when there is presence validation. Otherwise, Simple Formwill mark fields as optional. For performance reasons, this detection is skipped on validations that make use of conditional options, such as :if and :unless.
And of course, the required property of any input can be overwritten as needed

form.html.rb
1
2
3
4
5
6
<%= simple_form_for @user do |f| %>
<%= f.input :name, required: false %>
<%= f.input :username %>
<%= f.input :password %>
<%= f.button :submit %>
<% end %>

可以直接更改input type

form.html.rb
1
2
3
4
5
6
7
<%= simple_form_for @user do |f| %>
<%= f.input :username %>
<%= f.input :password %>
<%= f.input :description, as: :text %>
<%= f.input :accepts, as: :radio_buttons %>
<%= f.button :submit %>
<% end %>

經由checkbox轉變的as: :radio_buttons會自動出現yes/no的按鈕
as: :select可以製造出dropdown效果

官方補充敘述

So instead of a checkbox for the accepts attribute, you’ll have a pair of radio buttons with yes/no labels and a textare instead of a text field for the description. You can also render boolean attributes using as: :select to show a dropdown.

simple_form支持所有Rails tag原生功能

form.html.rb
1
2
3
4
5
6
7
<%= simple_form_for @user do |f| %>
<%= f.input :date_of_birth, as: :date, start_year: Date.today.year - 90,
end_year: Date.today.year - 12, discard_day: true,
order: [:month, :year] %>
<%= f.input :accepts, as: :boolean, checked_value: true, unchecked_value: false %>
<%= f.button :submit %>
<% end %>

simple_form可以把label, hint, input_field, error and full_error等等拆開讓他們各自是一個tag

詳情請閱讀官方文件!
官方敘述

Simple Form also allows you to use label, hint, input_field, error and full_error helpers (please take a look at the rdocs for each method for more info

form.html.rb
1
2
3
4
5
6
7
<%= simple_form_for @user do |f| %>
<%= f.input :date_of_birth, as: :date, start_year: Date.today.year - 90,
end_year: Date.today.year - 12, discard_day: true,
order: [:month, :year] %>
<%= f.input :accepts, as: :boolean, checked_value: true, unchecked_value: false %>
<%= f.button :submit %>
<% end %>

特別的Collections功能

可以簡易的做出一個數字範圍的select-不用輸入as: :select

form.html.rb
1
2
3
4
5
<%= simple_form_for @user do |f| %>
<%= f.input :user %>
<%= f.input :age, collection: 18..60 %>
<%= f.button :submit %>
<% end %>

Collections可以為一個陣列-也可以搭配兩個參數客製化select, radiobox等等
label_method -顯示標題
value_method -實際得到的值

實際例子

form.html.rb
1
2
3
<%= simple_form_for @user do |f| %>
<%= f.input :gender, as: :radio_buttons, collection: [['0', 'female'], ['1', 'male']], label_method: :second, value_method: :first %>
<% end %>

這時候會製造出兩個radiobox,label是second每個陣列的第二個,實際的值則是first第一個!

實際經驗


狀況1.
把submit加上disable_with可以在按鈕disable的時候更改敘述文字讓使用者更好懂

form.html.rb
1
2
3
<div class="form-actions">
<%= f.submit "Submit", disable_with: "Submiting...", class: "btn btn-primary"%>
</div>

狀況2.
假如route是有層級的
例如:/group/1/post/1
則需要對simple_form傳入陣列且順序不能錯!

form.html.rb
1
2
3
4
5
6
7
8
<%= simple_form_for [@group,@post] do |f| %>
<div class="form-group">
<%= f.input :content, label: "內容" input_html: { class: "form-control"} %>
</div>
<div class="form-actions">
<%= f.submit "Submit", disable_with: "Submiting...", class: "btn btn-primary"%>
</div>
<% end %>

希望能幫助到大家,有錯誤再請不吝嗇指教,當然還有更多文件請參考官方文件!

[Rails]利用 request direct_to 原本頁面

發表於 2018-04-15 更新於 2019-08-21 分類於 Rails

參考文章:
How to redirect to previous page in Ruby On Rails?(stackoverflow)

Ruby on Rails 實戰聖經

前言


redirect_to :back這個簡單回上一頁的方法似乎在Rails5不能使用了!
這時候我們可以利用request和session去做到導回前一頁的功能。

這裡的狀況:
有A和B頁面都可以過去C頁面編輯一篇文章,但從A頁面編輯完後要回到A,B則回到B,也就是說要做到這樣子:

A > C > A
B > C > B

如何實作?

實作


在C的controller裡的edit和update加入兩行

C_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def edit
@article = Article(params[:id])
session[:return_to] ||= request.referer
end

def update
@article = Article.find(params[:id])
if @article.update(post_params)
redirect_to session[:return_to]
session.delete(:return_to)
flash[:notuce] = "Update Success"
else
redirect_to root, alert: "Something wrong..."
end
end

private

def post_params
params.require(:article).permit(:content)
end

原理是用request.referer把前一頁的網址先存在session裡面,update的時候在導回剛剛存的網址頁。

所以我在A頁面的時候對某篇文章按編輯到C頁面觸發他的edit方法,這時候把前一頁也就是A的網址存下來,編輯完送出後觸發C的update導回剛剛存的A網址頁面,同理B也是一樣,我們就可以做到:

A > C > A
B > C > B

另外剛剛的update可以簡寫如下:

1
2
3
4
5
6
7
8
def update
@article = Article.find(params[:id])
if @article.update(post_params)
redirect_to session.delete(:return_to), notice: "Update Success"
else
redirect_to root, alert: "Something wrong..."
end
end

補充


request是用戶端發送請求的東西,例如header等等,當然也有response對象,可以參考

Ruby on Rails 指南

[Rails]AASM套件教學

發表於 2018-04-14 更新於 2020-05-26 分類於 Rails , Gem

參考文件:

官方文件
為你自己學

教學開始


在自己的model引入AASM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Job
include AASM

aasm do
state :sleeping, :initial => true
state :running, :cleaning

event :run do
transitions :from => :sleeping, :to => :running
end

event :clean do
transitions :from => :running, :to => :cleaning
end

event :sleep do
transitions :from => [:running, :cleaning], :to => :sleeping
end
end

end

state統整所有可能的狀態-initial為初始狀態
event各個事件method名稱
transitions從(from)什麼狀態改為(to)什麼狀態

此時我們在rails console也有了下面的methods可以呼叫

1
2
3
4
5
6
7
8
job = Job.new
job.sleeping? # => true
job.may_run? # => true
job.run
job.running? # => true
job.sleeping? # => false
job.may_run? # => false
job.run # => raises AASM::InvalidTransition

這時候在controller裡面可以呼叫

1
2
3
…
@job.run!
...

執行結果:
job.aasm_state從原本的"sleeping"更新為"running"

注意:
1.transitions from可以是一個陣列,但如果呼叫了此event但值不包含在from裡面則會報錯!
ex:
在job.aasm_state還是sleeping的時候執行@job.clean!

2.aasm do預設執會去找aasm_state這個欄位,如要設定哪個欄位請使用aasm(xxx) do
ex:
想要他去偵測一個location欄位需要寫成aasm(:location) do

3.我們可以宣告多個欄位,但有重複的event後面的會覆蓋到前面的event,請善用namespace!
ex:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class NamespacedMultipleExample
include AASM
aasm(:status) do
state :unapproved, :initial => true
state :approved

event :approve do
transitions :from => :unapproved, :to => :approved
end

event :unapprove do
transitions :from => :approved, :to => :unapproved
end
end

aasm(:review_status, namespace: :review) do
state :unapproved, :initial => true
state :approved

event :approve do
transitions :from => :unapproved, :to => :approved
end

event :unapprove do
transitions :from => :approved, :to => :unapproved
end
end
end

在rails console呼叫:

1
2
3
4
5
6
7
8
9
namespaced = NamespacedMultipleExample.new

namespaced.aasm(:status).current_state
# => :unapproved
namespaced.aasm(:review_status).current_state
# => :unapproved
namespaced.approve_review
namespaced.aasm(:review_status).current_state
# => :approved

以上我認為已經很夠用,如果想了解更多再去翻文件吧!
官方文件

1…8910…18

Kurt Hsu

Progress One Percent Every Day
171 文章
55 分類
163 標籤
RSS
© 2020 Kurt Hsu
由 Hexo 強力驅動 v3.8.0
|
主題 – NexT.Muse v7.3.0