23341


もともとuser_helper.rbに記述していたメソッドを新しく作成したcareer_decorator.rbに移動したいのですが、undefined
method `term' for #のエラーがでます。  
いくら考えて、実行しても改善できないので質問させていただきました。  
以下は現状のコードです

career_decorator.rb (user_helper.rbから移動したコード)

[code]

    module CareerDecorator
    
      def term
        start_date = l(start_date, format: :term)
    
        if end_date.blank?
          "#{start_date} - #{t('date.formats.ongoing')}"
        else
          "#{start_date} - #{l(end_date, format: :term)}"
        end
      end
    
      def distance_of_term
        if end_date.blank?
          t('datetime.distance_in_words.ongoing')
        else
          distance_of_time_in_words(start_date, end_date)
        end
      end
    end
    
[/code]

app/views/users/user.html.slim

[code]

    @user.careers.order('start_date desc, end_date desc').each do |career|
      tr
        td
          p = link_to career.term, edit_user_career_path(user_id: @user, id: career)
          p = career.distance_of_term
          td = career.title
    
[/code]

user_helper.rb（もともとはこのファイルの以下のようなtermとdestance_of_termメソッドがあり、これをcareer_decorator.rbに移動したい）

[code]

    module UsersHelper
      def term(career)
        start_date = l(career.start_date, format: :term)
    
          if career.end_date.blank?
            "#{start_date} - #{t('date.formats.ongoing')}"
          else
            "#{start_date} - #{l(career.end_date, format: :term)}"
          end
        end
    
      def distance_of_term(career)
        if career.end_date.blank?
          t('datetime.distance_in_words.ongoing')
        else
          distance_of_time_in_words(career.start_date, career.end_date)
        end
      end
    end
    
[/code]

careerがtermメソッドを持っていないことはなんとなくわかっていますがどうしたら良いのかわかりません。

自分なりの考え

  * helperからdecoratorに該当メソッドを移動する時にコピペだけだとだめっぽい=>decoratorのメソッドを変更するのか
  * モデルのアソシエーション操作が必要なのか?
  * decorator.rbは手打ちではなくコマンドで作成しないといけないのか？？=> rails g decorator careerとやったらgem周りでエラーが出ました
  * careerオブジェクトがtermメソッドを持っていない
  * users_controller.rbのshowにcareerのインスタンスを作成する必要がありそう

ヒントいただければ幸いです。


CC BY-SA 3.0
2016-03-17T06:12:53.683
23216
2016-03-22T07:03:15.267
2016-03-17T06:40:38.250
76
14825
question
ruby-on-rails ruby
メソッドをhelperからdecoratorに移動すると undefined method `term' のエラーが発生する


ActiveDecoratorをお使いですか?  
<https://github.com/amatsuda/active_decorator>

ActiveDecoratorでは、以下の場合、自動でモデルにmoduleをmixinしてくれます。(READMEから引用しました)

>   1. automatically mixes decorator module into corresponding model only
> when:  
>  i. passing a model or collection of models or an instance of
> ActiveRecord::Relation from controllers to views  
>  ii. rendering partials with models (using :collection or :object or :locals
> explicitly or implicitly)
>

雑に訳すると以下のようなタイミングです。

i. モデル、もしくはActiveRecord::Relationのインスタンスをコントローラからviewに渡すとき  
ii. モデルをpartialに渡したとき

なので、コントローラの中で以下のようにインスタンス変数に入れてviewに渡すようにすると、1の動作になり、termメソッドが使えるようになると思います。

[code]

    @careers = @user.careers
    
[/code]

app/views/users/user.html.slim

[code]

    @careers.order('start_date desc, end_date desc').each do |career|
      tr
        td
          p = link_to career.term, edit_user_career_path(user_id: @user, id: career)
          p = career.distance_of_term
          td = career.title
    
[/code]


CC BY-SA 3.0
2016-03-17T14:07:31.020
23229
2016-03-17T14:07:31.020
2599
23216
answer


回答をしてくださった方々ありがとうございます。検索しながら行い、なんとか自力でエラー回避できましたので、参考になればと思い自分で回答させていただきます。  
今回の問題はDecoratorを呼び出せていなかったことだったのですが、以下のように記述することでエラー回避できるようになりました!

[code]

    @user.careers.order('start_date desc, end_date desc').each do|career| 
    p = link_to ActiveDecorator::Decorator.instance.decorate(career).term
[/code]

>
> ActiveDecorator::Decorator.instance.decorate(career).termとすることで、decoratorを適用させるよ‌​という役割になるそうです。


CC BY-SA 3.0
2016-03-22T06:52:29.513
23341
2016-03-22T07:03:15.267
2016-03-22T07:03:15.267
14825
14825
23216
answer