The document discusses using presenters to address issues that arise from complex MVC architectures. It notes that as projects grow more complex, controllers and views can become "bloated" despite best efforts. Presenters are proposed as a way to represent the current state of a view. They act as an interface between the controller and view, and encapsulate all the logic and data needed to render a view. An example presenter class for invoices is provided, which initializes from an invoice or invoice preview and provides methods to render parts of the invoice view. The presenter approach helps reduce complexity and keeps views simple by moving logic out of them.
iOS is a great platform to work on, and many developers have spend some time looking at the platform. This talk is aimed at programmers with prior iOS experience who want to get into iOS in more depth.
This presentation will take you from a basic level of understanding of iOS to look at advanced topics that will make you apps more polished, better designed and, ideally, more successful.
Abstract concepts are no use, so in this talk we'll take some existing successful commercial iOS applications as a case study, and see how a selection of iOS technologies and techniques combine within it.
On the way, we'll see:
* How to use Objective-C language facilities to their best advantage
* How to exploit key iOS technologies to save you time and effort
* iOS development idioms that will improve the quality of your code
* Creating "universal" iPhone/iPad/retina applications without going mad
* Successful deployment and testing strategies
Rails Conf 2014 Concerns, Decorators, Presenters, Service-objects, Helpers, H...Justin Gordon
Slides Ruby Conf 2014 on using simple techniques to create slimer, clearer models, controllers, and views in Ruby on Rails.
blog: http://www.railsonmaui.com
Code samples: https://github.com/justin808/fat-code-refactoring-techniques
iOS is a great platform to work on, and many developers have spend some time looking at the platform. This talk is aimed at programmers with prior iOS experience who want to get into iOS in more depth.
This presentation will take you from a basic level of understanding of iOS to look at advanced topics that will make you apps more polished, better designed and, ideally, more successful.
Abstract concepts are no use, so in this talk we'll take some existing successful commercial iOS applications as a case study, and see how a selection of iOS technologies and techniques combine within it.
On the way, we'll see:
* How to use Objective-C language facilities to their best advantage
* How to exploit key iOS technologies to save you time and effort
* iOS development idioms that will improve the quality of your code
* Creating "universal" iPhone/iPad/retina applications without going mad
* Successful deployment and testing strategies
Rails Conf 2014 Concerns, Decorators, Presenters, Service-objects, Helpers, H...Justin Gordon
Slides Ruby Conf 2014 on using simple techniques to create slimer, clearer models, controllers, and views in Ruby on Rails.
blog: http://www.railsonmaui.com
Code samples: https://github.com/justin808/fat-code-refactoring-techniques
Rails Antipatterns (http://www.amazon.com/Rails-AntiPatterns-Refactoring-Addison-Wesley-Professional/dp/0321604814) 를 읽고 몇 가지 정도만 요약을 해보았습니다.
레일즈를 시작한지 얼마 되지 않은터라 맞지 않는 부분이 있더라도 양해 부탁드려요 :)
As present at FluentConf 2014 on March 11th, 2014.
AngularJS is one of the most popular, and powerful, JavaScript frameworks for building rich client-side applications. AngularJS is both simultaneously both simple to use and extremely full featured. With AngularJS a little goes a long way, but to make the most of it, you need to know what you’re doing.
In this workshop we will build a complex application to help exercise all of the salient points of the AngularJS framework.
Topics covered include, ngResource, directives, fitlers, routing, templates, controllers, testing, and more.
Code can be found at: https://github.com/markbates/fluent-2014
Introduction to Magento 2 module development - PHP Antwerp Meetup 2017Joke Puts
This presentation was given at a PHP Antwerp Meetup: https://www.meetup.com/phpantwerp/events/237632633/
Magento 2 is a commerce platform released since November 2015. In this introduction I’ll focus on the open source version, Magento Community and show you how easy it is to start creating modules for this platform. These modules can be used to customize your store or to publish on the Magento Marketplace.
Presented at Big Android BBQ 2015
Hurst Convention Center, Hurst Texas
This talk will cover Fragments in detail by comparing and contrasting them to something we know well, Activities. We will also cover examples and use cases. Fragments: Why, How, and What For? is targeted toward developers who may not have had a lot of experience using Fragments and those who want to understand them better. Why did Google introduce Fragments? Aren’t Activities enough? How do Fragments work? What For? Example and use cases such as Fragment reuse, single pane vs multi-pane, ViewPager, NavigationDrawer and DialogFragment.
From Backbone to Ember and Back(bone) Againjonknapp
As a software consultant, I get to see a lot of interesting code. In this particular instance a client was in the process of transforming their web application to a rich, interactive interface with the help of another company.
The project kicked off using Backbone and things were great. Until they were not great. Pages starting getting more and more involved and blame started being thrown at the technology choice.
A move to Ember.js ensued and the app was rewritten. But architecturally bad decisions don't hide long, and soon the rewrite was preforming even worse. That's when I stepped in, with the help of another consultant, to solve the performance issues once and for all. Our solution used Backbone.js and it was fast. This is that journey.
With third party clients connecting to your service you may find that the assumptions or opinions of a typical rails application are not robust enough. We'll run through some key considerations when building an API that will be consumed by a mobile app.
A talk I gave at Mage Titans Italy 2018: http://www.magetitans.it/speakers/joke-puts/
How can you make Magento do what you want? In Magento 2 there are a lot of ways to add customizations. What are your options? Can you do a rewrite like in Magento 1? Should you use an event to add that business-critical logic when your invoice reaches state paid? Or is a plugin a better option? Maybe it’s the only option. What’s the deal with dependency injection and why do I need interfaces? In this talk we’re going to explore all the possibilities.
Building Large Web Applications That Are Easy to MaintainMarsBased
This presentation was for the Ironhack students in Barcelona by our CTO Xavier Redó. In this presentation, you will learn best practices of developing web applications that are easy to maintain, by ensuring code readability, scalability and other criteria you can benefit from in the long-term.
QA in DevOps Methodologies - a proposal integrating BDD+Selenium, and their integration with QA.
DevOps methodologies are not adverse to QA and more generally to V-Model. What I intend to do now is to offer you a different working method starting from a tool designed for software development and its use within our current work cycle.
In his public lecture, Christian Timmerer provides insights into the fascinating history of video streaming, starting from its humble beginnings before YouTube to the groundbreaking technologies that now dominate platforms like Netflix and ORF ON. Timmerer also presents provocative contributions of his own that have significantly influenced the industry. He concludes by looking at future challenges and invites the audience to join in a discussion.
State of ICS and IoT Cyber Threat Landscape Report 2024 previewPrayukth K V
The IoT and OT threat landscape report has been prepared by the Threat Research Team at Sectrio using data from Sectrio, cyber threat intelligence farming facilities spread across over 85 cities around the world. In addition, Sectrio also runs AI-based advanced threat and payload engagement facilities that serve as sinks to attract and engage sophisticated threat actors, and newer malware including new variants and latent threats that are at an earlier stage of development.
The latest edition of the OT/ICS and IoT security Threat Landscape Report 2024 also covers:
State of global ICS asset and network exposure
Sectoral targets and attacks as well as the cost of ransom
Global APT activity, AI usage, actor and tactic profiles, and implications
Rise in volumes of AI-powered cyberattacks
Major cyber events in 2024
Malware and malicious payload trends
Cyberattack types and targets
Vulnerability exploit attempts on CVEs
Attacks on counties – USA
Expansion of bot farms – how, where, and why
In-depth analysis of the cyber threat landscape across North America, South America, Europe, APAC, and the Middle East
Why are attacks on smart factories rising?
Cyber risk predictions
Axis of attacks – Europe
Systemic attacks in the Middle East
Download the full report from here:
https://sectrio.com/resources/ot-threat-landscape-reports/sectrio-releases-ot-ics-and-iot-security-threat-landscape-report-2024/
Rails Antipatterns (http://www.amazon.com/Rails-AntiPatterns-Refactoring-Addison-Wesley-Professional/dp/0321604814) 를 읽고 몇 가지 정도만 요약을 해보았습니다.
레일즈를 시작한지 얼마 되지 않은터라 맞지 않는 부분이 있더라도 양해 부탁드려요 :)
As present at FluentConf 2014 on March 11th, 2014.
AngularJS is one of the most popular, and powerful, JavaScript frameworks for building rich client-side applications. AngularJS is both simultaneously both simple to use and extremely full featured. With AngularJS a little goes a long way, but to make the most of it, you need to know what you’re doing.
In this workshop we will build a complex application to help exercise all of the salient points of the AngularJS framework.
Topics covered include, ngResource, directives, fitlers, routing, templates, controllers, testing, and more.
Code can be found at: https://github.com/markbates/fluent-2014
Introduction to Magento 2 module development - PHP Antwerp Meetup 2017Joke Puts
This presentation was given at a PHP Antwerp Meetup: https://www.meetup.com/phpantwerp/events/237632633/
Magento 2 is a commerce platform released since November 2015. In this introduction I’ll focus on the open source version, Magento Community and show you how easy it is to start creating modules for this platform. These modules can be used to customize your store or to publish on the Magento Marketplace.
Presented at Big Android BBQ 2015
Hurst Convention Center, Hurst Texas
This talk will cover Fragments in detail by comparing and contrasting them to something we know well, Activities. We will also cover examples and use cases. Fragments: Why, How, and What For? is targeted toward developers who may not have had a lot of experience using Fragments and those who want to understand them better. Why did Google introduce Fragments? Aren’t Activities enough? How do Fragments work? What For? Example and use cases such as Fragment reuse, single pane vs multi-pane, ViewPager, NavigationDrawer and DialogFragment.
From Backbone to Ember and Back(bone) Againjonknapp
As a software consultant, I get to see a lot of interesting code. In this particular instance a client was in the process of transforming their web application to a rich, interactive interface with the help of another company.
The project kicked off using Backbone and things were great. Until they were not great. Pages starting getting more and more involved and blame started being thrown at the technology choice.
A move to Ember.js ensued and the app was rewritten. But architecturally bad decisions don't hide long, and soon the rewrite was preforming even worse. That's when I stepped in, with the help of another consultant, to solve the performance issues once and for all. Our solution used Backbone.js and it was fast. This is that journey.
With third party clients connecting to your service you may find that the assumptions or opinions of a typical rails application are not robust enough. We'll run through some key considerations when building an API that will be consumed by a mobile app.
A talk I gave at Mage Titans Italy 2018: http://www.magetitans.it/speakers/joke-puts/
How can you make Magento do what you want? In Magento 2 there are a lot of ways to add customizations. What are your options? Can you do a rewrite like in Magento 1? Should you use an event to add that business-critical logic when your invoice reaches state paid? Or is a plugin a better option? Maybe it’s the only option. What’s the deal with dependency injection and why do I need interfaces? In this talk we’re going to explore all the possibilities.
Building Large Web Applications That Are Easy to MaintainMarsBased
This presentation was for the Ironhack students in Barcelona by our CTO Xavier Redó. In this presentation, you will learn best practices of developing web applications that are easy to maintain, by ensuring code readability, scalability and other criteria you can benefit from in the long-term.
QA in DevOps Methodologies - a proposal integrating BDD+Selenium, and their integration with QA.
DevOps methodologies are not adverse to QA and more generally to V-Model. What I intend to do now is to offer you a different working method starting from a tool designed for software development and its use within our current work cycle.
In his public lecture, Christian Timmerer provides insights into the fascinating history of video streaming, starting from its humble beginnings before YouTube to the groundbreaking technologies that now dominate platforms like Netflix and ORF ON. Timmerer also presents provocative contributions of his own that have significantly influenced the industry. He concludes by looking at future challenges and invites the audience to join in a discussion.
State of ICS and IoT Cyber Threat Landscape Report 2024 previewPrayukth K V
The IoT and OT threat landscape report has been prepared by the Threat Research Team at Sectrio using data from Sectrio, cyber threat intelligence farming facilities spread across over 85 cities around the world. In addition, Sectrio also runs AI-based advanced threat and payload engagement facilities that serve as sinks to attract and engage sophisticated threat actors, and newer malware including new variants and latent threats that are at an earlier stage of development.
The latest edition of the OT/ICS and IoT security Threat Landscape Report 2024 also covers:
State of global ICS asset and network exposure
Sectoral targets and attacks as well as the cost of ransom
Global APT activity, AI usage, actor and tactic profiles, and implications
Rise in volumes of AI-powered cyberattacks
Major cyber events in 2024
Malware and malicious payload trends
Cyberattack types and targets
Vulnerability exploit attempts on CVEs
Attacks on counties – USA
Expansion of bot farms – how, where, and why
In-depth analysis of the cyber threat landscape across North America, South America, Europe, APAC, and the Middle East
Why are attacks on smart factories rising?
Cyber risk predictions
Axis of attacks – Europe
Systemic attacks in the Middle East
Download the full report from here:
https://sectrio.com/resources/ot-threat-landscape-reports/sectrio-releases-ot-ics-and-iot-security-threat-landscape-report-2024/
Essentials of Automations: The Art of Triggers and Actions in FMESafe Software
In this second installment of our Essentials of Automations webinar series, we’ll explore the landscape of triggers and actions, guiding you through the nuances of authoring and adapting workspaces for seamless automations. Gain an understanding of the full spectrum of triggers and actions available in FME, empowering you to enhance your workspaces for efficient automation.
We’ll kick things off by showcasing the most commonly used event-based triggers, introducing you to various automation workflows like manual triggers, schedules, directory watchers, and more. Plus, see how these elements play out in real scenarios.
Whether you’re tweaking your current setup or building from the ground up, this session will arm you with the tools and insights needed to transform your FME usage into a powerhouse of productivity. Join us to discover effective strategies that simplify complex processes, enhancing your productivity and transforming your data management practices with FME. Let’s turn complexity into clarity and make your workspaces work wonders!
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfPaige Cruz
Monitoring and observability aren’t traditionally found in software curriculums and many of us cobble this knowledge together from whatever vendor or ecosystem we were first introduced to and whatever is a part of your current company’s observability stack.
While the dev and ops silo continues to crumble….many organizations still relegate monitoring & observability as the purview of ops, infra and SRE teams. This is a mistake - achieving a highly observable system requires collaboration up and down the stack.
I, a former op, would like to extend an invitation to all application developers to join the observability party will share these foundational concepts to build on:
Accelerate your Kubernetes clusters with Varnish CachingThijs Feryn
A presentation about the usage and availability of Varnish on Kubernetes. This talk explores the capabilities of Varnish caching and shows how to use the Varnish Helm chart to deploy it to Kubernetes.
This presentation was delivered at K8SUG Singapore. See https://feryn.eu/presentations/accelerate-your-kubernetes-clusters-with-varnish-caching-k8sug-singapore-28-2024 for more details.
Elevating Tactical DDD Patterns Through Object CalisthenicsDorra BARTAGUIZ
After immersing yourself in the blue book and its red counterpart, attending DDD-focused conferences, and applying tactical patterns, you're left with a crucial question: How do I ensure my design is effective? Tactical patterns within Domain-Driven Design (DDD) serve as guiding principles for creating clear and manageable domain models. However, achieving success with these patterns requires additional guidance. Interestingly, we've observed that a set of constraints initially designed for training purposes remarkably aligns with effective pattern implementation, offering a more ‘mechanical’ approach. Let's explore together how Object Calisthenics can elevate the design of your tactical DDD patterns, offering concrete help for those venturing into DDD for the first time!
DevOps and Testing slides at DASA ConnectKari Kakkonen
My and Rik Marselis slides at 30.5.2024 DASA Connect conference. We discuss about what is testing, then what is agile testing and finally what is Testing in DevOps. Finally we had lovely workshop with the participants trying to find out different ways to think about quality and testing in different parts of the DevOps infinity loop.
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdfPeter Spielvogel
Building better applications for business users with SAP Fiori.
• What is SAP Fiori and why it matters to you
• How a better user experience drives measurable business benefits
• How to get started with SAP Fiori today
• How SAP Fiori elements accelerates application development
• How SAP Build Code includes SAP Fiori tools and other generative artificial intelligence capabilities
• How SAP Fiori paves the way for using AI in SAP apps
Securing your Kubernetes cluster_ a step-by-step guide to success !KatiaHIMEUR1
Today, after several years of existence, an extremely active community and an ultra-dynamic ecosystem, Kubernetes has established itself as the de facto standard in container orchestration. Thanks to a wide range of managed services, it has never been so easy to set up a ready-to-use Kubernetes cluster.
However, this ease of use means that the subject of security in Kubernetes is often left for later, or even neglected. This exposes companies to significant risks.
In this talk, I'll show you step-by-step how to secure your Kubernetes cluster for greater peace of mind and reliability.
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionAggregage
Join Maher Hanafi, VP of Engineering at Betterworks, in this new session where he'll share a practical framework to transform Gen AI prototypes into impactful products! He'll delve into the complexities of data collection and management, model selection and optimization, and ensuring security, scalability, and responsible use.
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex ProofsAlex Pruden
This paper presents Reef, a system for generating publicly verifiable succinct non-interactive zero-knowledge proofs that a committed document matches or does not match a regular expression. We describe applications such as proving the strength of passwords, the provenance of email despite redactions, the validity of oblivious DNS queries, and the existence of mutations in DNA. Reef supports the Perl Compatible Regular Expression syntax, including wildcards, alternation, ranges, capture groups, Kleene star, negations, and lookarounds. Reef introduces a new type of automata, Skipping Alternating Finite Automata (SAFA), that skips irrelevant parts of a document when producing proofs without undermining soundness, and instantiates SAFA with a lookup argument. Our experimental evaluation confirms that Reef can generate proofs for documents with 32M characters; the proofs are small and cheap to verify (under a second).
Paper: https://eprint.iacr.org/2023/1886
2. Design Pattern?
Per our good friends at Wikipedia:
In software engineering, a design pattern is a general
reusable solution to a commonly occurring problem
within a given context in software design.
3. Design Pattern?
Per our good friends at Wikipedia:
In software engineering, a design pattern is a general
reusable solution to a commonly occurring problem
within a given context in software design.
Observer
4. Design Pattern?
Per our good friends at Wikipedia:
In software engineering, a design pattern is a general
reusable solution to a commonly occurring problem
within a given context in software design.
Observer
Factory
5. Design Pattern?
Per our good friends at Wikipedia:
In software engineering, a design pattern is a general
reusable solution to a commonly occurring problem
within a given context in software design.
Observer
Factory Bridge
6. Design Pattern?
Per our good friends at Wikipedia:
In software engineering, a design pattern is a general
reusable solution to a commonly occurring problem
within a given context in software design.
Observer
Factory Bridge
Singleton
7. Design Pattern?
Per our good friends at Wikipedia:
In software engineering, a design pattern is a general
reusable solution to a commonly occurring problem
within a given context in software design.
Observer
Factory Bridge
Singleton
Decorator
8. Design Pattern?
Per our good friends at Wikipedia:
In software engineering, a design pattern is a general
reusable solution to a commonly occurring problem
within a given context in software design.
Observer
Factory Bridge
Singleton
Visitor Decorator
9. Swell!
MVC! Note to any Microsoft
knuckleheads:
This is not a presentation on
“MVP.”
11. GOsh, What’s Wrong With
MVC?
As your project gets more complex, the
Controllers and Views become “bloated” despite
your best efforts.
12. GOsh, What’s Wrong With
MVC?
As your project gets more complex, the
Controllers and Views become “bloated” despite
your best efforts.
13. These are just the filters in CityEats’ Orders
Controller!
skip_before_filter :protect_private_environments, except: [:new]
before_filter :set_user,
only: [:new, :credit_user_account, :create, :iframe, :payment_form, :offer_details]
# Are all three of these filters necessary? It doesn't seem so at a glance. -Tim
before_filter :load_restaurant,
only: [:new, :create, :iframe, :credit_user_account, :payment_form, :offer_details],
:if => lambda { |c| params[:restaurant_id].present? }
before_filter :load_restaurant_and_authenticate,
only: [:new],
:if => lambda { |c| params[:restaurant_id].present? || params[:restaurant_offer_id].present? }
before_filter :load_offer_and_set_restaurant,
only: [:new, :credit_user_account, :create, :payment_form, :offer_details],
:if => lambda { |c| params[:restaurant_offer_id].present? }
before_filter :require_restaurant,
only: [:new]
before_filter :merge_request_ip_address,
only: [:create]
around_filter :load_restaurant_time_zone,
only: [:new, :show, :create, :destroy, :iframe, :payment_form, :credit_user_account]
before_filter :load_watched_video,
only: [:create]
before_filter :init_reservation,
only: [:new, :iframe, :payment_form, :credit_user_account, :create, :offer_details]
before_filter :init_order,
only: [:new, :iframe, :payment_form, :credit_user_account, :create, :offer_details]
before_filter :set_price,
only: [:new, :create, :credit_user_account, :payment_form]
before_filter :init_gateway_request_filter,
only: [:new, :credit_user_account, :payment_form]
14. AW SHUCKS, Actions
too! create action:
Here’s the OrdersController’s
def create
if params[:iframe]
@styling = @restaurant.try(:restaurant_widget_customization) ||
RestaurantWidgetCustomization.new(:restaurant_id => @restaurant.try(:id))
@styling.merge(params["restaurant_widget_customization"]) if params["restaurant_widget_customization"].present?
end
@order.group_emailable = params[:group_emailable]
@reservation.landing_tag = cookies['landing_tag'] if cookies['landing_tag'].present?
if @order.save
UserMailer.confirm_order(@order).deliver
@order.user.accept_current_terms_of_service!(request.remote_ip)
flash["ignore_order_is_conversion"] = true #this is used to render the conversion tracking pixel - naudo feb.6.2012
flash_message(:notice, 'Your order was successfully created.')
if @order.invite_facebook_friends_to_reservation? && current_user.present? && current_user.is_a_facebook_user?
render(:invite_on_facebook) and return
end
render(:iframe_confirm, layout: 'minimal') and return if params[:iframe]
cookies['landing_tag'] = nil
redirect_to @order
else
# Reverse any preauth and/or subscription
@gateway_transaction.reverse_authorization_and_or_subscription if @gateway_transaction.present?
render(:iframe, layout: 'minimal') and return if params[:iframe]
render :new, layout: choose_layout
end
end
15. AW SHUCKS, Actions
too! create action:
Here’s the OrdersController’s
def create
if params[:iframe]
@styling = @restaurant.try(:restaurant_widget_customization) ||
RestaurantWidgetCustomization.new(:restaurant_id => @restaurant.try(:id))
@styling.merge(params["restaurant_widget_customization"]) if params["restaurant_widget_customization"].present?
end
@order.group_emailable = params[:group_emailable]
@reservation.landing_tag = cookies['landing_tag'] if cookies['landing_tag'].present?
if @order.save
UserMailer.confirm_order(@order).deliver
@order.user.accept_current_terms_of_service!(request.remote_ip)
flash["ignore_order_is_conversion"] = true #this is used to render the conversion tracking pixel - naudo feb.6.2012
flash_message(:notice, 'Your order was successfully created.')
if @order.invite_facebook_friends_to_reservation? && current_user.present? && current_user.is_a_facebook_user?
render(:invite_on_facebook) and return
end
render(:iframe_confirm, layout: 'minimal') and return if params[:iframe]
cookies['landing_tag'] = nil
redirect_to @order
else
# Reverse any preauth and/or subscription
@gateway_transaction.reverse_authorization_and_or_subscription if @gateway_transaction.present?
render(:iframe, layout: 'minimal') and return if params[:iframe]
render :new, layout: choose_layout
end
end
26. Invoicing!
Scripps needed a
way to preview
Invoices that were to
be sent to
Restaurants, as well
as view existing
invoices
27. Invoice
class InvoicePresenter Presenter
attr_accessor :reservation_transactions, :non_reservation_transactions, :transactions, :id, :date, :due_date, :account,
:reservation_transactions_total, :restaurant
def initialize(thing)
self.restaurant = thing.account.accountable
self.transactions = thing.transactions
self.date = thing.date
self.account = thing.account
self.reservation_transactions = thing.reservation_transactions
self.non_reservation_transactions = thing.non_reservation_transactions
if thing.is_a? Invoice
init_from_invoice(thing)
elsif thing.is_a? InvoicePreview
init_from_invoice_preview(thing)
else
raise ArgumentError.new("I don't know what to do with this thing.")
end
end
.
.
.
private
def init_from_invoice(invoice)
self.id = invoice.id
self.due_date = invoice.due_date || self.date.end_of_month + Invoice::INVOICE_DAYS_AFTER
end
def init_from_invoice_preview(preview)
self.id = "PREVIEW"
invoiced_on_date = self.date < Date.today ? Date.today : self.date
due_date = invoiced_on_date + Invoice::INVOICE_DAYS_AFTER
self.due_date = due_date
end
end
28. Invoice
Presenter
def render_performance_summary(context)
by_source = {}
total = 0
reservation_transactions.each do |txn|
unless txn.source.nil? # how does this happen?
by_source[txn.source.reservation_source.name] =
by_source.fetch(txn.source.reservation_source.name,0) + 1
total = total + 1
end
end
context.render partial: 'invoice_performance_summary',
locals: {total: total, by_source: by_source}
end
29. Invoice
def render_line_items(context)
Presenter
Yeah, it can still be kinda gross...
output = []
# First, the one time fees.
one_time_fee_total = 0.0
one_time_fees.each do |otf|
amount = otf[:unit_price] * otf[:quantity]
item = {unit_price: otf[:unit_price], quantity: otf[:quantity], description: otf[:description], discount: 0.00, amount: amount}
one_time_fee_total = one_time_fee_total + amount
output << context.render(partial: 'invoice_item', locals: {item: item})
end
unless one_time_fees.empty?
output << context.render(partial: 'invoice_total', locals: {total: one_time_fee_total, description: 'One Time Fees Subtotal', cssclass: 'sub-total'})
end
# Next, the reservation transactions
reservation_fee_total = 0.0
grouped_reservation_transactions.each do |txn|
amount = txn[:unit_price] * txn[:quantity]
item = {unit_price: txn[:unit_price], quantity: txn[:quantity], description: txn[:description], discount: 0.00, amount: amount}
reservation_fee_total = reservation_fee_total + amount
output << context.render(partial: 'invoice_item', locals: {item: item})
end
unless grouped_reservation_transactions.empty?
output << context.render(partial: 'invoice_total', locals: {total: reservation_fee_total, description: 'Reservation Fees Fees Subtotal', cssclass: 'sub-total'})
end
unless monthly_fee_cap_amount.blank? || monthly_fee_cap_amount.zero?
output << context.render(partial: 'invoice_total', locals: {total: "After Monthly Fee Cap - #{number_to_currency monthly_fee_cap_amount}", description: 'Balance at the
end of last period', cssclass: 'monthly-cap'})
end
# Other Totals
output << context.render(partial: 'invoice_total', locals: {total: balance_at_end_of_last_period, description: 'Balance at the end of last period', cssclass: 'sub-total'})
output << context.render(partial: 'invoice_total', locals: {total: last_payment_received_amount, description: "Payment Received - #{last_payment_received_on} - Thank
You", cssclass: 'sub-total'})
output << context.render(partial: 'invoice_total', locals: {total: sales_tax, description: 'Tax', cssclass: 'tax'})
output << context.render(partial: 'invoice_total', locals: {total: reservation_fee_total + one_time_fee_total + sales_tax, description: 'Total', cssclass: 'total'})
output.join
end
30. Invoice
%section
%h4#invoice-header
Invoice
%h4#ce-logo
Presenter
%img{:alt => 'CityEats', :src => '/assets/logo-cityeats-black.png'}
#invoice-summary
%h4 Invoice Summary:
%table
%tr
But the view is
%th
Invoice Id:
%td= @presenter.id
outta site!
%tr#invoice-date
%th Invoice Date:
%td= @presenter.date
%tr#due-date
%th Due Date:
%td= @presenter.due_date
%tr#amount-due
%th
Amount Due:
%td= number_to_currency(@presenter.amount_due)
#bill-to
%h4 Bill To:
= render partial: 'invoice_bill_to_address', locals: {name: @presenter.restaurant.name, address: @presenter.restaurant.address}
%h4 Remittance
%p The amount owing will automatically be charged to your credit card or debited from your bank account, according to the terms of your contract. <br /><em>If paying by check, please
include a copy of this statement.</em>
%h4 Fee Summary
%table#fee-summary
%tr
Gosh, no references to
%th Description
%th.quantity Quantity
%th.unit-price Unit Price
%th.discount Discount
models anywhere!
%th.amount Amount
= raw @presenter.render_line_items(self)
%h4 Performance Summary
= raw @presenter.render_performance_summary(self)
= javascript_include_tag "invoicing"
31. ...and the controller is tiny, too!
def show
invoice = Invoice.find(params[:id])
@presenter = InvoicePresenter.new(invoice)
end
def new
account = @restaurant.account
invoice_date = @restaurant.next_invoice_date
@presenter = InvoicePresenter.new(InvoicePreview.new(account, invoice_date))
end
49. Decorator Pattern?
SimpleDelegator
Model Exhibitor
+initializer(a_model: Model)
+render_body(context:View)
50. Exhibitor Pattern
Uses “Decorator Pattern” to extend an
existing model
Implements Decorator Pattern using
Ruby’s SimpleDelegator class
# exhibits/text_post_exhibit.rb
require 'delegate'
class TextPostExhibit < SimpleDelegator
def initialize(model, context)
@context = context
super(model)
end
def render_body
@context.render(partial: "/posts/text_body", locals: {post: self})
end
end
51. some People in the rails
Community conflate these
two notions (exhibitor vs.
presenter)
But now you’re smarter
than all of them!
53. FURTHER Reading
http://blog.jayfields.com/2007/03/rails-presenter-pattern.html
Simple one, does some similar stuff w/ delegation like Avdi without using
SimpleDelagator
http://broadcastingadam.com/2011/06/present_yourself/
Does some neat stuff with memoization
http://railsvideos.net/railsconf-2012-presenters-and-decorators-a-co
Very Good RailsConf 2012 Presentation by Mike Moore. Uses
ActiveDecorator to implement a form of Exhibitor
54. Quest ions?
Retro Clip Art Provided By Tack-o-Rama
http://tackorama.net