Sorry, this entry is only available in 日本語.
Rails: How to Solve devise error undefined method failure_app for nil class
I bumped into the following error when I was creating API program. The origin was devise gem.
NoMethodError (undefined method `failure_app’ for nil:NilClass)
Environment
- Ruby 2.2.3p173
- Rails 4.2.4
- devise 3.5.2
Origin
I used sign_in method for unauthorized user.
The API in construction, we have to make unauthorized user able to login, so I wrote logging in procedure for all users, including unauthorized users. Then, devise and warden rejected unauthorized user and raised error.
Solution
Write the following setting into config/initializer/devise.rb.
|
1 |
config.allow_unconfirmed_access_for = 2000.years |
Or write the following method into the model class that is used by devise for authentication. User class for example.
|
1 2 3 4 |
private def confirmation_period_valid? return true end |
I recommend latter solution.
confirmation_period_valid?
confirmation_period_valid? method is defined at the module Devise::Models::Confirmable of devise gem.
The way to eat lunch for less than 540 yen everyday around Ginza
Rails: Upgrade Cells 3 to Cells 4
In Rails, I upgraded Cells gem from 3.11.3 to 4.0.2. And I upgraded Rails from 4.1.9 to 4.2.4 together. Here, I wrote what I did about Cells upgrade.
Basic instruction is in From Cells 3 to Cells 4 Upgrading Guide. It’s not easy to upgrade it.
Environment
- Ruby 2.2.3
- Template Engine: Slim
Story
ある人が外注に出していたプログラムを なぜか私がデザイン、マークアップ含めて更新することになり、 Rails と Gem のバージョンを更新した。
その Rails のアプリケーションにテストコードは一切なかった。
リリース前のプログラムに対して変更を行いました。
What I did
- Create ApplicationCell
- Change helper to include
- Change render_cell to cell
- Change file name
- Change partial view rendering way
Create ApplicationCell
If you use functions relates to device or form tags, the application will stop working after upgrading to Cells 4. Then I created ApplicationCell as a parent class of all Cell class.
アプリケーションを見ながら 次のような ApplicationCell を作りました。 include で取り込んでいるモジュールは、 エラーが出る度に順次取り込んでいったものです。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
class ApplicationCell < Cell::ViewModel include Cell::Slim include ActionView::Helpers::DateHelper include ActionView::Helpers::TextHelper include ActionView::Helpers::NumberHelper include ActionView::Helpers::FormHelper include ActionView::Helpers::FormOptionsHelper include ERB::Util def self.helper_method(*) end def dom_class(record, prefix = nil) ActionView::RecordIdentifier.dom_class(record, prefix) end def dom_id(record, prefix = nil) ActionView::RecordIdentifier.dom_id(record, prefix) end end |
self.helper_method is called by devise, so it is necessary. Cells では 既に意味のないメソッドになっているので、 何も処理は行いません。
Change helper to include
In each cell class, there was a line “helper ApplicationHelper“.
Webrick を実行してページを開くと undefined method と表示されました。 Then, change helper statement to include statement with sed command.
Change render_cell to cell
Cells 4 から メソッドが変わりました。 ビューの中で使用されている render_cell を cell に書き換えました。
いままで書いていた人がコードを綺麗に保っていたので、 sedコマンドを使って簡単に変更できました。 書き方が何通りもある場合は、簡単にはいきません。
Before
|
1 |
= render_cell :cell_name, :method_name, option_1: 1, option_2: 2 |
After
|
1 |
= cell(:cell_name).(:method_name, option_1: 1, option_2: 2) |
Change file name
There were cell templates named like method_name.html.slim, but Cells 4 method cell(:cell_name).(:method_name) search template named method_name.slim. It caused exception.
In cells/lib/cell/view_model.rb of Cells 4, find_template method generates template name. Generated template name by that method doesn’t contain the string 'html'.
I removed “html” from template file name.
Change partial view rendering way
I know what I did is quick and dirty way.
In old code, cell template renders partial view app/views/shared/something.html.slim.
Before
|
1 |
= render partial: 'shared/something', locals: {something: true} |
But it doesn’t work in Cells 4.
cells/lib/cell/templates.rb と cells/lib/cell/view_model.rb を見ながら次のようにコードを変更しました。
After
|
1 |
= render prefixes: ['app/views'], view: 'shared/_something.html', locals: {something: true} |
I had not only to create prefixes and view value, but change view value.
app/views内のテンプレートを呼び出す際のメソッドを ApplicationCell に作ったほうがよかったかもしれません。
Cell の中に self.view_paths += ['app/views'] を加えると、 app/views/cell_name の中でテンプレートを探すようになります。 つまり、次のように変更しても動くようになります。
Alternative
|
1 |
= render view: '../shared/_something.html', locals: {something: true} |