Рубин на рельсах 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
Он создан быстро, поэтому прошу прощения за некоторые уродливые методы (скоро перепишу его в гораздо лучший формат)
Вы также можете прочитать это для сложной интеграции