gist:moro/5652724 module Censorable extend ActiveSupport::Concern included do has_many :monitor_requests, as: :entity, validates :censor_status, inclusion: Censorable end module ClassMethods def censor_passed where(status: Censorable::PASSED_STATUSES) end end def censor_passed? censor_status.passed? end
✓ Users can tag the {question|answer}. ✓ Users can comment on the {question|answer}. ✓ Service providers must censor user- posted {question|answer}’s content.
class Question < AR::Base include Taggable include Commentable include Censorable # and question specific definitions.. end class Answer < AR::Base include Taggable include Commentable include Censorable # and question answer definitions.. end
# question and answers that the user has # /users/:user_id/questions # /users/:user_id/answers resources :users do resources :questions resources :answers end
module UsersResource extend ActiveSupport::Concern included do helper_method :owner hide_action :owner end private def owner @_owner ||= User.where(id: params[:user_id]).first end end
gist:moro/5652724 module Censorable extend ActiveSupport::Concern (skip) def feedback_monitor_judge(status) if PASSED_STATUSES.include?(status) .... else .... end end def request_monitoring! req = monitor_requests.create!(content: monitor res = post_monitor_request(req) unless res.code == '200' raise Censorable::MonitorRequestFailed.new(re end Bad case
gist:moro/5652724 class MonitorRequest < ActiveRecord::Base class << self def submit(entity) req = create!(entity: entity, content: monito res = post_monitor_request(req) unless res.code == '200' raise Censorable::MonitorRequestFailed.new( end end end end Good case
gist:moro/5652724 describe Censorable do let(:question) { create(:question) } before do question.request_monitoring! end specify do MonitoringRequest. should have(1).record end end Bad case
gist:moro/5652724 describe MonitoringRequest do let(:question) { create(:question) } before do MonitoringRequest.submit(question) end specify do MonitoringRequest. should have(1).record end end Good case
gist:moro/5652724 class MonitorRequest < ActiveRecord::Base class << self def monitoring_content(obj) case obj when Question [obj.title, obj.body].join("\n\n") when Answer entity.body end end end end Plain old conditional branch
gist:moro/5652724 class MonitorRequest < ActiveRecord::Base class << self def submit(entity) content = entity.monitoring_content ... class Question < AR::Base def monitoring_content [title, body].join("\n\n") end end class Answer < AR::Base def monitoring_content; body; end end Template method
“Refinements are intended to restrict the impact of monkey patching to a certain scope http://jp.rubyist.net/magazine/?Ruby200SpecialEn-refinement @shugomaeda says:
gist:moro/5652724 module Censorable module MonitoringContent refine Question do def monitoring_content [title, body].join("\n\n") end end refine Answer do def monitoring_content; body ; end end end end Refinements
Acknowledgements ✓ All of Ruby community: especially Ruby team , Rails team, RubyKaigi staffs and you. ✓ My clients, colleagues, friends and family. ✓ Nice material authors: ✓ http://good-wallpapers.com/misc/22337 ✓ http://www.fontspace.com/pete-klassen/ringbearer ✓ http://subtlepatterns.com/ ✓ http://www.flickr.com/photos/dailyinvention/23126614/ ✓ http://www.flickr.com/photos/bdamgaard/510134092/