- object that inherits from that object that adds more functions, method, etc, to it
gem 'draper', '~> 1.3'
- generates the decorator for Campaign
bin/rails g decorator Campaign
- decorator will go to app/decorator folder
- initially, the file is generated as the following:
class CampaignDecorator < Draper::Decorator
delegate_all
# Define presentation-specific methods here. Helpers are accessed through
# `helpers` (aka `h`). You can override attributes, for example:
#
# def created_at
# helpers.content_tag :span, class: 'time' do
# object.created_at.strftime("%a %m/%d/%y")
# end
# end
end
- in order for decorator file to be loaded in rails console, add this to application.rb
config.autoload_paths << Rails.root.join("app", "decorators")
- go to rails console and type c = Campaign.last, then give c a decorator called d using:
2.2.3 :005 > d = c.decorate
- which will show:
#<Campaign:0x007ff2a06ab7e8> {
:id => 8,
:name => "Hello try reward",
:description => "hello",
:goal => 30,
:end_date => Tue, 15 Mar 2016 20:32:00 UTC +00:00,
:created_at => Tue, 15 Mar 2016 20:32:51 UTC +00:00,
:updated_at => Fri, 18 Mar 2016 20:47:31 UTC +00:00,
:user_id => nil,
:slug => "hello-try-reward",
:image => #<ImageUploader:0x007ff2a0681df8 @model=#<Campaign id: 8, name: "Hello try reward", description: "hello", goal: 30, end_date: "2016-03-15 20:32:00", created_at: "2016-03-15 20:32:51", updated_at: "2016-03-18 20:47:31", user_id: nil, slug: "hello-try-reward", image: nil, aasm_state: "funded", address: "142 W Hasting Street", longitude: -123.1086604, latitude: 49.2819605>, @mounted_as=:image>,
:aasm_state => "funded",
:address => "142 W Hasting Street",
:longitude => -123.1086604,
:latitude => 49.2819605
}
- in decorator file, put the following :
def name
object.name.titlelize
end
- then change the find campaign method in the controller:
def find_campaign
@campaign = Campaign.friendly.find(params[:id]).decorate
end
-
then remove all titlieze calls in the view
-
another example of deocrator feature is :
def goal
# `helpers` (aka `h`)
h.number_to_currency object.goal
end
- generate html tag
def state_label
h.content_tag :div, class:"label label-default" do
object.aasm_state
end
end
- then modify the show
<%= @campaign.state_label %>
<!-- <div class="label label-default">
<%= @campaign.aasm_state %>
</div> -->
- create a file "publish_campaign.rb" under app/services/campaigns
class Campaigns::PublishCampaign
# only call can be a public method
def call
end
end
- use a virtus gem to pass in param when creating object
gem "virtus"
- then the service file should be changed to:
class Campaigns::PublishCampaign
include Virtus.model
attribute :campaign, Campaign
# only call can be a public method
def call
end
end
- then implement the call function to handle the publish
def call
if campaign.publish!
DetermineCampaignStateJob.set(wait_until: campaign.end_date).perform_later(campaign)
true
else
false
end
end
- the create action in publish controller will look like this:
def create
campaign = current_user.campaigns.friendly.find params[:campaign_id]
service = Campaigns::PublishCampaign.new(campaign: campaign)
if service.call
redirect_to campaign, notice: "Published!"
else
redirect_to campaign, alert: "Can't publish! Published already?"
end
end
- give a service class called CreateCampaign
class Campaigns::CreateCampaign
include Virtus.model
attribute :params, Hash
attribute :user, User
# this is the campaign that gets created, we may need it for things such as rebuilding teh form with errors
attribute :campaign, Campaign
def call
@campaign = Campaign.new(params)
@campaign.user = user
@campaign.save
end
end
- adjust the controller create action
def create
service = Campaign::CreateCampaign.new(user: current_user, params: campaign_params)
if service.call
campaign = service.campaign
flash[:notice] = "campaign created"
redirect_to campaign_path(campaign)
else
build_associated_rewards
flash[:alert] = "campaign did not get created"
render :new
end
end