State Machine, naming the next and previous states - ruby-on-rails-3

I'm using the state_machine gem in my Rails 3.2.9 application and am trying to get the name of the next state.
I can list all states with:
Order.state_machine.states.map &:name
But I can't see in the docs whether it's possible to get the name of the next state.
I have something like this in my model:
state_machine :initial => 'stage_1', :use_transactions => false do
event :next do
transition :from => 'stage_1', :to => 'stage_2'
transition :from => 'stage_2', :to => 'stage_3', :if => :is_valid?
transition :from => 'stage_2', :to => 'stage_4'
If I'm on state_2, I'd like to display stage_3.
Any suggestions?

You can simply use the helper methods like
Order.state_events
Order.state_transitions
Order.state_paths.from_name
Order.state_paths.to_name
Check the documentation on instance methods

Related

Rename a custom member route named helper in Rails 3

I have routes listed as follows
resources :jobs do
resources :invoices, :only => [:show] do
get 'submit_invoice', :on => :member
end
end
So the middle route creates a url like /jobs/:job_id/invoices/:id/submit_invoice which is exactly what I want. However rails assigns the name submit_invoice_job_invoice to the path which is ugly and horrible to type.
How can I make the name just submit_invoice so that I can have submit_invoice_path and submit_invoice_url?
The answer should be:
get "/jobs/:job_id/invoices/:id/submit_invoice" => "invoices#submit_invoice",
:as => "submit_invoice"
resources :jobs do
resources :invoices, :only => [:show] do
get 'submit_invoice', :on => :member, :as => 'submit_invoice'
end
end
Use :as => 'routename' and invoke it as routename_path.
:)

Using generated paths with resources in Rails

I have following routes defined:
CyberTrackRails3::Application.routes.draw do
scope "(:locale)", :locale => /en|de|nl/ do
resources :login do
get 'index', on: :collection
get 'check', on: :collection
end
end
end
Now, url_for(:controller => 'login', :action => 'check'), gives me the correct url, en/login/check.
Using login_check_path however doesn't work. How do I make this work?
I've tried replacing get 'index', on: :collection with match 'check' => 'check' but that doesn't work. Neither does match 'check' => 'login#check'.
since you're adding an action to a resource, i think the automatically generated name is going to be reversed, ie 'check_logins_path' (see adding-more-restful-actions)
do you need login_check_path specifically? if so, you should be able to define the path outside of the resources :login block, ie
match '/login/check' => 'login#check', :via => :get, :as => 'login_check'
and like Fivell suggested, rake routes will show you the automatically generated name for a route.

Routes problem with I18n_routing gem

I'm on Rails 3 and on my 2nd Rails project (i.e. I'm a newbie). I am making a website with several locales, at the moment Swedish and US. I am using the I18n_routing gem to create localized url:s. I am also using the friendly_id gem to create better urls.
My problem: I cannot get my nested urls to be translated. They remain as the default-urls.
This is my routes.rb:
localized(I18n.available_locales, :verbose => true) do
resources :calculation_types, :only => [:show], :path => '' do
resources :calculations, :only => [:index, :show], :path => '' do
member do
put 'calculate_it'
get 'calculate_it', :redirect_me => true
get 'link'
end
end
end
end
localized(I18n.available_locales, :verbose => true) do
match 'searchresults' => 'home#search-results', :as => :searchresults
match 'about' => 'home#about', :as => :about
match 'advertise' => 'home#advertise', :as => :advertise
match 'terms' => 'home#terms', :as => :terms
match 'calculator' => 'home#calculator', :as => :calculator
match 'feedback' => 'home#feedback', :as => :feedback
end
This is a sample (cut) of my locale (for Swedish):
se:
named_routes_path:
about: 'om'
advertise: 'annonsera'
calculator: 'kalkylator'
feedback: 'feedback'
searchresults: 'sokresultat'
terms: 'anvandaranvisning'
resources:
accumulated-passive-income: "vardet-av-din-passiva-inkomst"
all-about-a-date: "allt-om-ett-datum"
area: "area"
average-speed: "genomsnittshastighet"
birthday-in-days: "fodelsedag-i-dagar"
These are some facts of the case:
The resources-translations include both "calculation_types" and "calculations".
I have tried several set-ups in the translation file.
The SECOND routing WORKS, the one with the "match", they also appear when I do rake routes.
I get no error messages. Everything works fine.
I am using friendly_id as the url-words. An example of a url could be http://local.domain.com:3000/diet/bmi where "diet" is calculation_type.friendly_id and bmi is calculation.friendly_id
I want help with:
- Why do the nested routes not show up as routes? Why are they not being created?
- How do I get this to work?
Do you need any more info to help me?
It seems like it is not a matter of I18n_routing after all since the words that should be translated are actually friendly_id:s. So, disregard the I18n_routing part of this problem and focus on the friendly_id-translation...

