Рубин на рельсах AASM Изменить переход по нажатию кнопки

Мой вопрос очень прост: как я могу изменить aasm переходы по нажатию кнопки? Что я должен поставить на мой взгляд?

У меня есть две кнопки: Approve а также Reject, Мои штаты выглядят так:

  aasm :column => 'state' do
    state :pending, :initial => true
    state :approved
    state :rejected

    event :approve do
      transitions :to => :approved, :from => [:pending]
    end

    event :reject do
      transitions :to => :rejected, :from => [:pending]
    end
  end

ОБНОВЛЕНИЕ: Мои параметры это:

{"utf8"=>"✓", "_method"=>"put", "authenticity_token"...", "commit"=>"APP", "id"=>"65"},

И вот как я получаю доступ к действию из представления:

= form_for([:admin, shop], method: :put, data: { confirm: "You sure?" }) do |f|
  = f.submit "Approve", :controller => :shops, :action => :approve

Код моего контроллера:

def approve
  @shop = Shop.find(params[:id])
  @shop.approve!
end

Маршруты:

namespace :admin do
  get "shops/:id/approve" => "shops#approve"

4 ответа

Решение

Как упомянуто Srikanth вы захотите отправить запрос на контроллер, однако вместо form откровенно, я бы рекомендовал использовать button_to следующее:

<%= button_to "Approve", admin_shops_approve_path(shop.id), method: :put %>
<%= button_to "Disapprove", admin_shops_disapprove_path(shop.id), method: :put %>

Это отправит запрос вашему контролеру. Похоже, вы уже делаете это, но для пояснения вам понадобится следующее:

#config/routes.rb
namespace :admin do
   resources :shops do
      put :approve #-> domain.com/admin/shops/:id/approve
      put :disapprove #-> domain.com/admin/shops/:id/disapprove
   end
end

#app/controllers/admin/shops_controller.rb
class Admin::ShopsController < ApplicationController
   before_action, :set_shop

   def approve
      @shop.approve!
   end

   def disapprove
      @shop.disapprove!
   end

   private

   def set_shop
      @shop = Shop.find params[:id]
   end
end

Это даст вам эффективный способ отправки необходимых данных в вашу форму, вызывая AASM процесс в результате.

Aasm работает путем добавления состояний, переходов и событий в модель.

Вы не можете получить доступ к модели непосредственно из вида. Вместо этого вы можете создавать соответствующие действия в вашем контроллере, к которым вы можете привязать свои кнопки.

Обратите внимание, что у событий aasm есть логика, т.е. к какому событию вы можете перейти и т. Д. Вы можете выполнить все эти проверки и предоставить соответствующее ответное сообщение от действия вашего контроллера.

Редактировать:

Вот идея, как бы я это сделал:

FooController.rb:

class FooController < ApplicationController
  def approve
    foo = Foo.find(params[:id])
    foo.approve!
  end

  def reject
    foo = Foo.find(params[:id])
    foo.reject!
  end
end

routes.rb:

get "foo/:id/approve" => "foo#approve"
get "foo/:id/reject" => "foo#reject"

замещать Foo с вашей моделью!

У меня была такая же проблема. Я решил это так:

модель

class Call < ActiveRecord::Base

  include AASM

  aasm_column :status

  aasm do
    state :start, :initial => true
    state :in_progress
    state :finished
    state :archived

    event :run do
     transitions :from => [:start, :finished, :archived], :to => :in_progress
    end

    event :stop do
      transitions :from => :in_progress, :to => :finished
    end

    event :resolve do
      transitions :from => [:in_progress, :finished], :to => :archived
    end
  end
end

контроллер

class CallsController < ApplicationController
  before_action :set_call, only: [:run, :stop, :resolve]

  def run
    redirect_to calls_path if @call.run!
  end

  def stop
    redirect_to calls_path if @call.stop!
  end

  def resolve
    redirect_to calls_path if @call.resolve!
  end

  private

    def set_call
      @call = Call.find(params[:id])
    end
end

Routes route.rb

resources :calls do
  member do
    put :run
    put :stop
    put :resolve
  end
end

Просматривает звонки /index.html.erb

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Status</th>
      <th>Start call</th>
      <th>Stop call</th>
      <th>Resolve call</th>
    </tr>
  </thead>

  <tbody>
    <% @calls.each do |call| %>
      <tr>
        <td><%= call.name %></td>
        <td><%= call.status %></td>
        <td><%= link_to "Start", run_call_path(call) , method: :put %></td>
        <td><%= link_to "Stop", stop_call_path(call), method: :put %></td>
        <td><%= link_to "Resolve", resolve_call_path(call), method: :put %></td>
      </tr>
    <% end %>
  </tbody>
</table>

Вы также можете добавить обратный вызов в свою модель, например

before_update { |order| order.log_status_change if order.aasm_state_changed? }

*filed_name_<_ изменено?>

Мой текущий проект был необходим для создания селектора AASM, зависит от разрешения CanCan и текущих событий.

Если кто-то ищет эту функцию, вы можете использовать эту суть: https://gist.github.com/alexey/446c6c4ce2a5af0f4fb6851e6d6d514e

Он создан быстро, поэтому прошу прощения за некоторые уродливые методы (скоро перепишу его в гораздо лучший формат)

Вы также можете прочитать это для сложной интеграции

Другие вопросы по тегам