2013-07-01 2 views
1

내가 가진 정의 간단한 다형성 코멘트 모델은 다음과 같습니다 당신은 내가의 숫자를 생성하기 위해 약간의 레디 스의 마법을 사용하여 볼 수 있습니다어떻게 모델의 URL을 리팩토링

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 

특정 commentable에 가입자지만, 내 질문은 어떻게 여기에 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 

답변

1

해당 알림 로직을 서비스 오브젝트 (read more here)로 이동할 수 있습니다.

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

새 서비스 객체 알림 로직을 수행에 대한 책임은 전적으로이 될 것입니다, 당신은 적어도 당신의 코멘트 모델에 전달하고 포함하거나 종속

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

이 그것을 인스턴스화하는 URL 도우미를 주입 할 필요가 당신은 이전 모델의 notify_subscribers 충족과 같은 작업을 수행 할 수 있습니다 서비스의 do_the_work 방법 이제

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 

: 같은 컨트롤러 벽돌 상자. 의존성 주입 부분은 최고가 아니며 (특별히 작성한 방법) 좋은 출발점입니다. 모델에서했던 것처럼 서비스 객체에 url_helpers를 포함시킬 수 있습니다.

서비스 개체 접근 방식은 알림을 수행해야하는 추가 책임을 제거하여 모델을 간결하고 쉽게 테스트 할 수있게합니다. 그런 다음 알림 논리를 쉽게 테스트 할 수 있습니다.

+0

서비스 객체로 이동하는 것은 좋은 생각입니다. 그러나이 작업을 시작했습니다. 그러나 서비스 객체에서'polymorphic_url'을 사용하지 않는다는 것을 어떻게 볼 수 있습니까? 이것은 내가 Capybara와 Selenium에서 여전히 같은 문제를 겪고 있음을 의미합니다. 테스트에서 실행중인 전체 도메인/포트를 항상 알 수는 없습니다. 어떤 충고? – idrysdale

+0

아, PinnyM이 말한 것을해야합니다. – DiegoSalazar

+0

Capybara가'capybara.server_port = 7787'을 사용하여 실행중인 포트를 지정하는 것을 끝내기 시작했습니다.이 포트는 test.rb에서 사용되었습니다. config.action_mailer.default_url_options = {: host => "127.0.0.1:7787"}' – idrysdale

0

이러한 속성 (예 : config/environments/development.rb) 해당 환경 파일에 설정해야합니다

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

production.rb 환경에 동일한 작업을 수행 파일을 해당 호스트 이름과 비교하십시오.