How can I call different controllers from routes.rb

I'm just struggling a few hours with a problem, that seems rather easy, but not for me and not for google :)
I put some routes via
scope :path => '/:mandate_key', :controller => :tasks do
get '/' => :index #mandate_path
match '/import' => "import#index"
match '/clearance' => "clearance#index"
end
So far, so ugly! I'm looking for a way to call different controllers (import and clearance) dependent on the second param. Something like this:
scope :path => '/:mandate_key', :controller => :tasks do
get '/' => :index
scope :path => ':task_key', :controller => %{'task_key'}
get '/' => :index
end
end
where :task_key should be recognized as params[:task_key] and the called controller should be the value of params[:task_key]
So if a click a link like http://some.url/a_mandate_key/import it should call the ImportController.
I'm sure that the solution will be simple, but finding is hard!
Sometimes one is looking for a highly complicated solution, but it could be so much easier:
scope :path => '/:mandate_key' do
get '/' => "tasks#index" #mandate_path
get '/import' => "import#index"
get '/clearance' => "clearance#index"
end
Calling http://localhost/mandate the controller 'mandate' is called an params[:mandate_key] provides 'mandate'
Calling http://localhost/mandate/import the controller 'import' is called an params[:controller] provides 'import'
Trying the easy way is often the best way :)
Thanks for your help, Bohdan!
you might add in the bottom of your routes match ':controller(/:action(/:id))' so any unknown url will be dispatched this way
How about
scope :path => '/:mandate_key', :controller => :tasks do
get '/' => :index #mandate_path
end
....
match ':mandate_key/:controller(/:action)'
first scope will match routes /:mandate_key/tasks and the second one /:mandate_key/:controller or /:mandate_key/:controller/:action however second part should be defined in the bottom of your routes.rb file otherwise it'll match wrong routes

How to achieve a separated Admin (namespaced or scoped) with two devise models (User & Admin) in Rails 3?

Consider this as a challenge rather than its general approach. The reason I mention this is because, it is generally preferred to incorporate admin-accessible features into the public facing site. This is what's required:
Devise model for Users, visitors accessing the public facing site
Devise model for Admins
Namespace or scope the admin 'area' to /admin. Admins can only login from this route.
Users can sign up directly from the site's public facing landing page; they are not forced to visit /users/sign_up as per the default devise generated route.
Consider overriding the default devise controllers
Thanks,
Mike.
The following seems like I've made some progress in the right direction; this at least provides identical out-of-the-box devise functionality for both users and admins, with the custom routing,
match 'admin', :controller => 'admin'
namespace :admin do
# to be updated later...
end
devise_for :users
#devise_for :admins, :path => "admin" # this works but uses the default
# Devise::SessionController
devise_for :admins,
:controllers => {
:sessions => "admin/sessions",
:passwords => "admin/passwords",
:registrations => "admin/registrations" }, :path => "admin",
:skip => [:sessions, :passwords, :registrations] do
get 'admin/sign_in' => 'admin/sessions#new', :as => :new_admin_session
post 'admin/sign_in' => 'admin/sessions#create', :as => :admin_session
get 'admin/sign_out' => 'admin/sessions#destroy', :as => :destroy_admin_session
get 'admin/sign_up' => 'admin/registrations#new', :as => :new_admin_registration
get 'admin/account' => 'admin/registrations#edit', :as => :edit_admin_registration
post 'admin/account' => 'admin/registrations#create', :as => :admin_registration
get 'admin/cancel' => 'admin/registrations#cancel', :as => :cancel_admin_registration
put 'admin/account' => 'admin/registrations#update'
delete 'admin/account' => 'admin/registrations#destroy'
post 'admin/password' => 'admin/passwords#create', :as => :admin_password
get 'admin/password/new' => 'admin/passwords#new', :as => :new_admin_password
get 'admin/password/edit' => 'admin/passwords#edit', :as => :edit_admin_password
put 'admin/password' => 'admin/passwords#update'
end
Ideas?
caveat: in this example, I've included the :registerable devise module in the Admin model just for testing during development. The sign_up route will, ultimately, be removed.
Much searching yielded (mind the pun) the following blog post that seems to indicate overriding a devise controller requires the re-mapping of all its specified 'HTTP verbs' as it were; this makes sense as unmapped ones would be handled by the default devise controller.
If anyone has more experience working with multiple devise models and the separated admin approach, I would be very much interested in your thoughts and suggestions!