12/08/2018, 13:55

Tìm hiểm gem Wicked trong Rails

1. Giới thiệu Trong Rails, rất nhiều trường hợp chúng ta phải phá vỡ RESTful để thực hiện step by step một công việc nào đó. (Ví dụ: Khi muốn tạo mới một object bạn muốn có thể preview thông tin của object đó trước khi save lại. Trong trường hợp này bạn phải tạo thêm một hàm preview trong ...

1. Giới thiệu

Trong Rails, rất nhiều trường hợp chúng ta phải phá vỡ RESTful để thực hiện step by step một công việc nào đó. (Ví dụ: Khi muốn tạo mới một object bạn muốn có thể preview thông tin của object đó trước khi save lại. Trong trường hợp này bạn phải tạo thêm một hàm preview trong controller). Wicked giúp chúng tao thu gọn những hàm không cần thiết một cách linh hoạt để controller luôn thỏa mãn RESTful. Hãy cũng đọc qua bài hướng dẫn này để hiểu thêm cách hoạt động của nó.

2. Cài đặt

Thêm vào Gemfile

gem “wicked”

Run bundle install

Giờ chúng ta sẽ ví dụ trên controller after signup

  • Tạo controller:
rails g controller after_signup
  • Thêm route vào file config/routes.rb :
resource :after_signup
  • Include Wicked::Wizard vào controller trên
class AfterSignupController < ApplicationController
  include Wicked::Wizard
  steps :confirm_password, :confirm_profile, :find_friends
end

Một cách khai báo khác bằng cách thừa kế Wicked::WizardController :

class AfterSignupController < Wicked::WizardController
  steps :confirm_password, :confirm_profile, :find_friends
end

wizard được dùng để gọi step trong hàm show, bạn có thể tùy chỉnh logic trong hàm show tùy vào từng trường hợp như ví dụ bên dưới đây.

class AfterSignupController < ApplicationController
  include Wicked::Wizard

  steps :confirm_password, :confirm_profile, :find_friends

  def show
    @user = current_user
    case step
    when :find_friends
      @friends = @user.find_friends
    end
    render_wizard
  end
end

Bạn cần phải gọi render_wizard ở cuối của hàm để gọi được view tương ứng.

Mặc định wizard sẽ render view cùng tên với step trong controller. Vậy với AfterSignupController bạn sẽ có thư mục view tương ứng là /views/after_signup/. Nếu gọi step :confirm_password thì wizard sẽ render views/after_signup/confirm_password.html.erb

Ở view bạn có thể suer dụng helper để chuyển tới bước tiếp theo:

<%= link_to 'skip', next_wizard_path %>

Bạn cũng có thể chỉ định chính xác step mà mình muốn chuyển đến bằng cách sử dụng wizard_path helper:

<%= link_to 'skip', wizard_path(:find_friends) %>

Một ví dụ khác về wicked trong hàm update

class AfterSignupController < ApplicationController
  include Wicked::Wizard

  steps :confirm_password, :confirm_profile, :find_friends

  def update
    @user = current_user
    case step
    when :confirm_password
      @user.update_attributes(params[:user])
    end
    sign_in(@user, bypass: true) # needed for devise
    render_wizard @user
  end
end

Ở đây chúng ta sử dụng render_wizard @user. Khi sử dụng như thế này controller sẽ chuyển đến bước tiếp theo nếu @user save thành công hoặc chuyển đến bước trước nếu thất bại.

CHú ý : render_wizard bao gồm cả save đối tượng. Điều đó có nghĩa rằng với ví dụ bên trên đối tượng sẽ lưu lại hai lần đồng nghĩa là nếu có callback sẽ cũng sẽ bị gọi hai lần. Vì vậy trong trường hợp này chúng ta nên sử dụng assign_attributes thay cho update_attributes sẽ chính xác hơn.

Để gọi update cho user chỉ đơn giản submit form với method PUT tới chính xác url:

<%= form_for @user, url: wizard_path, method: :put do |f| %>
  <%=  f.password_field :password  %>
  <%=  f.password_field :password_confirmation  %>

  <%= f.submit "Change Password" %>
<% end %>

Hãy nhơ khai báo method: :put ở đây vì nếu quên điều này bạn sẽ nhận được một cảnh báo rằng không tìm thấy action create nào hoặc "no route found for POST.

Ngoài ra trong controller nếu bạn muốn bỏ qua một step nào đó thì chỉ cần gọi hàm skip_step

def show
  @user = current_user
  case step
  when :find_friends
    if @user.has_facebook_access_token?
      @friends = @user.find_friends
    else
      skip_step
    end
  end
  render_wizard
end

3. Danh sách method

View/URL Helpers:

wizard_path                  # lấy path hiện thời
wizard_path(:specific_step)  # path tới :specific_step
next_wizard_path             # path tới step kế tiếp
previous_wizard_path         # path tới step trước đó

Controller

steps  :first, :second       # set thứ tự của các step
step                         # gọi step hiện tại
next_step                    # gọi step kế tiếp
previous_step                # gọi step trước đó
skip_step                    # bỏ qua step
jump_to(:specific_step)      # gọi :specific_step
render_wizard                # Renders step hiện tại
render_wizard(@user)         # render step kế tiếp nếu @user lưu thành công
wizard_steps                 # list các step

4. Tổng kết

Trên đây là những hướng dẫn cơ bản để sử dung gem Wicked tạo các step trong controller. Các bạn có thể tham khảo thêm tại : gem Wicked. Chúc các bạn thành công

0