1

次のように定義された単純なポリモーフィックコメントモデルがあります。

class Comment < ActiveRecord::Base
  include Rails.application.routes.url_helpers
  if Rails.env.production?
    default_url_options[:host] = "www.livesite.org"
  else  
    default_url_options[:host] = "livesite.dev"
  end

  attr_accessible :content
  attr_accessible :commentable_id, :commentable_type
  belongs_to :commentable, polymorphic: true
  belongs_to :user

  validates_presence_of :content

  after_create :subscribe_to, :notify_subscribers

  private

    def subscribe_to
      commentable.rdb[:subscribers].sadd user_id
    end

    def notify_subscribers
      subscriber_ids = commentable.rdb[:subscribers].smembers.to_a
      subscriber_ids.delete user_id.to_s
      # remove the author's id from the array
      subscribers = User.where(id: subscriber_ids)
      subscribers.each do |subscriber|
        subscriber.notifications.create(
          content:        "<a href='#{ user_url(user) }'>#{user.name}</a> commented about <a href='#{ polymorphic_url(commentable) }'>#{commentable.name}</a>",
          read:           false,
          notifyable:     commentable
        )
      end
    end

end

Redis のちょっとした魔法を使って、特定のコメント可能なサブスクライバーを多数作成していることがわかりますが、私の質問は、polymorphic_urlここでモデルの一部を抽象化するにはどうすればよいかということです。モデルレベルでそれを持っているのは奇妙に思えます。より良いアプローチはありますか?ここにあるということは、 を含める必要があることを意味url_helpersし、Capybara と連携して実際の palava をテストしています。

参考までに、Notification.rb は次のとおりです。

class Notification < ActiveRecord::Base
  attr_accessible :subject, :read, :user_id, :notifyable

  belongs_to :user
  belongs_to :notifyable, polymorphic: true

  default_scope order('created_at DESC')

end
4

2 に答える 2

1

その通知ロジックをサービス オブジェクトに移動できます (詳細はこちらを参照)。

- app
  - models
  - views
  - controllers
  - services # put service objects here

新しいサービス オブジェクトは、通知ロジックを実行する責任を単独で負います。少なくともコメント モデルを渡し、URL ヘルパーをインクルードまたは依存性注入する必要があります。

class CommentNotificationService
  def initialize(comment, url_provider)
    @comment, @url_provider = comment, url_provider
  end
end

次のようにコントローラーでインスタンス化します。

class CommentsController < ApplicationController
  def create
    comment = Comment.new params[:comment]
    service = CommentNotificationService.new comment, Rails.application.routes.url_helpers

    if comment.save
      service.do_the_work
    else
      ...
  end
end

サービスのdo_the_workメソッドでは、古いモデルのメソッドと同じことができますnotify_subscribers。依存性注入の部分は (特に私の書き方が) 最善ではありませんが、良い出発点です。モデルで行ったように、サービス オブジェクトに url_helpers を含めることができます。

サービス オブジェクト アプローチは、通知を行う必要があるという追加の責任を取り除くことで、モデルを無駄なくテストしやすいものにします。その後、通知ロジックを簡単にテストできます。

于 2013-07-01T16:34:42.930 に答える
0

これらの属性は、対応する環境ファイル (例: config/environments/development.rb)で設定する必要があります。

config.after_initialize do
  Rails.application.routes.default_url_options[:host] = 'livesite.dev'
end    

production.rb対応するホスト名を使用して、環境ファイルに対して同じことを行います。

于 2013-07-01T16:20:30.857 に答える