SlideShare a Scribd company logo
WHY LIFE WITH RUBY ON RAILS BECOMES
SO HARD AFTER FEW MONTHS OF DEVELOPMENT?
IVAN NEMYTCHENKO
IVAN NEMYTCHENKO
> 14 years in IT
> cofounded 2 IT-companies
> occasional speaker
> coorganized 2 HappyDev conferences
> worked in a startup
> worked as project-manager
> working with Rails since 2006
> author of RailsHurts.com
> internship for ruby junior developers:
SkillGrid
> twitter: @inem
WHAT IS WRONG
WITH RAILS?
SAME PATTERN
RAILSHURTS.COM/MESS
RAILS-WAY IS NOT
ENOUGH
RAILS WORLD is so cool
that we don't even have whole class of problems
millions of java programmers
struggring every day
THESE THINGS MIGHT HELP YOU
> SOLID principles
> Design Patterns
> Refactoring techniques
> Architecture types
> Code smells identification
> Best practices of testing
PRINCIPLES.
MISUNDERSTOOD.
APPLIED.
DRY
«DON'T REPEAT YOURSELF»
RAILSHURTS.COM/_DRY
JUST AVOID DUPLICATION, RIGHT?
EVERYTHING
HAS ITS PRICE
PRICE: MORE RELATIONS
«Duplication is far cheaper that
wrong abstraction»
— Sandi Metz
KISS
«KEEP IT SIMPLE, STUPID»
RAILSHURTS.COM/_KISS
RAILS IS SIMPLE, RIGHT?
ACTIVERECORD
class User < ActiveRecord::Base
end
ACTIVERECORD
ACTIVERECORD
> input data coercion
> setting default values
> input data validation
> interaction with the database
> handling nested structures
> callbacks (before_save, etc...)
- WHY SHOULD I CARE?
Polymorphic STI model which belongs to another
polymorphic model through third model, which also has
some valuable JSON data stored in Postgres using
hstore.
WHAT ARE YOU GONNA DO?
> reorganize associations
> become Rails core contributor
IT IS GOING TO
BE PAINFUL
PAINFUL BECAUSE OF THE
COMPLEXITY
RAILS IS NOT SIMPLE. IT IS CONVENIENT.
FAT MODEL,
SKINNY CONTROLLER
RAILSHURTS.COM/_SKINNY
RIGHT PROBLEM IDENTIFIED
BUT IT IS ONLY PART OF THE PROBLEM
YOU SHOULD HAVE NO FAT CLASSES AT ALL
*HINT:
PROPER SOLUTION
REQUIRES THINKING
OUT OF MVC BOX
RAILS
IS NOT YOUR
APPLICATIONRAILSHURTS.COM/_APP
It just doesn't make sense.
Here's my Rails application.
Here's app folder. What's wrong?
RAILSHURTS.COM/_CLEAN
HEXXAGONAL ARCHITECTURE
RAILSHURTS.COM/_HEXX
YAGNI«YOU AREN'T GONNA NEED IT»
RAILSHURTS.COM/_YAGNI
WHAT IF YOUR APP
DOESN'T NEED PERSISTANCE YET?
WHAT IF YOUR APP CORE
DOESN'T NEED WEB FRAMEWORK YET?
«Question everything generally
thought to be obvious»
— Dieter Rams
THREE RULES FOR DEVELOPERS
WHO ARE NOT SURE OF ONE'S STRENGTH
> Do not apply DRY principle too early
> Remember about Single Responsibility Principle
> Learn how to apply Design Patterns
LET'S GET OUR HANDS DIRTY!
FEATURE #1: USERS REGISTRATION
FEATURE #1: USERS REGISTRATION
SINGLE TABLE
INHERITANCE !
 
CONDITIONAL
VALIDATIONS !
BOTH STI AND CONDITIONAL
VALIDATIONS ARE JUST WORKAROUNDS
THE PROBLEM IS DEEPER!
SINGE RESPONSIBILITY PRINCIPLE:
A CLASS SHOULD HAVE
ONLY ONE REASON TO
CHANGE
OUR MODEL KNOWS ABOUT HOW..
> admin form is validated
> org_user form is validated
> guest_user form is validated
> user data is saved
FORM OBJECT !
  
COOKING FORM OBJECT (STEP 1)
class Person
attr_accessor :first_name, :last_name
def initialize(first_name, last_name)
@first_name, @last_name = first_name, last_name
end
end
COOKING FORM OBJECT (STEP 2)
class Person
attr_accessor :first_name, :last_name
def initialize(first_name, last_name)
@first_name, @last_name = first_name, last_name
end
include ActiveModel::Validations
validates_presence_of :first_name, :last_name
end
COOKING FORM OBJECT (STEP 3)
class Person
include Virtus.model
attribute :first_name, String
attribute :last_name, String
include ActiveModel::Validations
validates_presence_of :first_name, :last_name
end
FORM OBJECT
class OrgUserInput
include Virtus.model
include ActiveModel::Validations
attribute :login, String
attribute :password, String
attribute :password_confirmation, String
attribute :organization_id, Integer
validates_presence_of :login, :password, :password_confirmation
validates_numericality_of :organization_id
end
USING FORM OBJECT
def create
input = OrgUserInput.new(params)
if input.valid?
@user = User.create(input.to_hash)
else
#...
end
end
FOUR SIMPLE OBJECTS
INSTEAD OF ONE COMPLEX
FEATURE #2: BONUSCODE REDEEM
def redeem
unless bonuscode = Bonuscode.find_by_hash(params[:code])
render json: {error: 'Bonuscode not found'}, status: 404 and return
end
if bonuscode.used?
render json: {error: 'Bonuscode is already used'}, status: 404 and return
end
unless recipient = User.find_by_id(params[:receptor_id])
render json: {error: 'Recipient not found'}, status: 404 and return
end
ActiveRecord::Base.transaction do
amount = bonuscode.mark_as_used!(params[:receptor_id])
recipient.increase_balance!(amount)
if recipient.save && bonuscode.save
render json: {balance: recipient.balance}, status: 200
else
render json: {error: 'Error during transaction'}, status: 500
end
end
end
SINGLE
RESPONSIBILITY
PRINCIPLE
bonuscode.redeem_by(user)
OR
user.redeem_bonus(code)
?
SERVICE OBJECT!
(USE CASE, INTERACTOR)
  
COOKING SERVICE OBJECT (STEP 1)
class RedeemBonuscode
def redeem
unless bonuscode = Bonuscode.find_by_hash(params[:code])
render json: {error: 'Bonuscode not found'}, status: 404 and return
end
if bonuscode.used?
render json: {error: 'Bonuscode is already used'}, status: 404 and return
end
unless recipient = User.find_by_id(params[:receptor_id])
render json: {error: 'Recipient not found'}, status: 404 and return
end
ActiveRecord::Base.transaction do
amount = bonuscode.mark_as_used!(params[:receptor_id])
recipient.increase_balance!(amount)
if recipient.save && bonuscode.save
render json: {balance: recipient.balance}, status: 200
else
render json: {error: 'Error during transaction'}, status: 500
end
end
end
end
COOKING SERVICE OBJECT (STEP 2)
class RedeemBonuscode
def run!(params)
unless bonuscode = Bonuscode.find_by_hash(params[:code])
raise BonuscodeNotFound.new
end
if bonuscode.used?
raise BonuscodeIsAlreadyUsed.new
end
unless recipient = User.find_by_id(params[:receptor_id])
raise RecipientNotFound.new
end
ActiveRecord::Base.transaction do
amount = bonuscode.mark_as_used!(params[:receptor_id])
recipient.increase_balance!(amount)
recipient.save! && bonuscode.save!
end
recipient.balance
end
end
  
  
  
COOKING SERVICE OBJECT (STEP 3)
def redeem
use_case = RedeemBonuscode.new
begin
recipient_balance = use_case.run!(params)
rescue BonuscodeNotFound, BonuscodeIsAlreadyUsed, RecipientNotFound => ex
render json: {error: ex.message}, status: 404 and return
rescue TransactionError => ex
render json: {error: ex.message}, status: 500 and return
end
render json: {balance: recipient_balance}
end
BUSINESS LOGIC /
CONTROLLER SEPARATION
7 Patterns to Refactor Fat ActiveRecord Models
railshurts.com/_7ways
* * *
Arkency
railshurts.com/_arkency
* * *
Adam Hawkins
railshurts.com/_hawkins

More Related Content

What's hot

Hassliebe Onlineformulare, Enhance your Form for better UX
Hassliebe Onlineformulare, Enhance your Form for better UXHassliebe Onlineformulare, Enhance your Form for better UX
Hassliebe Onlineformulare, Enhance your Form for better UX
Peter Rozek
 
Erica Scales PPP_Final
Erica Scales PPP_FinalErica Scales PPP_Final
Erica Scales PPP_Final
senate25
 
Vmware
Vmware Vmware
Vmware
sumit007c
 
Part 2: Intermediate Designing for Multiple Devices - GA London, 31 Jul 2013
Part 2: Intermediate Designing for Multiple Devices - GA London, 31 Jul 2013Part 2: Intermediate Designing for Multiple Devices - GA London, 31 Jul 2013
Part 2: Intermediate Designing for Multiple Devices - GA London, 31 Jul 2013
Anna Dahlström
 
Ruby & Python with Silverlight O RLY? YA RLY!
Ruby & Python with Silverlight O RLY? YA RLY!Ruby & Python with Silverlight O RLY? YA RLY!
Ruby & Python with Silverlight O RLY? YA RLY!
Martha Rotter
 
Smart app banners
Smart app bannersSmart app banners
Smart app banners
CocoaHeads France
 
Reyrey pecha kucha
Reyrey pecha kucha Reyrey pecha kucha
Reyrey pecha kucha
maiterey
 

What's hot (7)

Hassliebe Onlineformulare, Enhance your Form for better UX
Hassliebe Onlineformulare, Enhance your Form for better UXHassliebe Onlineformulare, Enhance your Form for better UX
Hassliebe Onlineformulare, Enhance your Form for better UX
 
Erica Scales PPP_Final
Erica Scales PPP_FinalErica Scales PPP_Final
Erica Scales PPP_Final
 
Vmware
Vmware Vmware
Vmware
 
Part 2: Intermediate Designing for Multiple Devices - GA London, 31 Jul 2013
Part 2: Intermediate Designing for Multiple Devices - GA London, 31 Jul 2013Part 2: Intermediate Designing for Multiple Devices - GA London, 31 Jul 2013
Part 2: Intermediate Designing for Multiple Devices - GA London, 31 Jul 2013
 
Ruby & Python with Silverlight O RLY? YA RLY!
Ruby & Python with Silverlight O RLY? YA RLY!Ruby & Python with Silverlight O RLY? YA RLY!
Ruby & Python with Silverlight O RLY? YA RLY!
 
Smart app banners
Smart app bannersSmart app banners
Smart app banners
 
Reyrey pecha kucha
Reyrey pecha kucha Reyrey pecha kucha
Reyrey pecha kucha
 

Similar to How to stop being Rails Developer

StartupDecode - Meetup #00
StartupDecode - Meetup #00StartupDecode - Meetup #00
StartupDecode - Meetup #00
Amine Sadry
 
Stripes RJUG March 2012
Stripes RJUG March 2012Stripes RJUG March 2012
Stripes RJUG March 2012
timstone
 
Droidcon Paris: The new Android SDK
Droidcon Paris: The new Android SDKDroidcon Paris: The new Android SDK
Droidcon Paris: The new Android SDK
PayPal
 
Legacy Code: Evolve or Rewrite?
Legacy Code: Evolve or Rewrite?Legacy Code: Evolve or Rewrite?
Legacy Code: Evolve or Rewrite?
Cyrille Martraire
 
Ruby For Startups
Ruby For StartupsRuby For Startups
Ruby For Startups
Mike Subelsky
 
Let's do SPA
Let's do SPALet's do SPA
Let's do SPA
Marek Piasecki
 
Building Mobile Friendly APIs in Rails
Building Mobile Friendly APIs in RailsBuilding Mobile Friendly APIs in Rails
Building Mobile Friendly APIs in Rails
Jim Jeffers
 
Component driven development: How to guide
Component driven development: How to guideComponent driven development: How to guide
Component driven development: How to guide
Nikolay Kozhukharenko
 
Backbone.js – an introduction
Backbone.js – an introductionBackbone.js – an introduction
Backbone.js – an introduction
bobbyroe
 
Intro To Node.js
Intro To Node.jsIntro To Node.js
Intro To Node.js
Chris Cowan
 
Building a Single Page Application using Ember.js ... for fun and profit
Building a Single Page Application using Ember.js ... for fun and profitBuilding a Single Page Application using Ember.js ... for fun and profit
Building a Single Page Application using Ember.js ... for fun and profit
Ben Limmer
 
Redux at scale
Redux at scaleRedux at scale
Redux at scale
inovia
 
10 tips for Redux at scale
10 tips for Redux at scale10 tips for Redux at scale
10 tips for Redux at scale
inovia
 
Introduction to Using PHP & MVC Frameworks
Introduction to Using PHP & MVC FrameworksIntroduction to Using PHP & MVC Frameworks
Introduction to Using PHP & MVC Frameworks
Gerald Krishnan
 
Nikolay Kozhukharenko ''Component driven development how to guide''
Nikolay Kozhukharenko ''Component driven development how to guide''Nikolay Kozhukharenko ''Component driven development how to guide''
Nikolay Kozhukharenko ''Component driven development how to guide''
OdessaJS Conf
 
The State of Front-end At CrowdTwist
The State of Front-end At CrowdTwistThe State of Front-end At CrowdTwist
The State of Front-end At CrowdTwist
Mark Fayngersh
 
Meteor.js Workshop by Dopravo
Meteor.js Workshop by DopravoMeteor.js Workshop by Dopravo
Meteor.js Workshop by Dopravo
ArabNet ME
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on Rails
Diki Andeas
 
How to Build a Micro-Application using Single-Spa
How to Build a Micro-Application using Single-SpaHow to Build a Micro-Application using Single-Spa
How to Build a Micro-Application using Single-Spa
RapidValue
 
RoR 101: Session 5
RoR 101: Session 5RoR 101: Session 5
RoR 101: Session 5
Rory Gianni
 

Similar to How to stop being Rails Developer (20)

StartupDecode - Meetup #00
StartupDecode - Meetup #00StartupDecode - Meetup #00
StartupDecode - Meetup #00
 
Stripes RJUG March 2012
Stripes RJUG March 2012Stripes RJUG March 2012
Stripes RJUG March 2012
 
Droidcon Paris: The new Android SDK
Droidcon Paris: The new Android SDKDroidcon Paris: The new Android SDK
Droidcon Paris: The new Android SDK
 
Legacy Code: Evolve or Rewrite?
Legacy Code: Evolve or Rewrite?Legacy Code: Evolve or Rewrite?
Legacy Code: Evolve or Rewrite?
 
Ruby For Startups
Ruby For StartupsRuby For Startups
Ruby For Startups
 
Let's do SPA
Let's do SPALet's do SPA
Let's do SPA
 
Building Mobile Friendly APIs in Rails
Building Mobile Friendly APIs in RailsBuilding Mobile Friendly APIs in Rails
Building Mobile Friendly APIs in Rails
 
Component driven development: How to guide
Component driven development: How to guideComponent driven development: How to guide
Component driven development: How to guide
 
Backbone.js – an introduction
Backbone.js – an introductionBackbone.js – an introduction
Backbone.js – an introduction
 
Intro To Node.js
Intro To Node.jsIntro To Node.js
Intro To Node.js
 
Building a Single Page Application using Ember.js ... for fun and profit
Building a Single Page Application using Ember.js ... for fun and profitBuilding a Single Page Application using Ember.js ... for fun and profit
Building a Single Page Application using Ember.js ... for fun and profit
 
Redux at scale
Redux at scaleRedux at scale
Redux at scale
 
10 tips for Redux at scale
10 tips for Redux at scale10 tips for Redux at scale
10 tips for Redux at scale
 
Introduction to Using PHP & MVC Frameworks
Introduction to Using PHP & MVC FrameworksIntroduction to Using PHP & MVC Frameworks
Introduction to Using PHP & MVC Frameworks
 
Nikolay Kozhukharenko ''Component driven development how to guide''
Nikolay Kozhukharenko ''Component driven development how to guide''Nikolay Kozhukharenko ''Component driven development how to guide''
Nikolay Kozhukharenko ''Component driven development how to guide''
 
The State of Front-end At CrowdTwist
The State of Front-end At CrowdTwistThe State of Front-end At CrowdTwist
The State of Front-end At CrowdTwist
 
Meteor.js Workshop by Dopravo
Meteor.js Workshop by DopravoMeteor.js Workshop by Dopravo
Meteor.js Workshop by Dopravo
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on Rails
 
How to Build a Micro-Application using Single-Spa
How to Build a Micro-Application using Single-SpaHow to Build a Micro-Application using Single-Spa
How to Build a Micro-Application using Single-Spa
 
RoR 101: Session 5
RoR 101: Session 5RoR 101: Session 5
RoR 101: Session 5
 

More from Ivan Nemytchenko

Breaking Bad Habits with GitLab CI
Breaking Bad Habits with GitLab CIBreaking Bad Habits with GitLab CI
Breaking Bad Habits with GitLab CI
Ivan Nemytchenko
 
What I Have Learned from Organizing Remote Internship for Ruby developers
What I Have Learned from Organizing Remote Internship for Ruby developersWhat I Have Learned from Organizing Remote Internship for Ruby developers
What I Have Learned from Organizing Remote Internship for Ruby developers
Ivan Nemytchenko
 
Breaking bad habits with GitLab CI
Breaking bad habits with GitLab CIBreaking bad habits with GitLab CI
Breaking bad habits with GitLab CI
Ivan Nemytchenko
 
Lean Poker in Lviv announce
Lean Poker in Lviv announceLean Poker in Lviv announce
Lean Poker in Lviv announce
Ivan Nemytchenko
 
How to use any static site generator with GitLab Pages.
How to use any static site generator with GitLab Pages. How to use any static site generator with GitLab Pages.
How to use any static site generator with GitLab Pages.
Ivan Nemytchenko
 
Опыт организации удаленной стажировки для рубистов
Опыт организации удаленной стажировки для рубистовОпыт организации удаленной стажировки для рубистов
Опыт организации удаленной стажировки для рубистов
Ivan Nemytchenko
 
Principles. Misunderstood. Applied
Principles. Misunderstood. AppliedPrinciples. Misunderstood. Applied
Principles. Misunderstood. Applied
Ivan Nemytchenko
 
From Rails-way to modular architecture
From Rails-way to modular architectureFrom Rails-way to modular architecture
From Rails-way to modular architecture
Ivan Nemytchenko
 
Рассказ про RedDotRubyConf 2014
Рассказ про RedDotRubyConf 2014Рассказ про RedDotRubyConf 2014
Рассказ про RedDotRubyConf 2014
Ivan Nemytchenko
 
Рефакторинг rails-приложения. С чего начать?
Рефакторинг rails-приложения. С чего начать?Рефакторинг rails-приложения. С чего начать?
Рефакторинг rails-приложения. С чего начать?Ivan Nemytchenko
 
Different approaches to ruby web applications architecture
Different approaches to ruby web applications architectureDifferent approaches to ruby web applications architecture
Different approaches to ruby web applications architecture
Ivan Nemytchenko
 
От Rails-way к модульной архитектуре
От Rails-way к модульной архитектуреОт Rails-way к модульной архитектуре
От Rails-way к модульной архитектуре
Ivan Nemytchenko
 
ActiveRecord vs Mongoid
ActiveRecord vs MongoidActiveRecord vs Mongoid
ActiveRecord vs Mongoid
Ivan Nemytchenko
 
Coffescript - счастье для javascript-разработчика
Coffescript - счастье для javascript-разработчикаCoffescript - счастье для javascript-разработчика
Coffescript - счастье для javascript-разработчикаIvan Nemytchenko
 
Tequila - язык для продвинутой генерации JSON
Tequila - язык для продвинутой генерации JSONTequila - язык для продвинутой генерации JSON
Tequila - язык для продвинутой генерации JSONIvan Nemytchenko
 

More from Ivan Nemytchenko (15)

Breaking Bad Habits with GitLab CI
Breaking Bad Habits with GitLab CIBreaking Bad Habits with GitLab CI
Breaking Bad Habits with GitLab CI
 
What I Have Learned from Organizing Remote Internship for Ruby developers
What I Have Learned from Organizing Remote Internship for Ruby developersWhat I Have Learned from Organizing Remote Internship for Ruby developers
What I Have Learned from Organizing Remote Internship for Ruby developers
 
Breaking bad habits with GitLab CI
Breaking bad habits with GitLab CIBreaking bad habits with GitLab CI
Breaking bad habits with GitLab CI
 
Lean Poker in Lviv announce
Lean Poker in Lviv announceLean Poker in Lviv announce
Lean Poker in Lviv announce
 
How to use any static site generator with GitLab Pages.
How to use any static site generator with GitLab Pages. How to use any static site generator with GitLab Pages.
How to use any static site generator with GitLab Pages.
 
Опыт организации удаленной стажировки для рубистов
Опыт организации удаленной стажировки для рубистовОпыт организации удаленной стажировки для рубистов
Опыт организации удаленной стажировки для рубистов
 
Principles. Misunderstood. Applied
Principles. Misunderstood. AppliedPrinciples. Misunderstood. Applied
Principles. Misunderstood. Applied
 
From Rails-way to modular architecture
From Rails-way to modular architectureFrom Rails-way to modular architecture
From Rails-way to modular architecture
 
Рассказ про RedDotRubyConf 2014
Рассказ про RedDotRubyConf 2014Рассказ про RedDotRubyConf 2014
Рассказ про RedDotRubyConf 2014
 
Рефакторинг rails-приложения. С чего начать?
Рефакторинг rails-приложения. С чего начать?Рефакторинг rails-приложения. С чего начать?
Рефакторинг rails-приложения. С чего начать?
 
Different approaches to ruby web applications architecture
Different approaches to ruby web applications architectureDifferent approaches to ruby web applications architecture
Different approaches to ruby web applications architecture
 
От Rails-way к модульной архитектуре
От Rails-way к модульной архитектуреОт Rails-way к модульной архитектуре
От Rails-way к модульной архитектуре
 
ActiveRecord vs Mongoid
ActiveRecord vs MongoidActiveRecord vs Mongoid
ActiveRecord vs Mongoid
 
Coffescript - счастье для javascript-разработчика
Coffescript - счастье для javascript-разработчикаCoffescript - счастье для javascript-разработчика
Coffescript - счастье для javascript-разработчика
 
Tequila - язык для продвинутой генерации JSON
Tequila - язык для продвинутой генерации JSONTequila - язык для продвинутой генерации JSON
Tequila - язык для продвинутой генерации JSON
 

Recently uploaded

办理毕业证(NYU毕业证)纽约大学毕业证成绩单官方原版办理
办理毕业证(NYU毕业证)纽约大学毕业证成绩单官方原版办理办理毕业证(NYU毕业证)纽约大学毕业证成绩单官方原版办理
办理毕业证(NYU毕业证)纽约大学毕业证成绩单官方原版办理
uehowe
 
成绩单ps(UST毕业证)圣托马斯大学毕业证成绩单快速办理
成绩单ps(UST毕业证)圣托马斯大学毕业证成绩单快速办理成绩单ps(UST毕业证)圣托马斯大学毕业证成绩单快速办理
成绩单ps(UST毕业证)圣托马斯大学毕业证成绩单快速办理
ysasp1
 
Should Repositories Participate in the Fediverse?
Should Repositories Participate in the Fediverse?Should Repositories Participate in the Fediverse?
Should Repositories Participate in the Fediverse?
Paul Walk
 
存档可查的(USC毕业证)南加利福尼亚大学毕业证成绩单制做办理
存档可查的(USC毕业证)南加利福尼亚大学毕业证成绩单制做办理存档可查的(USC毕业证)南加利福尼亚大学毕业证成绩单制做办理
存档可查的(USC毕业证)南加利福尼亚大学毕业证成绩单制做办理
fovkoyb
 
国外证书(Lincoln毕业证)新西兰林肯大学毕业证成绩单不能毕业办理
国外证书(Lincoln毕业证)新西兰林肯大学毕业证成绩单不能毕业办理国外证书(Lincoln毕业证)新西兰林肯大学毕业证成绩单不能毕业办理
国外证书(Lincoln毕业证)新西兰林肯大学毕业证成绩单不能毕业办理
zoowe
 
留学学历(UoA毕业证)奥克兰大学毕业证成绩单官方原版办理
留学学历(UoA毕业证)奥克兰大学毕业证成绩单官方原版办理留学学历(UoA毕业证)奥克兰大学毕业证成绩单官方原版办理
留学学历(UoA毕业证)奥克兰大学毕业证成绩单官方原版办理
bseovas
 
一比一原版(USYD毕业证)悉尼大学毕业证如何办理
一比一原版(USYD毕业证)悉尼大学毕业证如何办理一比一原版(USYD毕业证)悉尼大学毕业证如何办理
一比一原版(USYD毕业证)悉尼大学毕业证如何办理
k4ncd0z
 
办理毕业证(UPenn毕业证)宾夕法尼亚大学毕业证成绩单快速办理
办理毕业证(UPenn毕业证)宾夕法尼亚大学毕业证成绩单快速办理办理毕业证(UPenn毕业证)宾夕法尼亚大学毕业证成绩单快速办理
办理毕业证(UPenn毕业证)宾夕法尼亚大学毕业证成绩单快速办理
uehowe
 
Design Thinking NETFLIX using all techniques.pptx
Design Thinking NETFLIX using all techniques.pptxDesign Thinking NETFLIX using all techniques.pptx
Design Thinking NETFLIX using all techniques.pptx
saathvikreddy2003
 
Discover the benefits of outsourcing SEO to India
Discover the benefits of outsourcing SEO to IndiaDiscover the benefits of outsourcing SEO to India
Discover the benefits of outsourcing SEO to India
davidjhones387
 
制作毕业证书(ANU毕业证)莫纳什大学毕业证成绩单官方原版办理
制作毕业证书(ANU毕业证)莫纳什大学毕业证成绩单官方原版办理制作毕业证书(ANU毕业证)莫纳什大学毕业证成绩单官方原版办理
制作毕业证书(ANU毕业证)莫纳什大学毕业证成绩单官方原版办理
cuobya
 
重新申请毕业证书(RMIT毕业证)皇家墨尔本理工大学毕业证成绩单精仿办理
重新申请毕业证书(RMIT毕业证)皇家墨尔本理工大学毕业证成绩单精仿办理重新申请毕业证书(RMIT毕业证)皇家墨尔本理工大学毕业证成绩单精仿办理
重新申请毕业证书(RMIT毕业证)皇家墨尔本理工大学毕业证成绩单精仿办理
vmemo1
 
不能毕业如何获得(USYD毕业证)悉尼大学毕业证成绩单一比一原版制作
不能毕业如何获得(USYD毕业证)悉尼大学毕业证成绩单一比一原版制作不能毕业如何获得(USYD毕业证)悉尼大学毕业证成绩单一比一原版制作
不能毕业如何获得(USYD毕业证)悉尼大学毕业证成绩单一比一原版制作
bseovas
 
假文凭国外(Adelaide毕业证)澳大利亚国立大学毕业证成绩单办理
假文凭国外(Adelaide毕业证)澳大利亚国立大学毕业证成绩单办理假文凭国外(Adelaide毕业证)澳大利亚国立大学毕业证成绩单办理
假文凭国外(Adelaide毕业证)澳大利亚国立大学毕业证成绩单办理
cuobya
 
Gen Z and the marketplaces - let's translate their needs
Gen Z and the marketplaces - let's translate their needsGen Z and the marketplaces - let's translate their needs
Gen Z and the marketplaces - let's translate their needs
Laura Szabó
 
可查真实(Monash毕业证)西澳大学毕业证成绩单退学买
可查真实(Monash毕业证)西澳大学毕业证成绩单退学买可查真实(Monash毕业证)西澳大学毕业证成绩单退学买
可查真实(Monash毕业证)西澳大学毕业证成绩单退学买
cuobya
 
Search Result Showing My Post is Now Buried
Search Result Showing My Post is Now BuriedSearch Result Showing My Post is Now Buried
Search Result Showing My Post is Now Buried
Trish Parr
 
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
xjq03c34
 
留学挂科(UofM毕业证)明尼苏达大学毕业证成绩单复刻办理
留学挂科(UofM毕业证)明尼苏达大学毕业证成绩单复刻办理留学挂科(UofM毕业证)明尼苏达大学毕业证成绩单复刻办理
留学挂科(UofM毕业证)明尼苏达大学毕业证成绩单复刻办理
uehowe
 
制作原版1:1(Monash毕业证)莫纳什大学毕业证成绩单办理假
制作原版1:1(Monash毕业证)莫纳什大学毕业证成绩单办理假制作原版1:1(Monash毕业证)莫纳什大学毕业证成绩单办理假
制作原版1:1(Monash毕业证)莫纳什大学毕业证成绩单办理假
ukwwuq
 

Recently uploaded (20)

办理毕业证(NYU毕业证)纽约大学毕业证成绩单官方原版办理
办理毕业证(NYU毕业证)纽约大学毕业证成绩单官方原版办理办理毕业证(NYU毕业证)纽约大学毕业证成绩单官方原版办理
办理毕业证(NYU毕业证)纽约大学毕业证成绩单官方原版办理
 
成绩单ps(UST毕业证)圣托马斯大学毕业证成绩单快速办理
成绩单ps(UST毕业证)圣托马斯大学毕业证成绩单快速办理成绩单ps(UST毕业证)圣托马斯大学毕业证成绩单快速办理
成绩单ps(UST毕业证)圣托马斯大学毕业证成绩单快速办理
 
Should Repositories Participate in the Fediverse?
Should Repositories Participate in the Fediverse?Should Repositories Participate in the Fediverse?
Should Repositories Participate in the Fediverse?
 
存档可查的(USC毕业证)南加利福尼亚大学毕业证成绩单制做办理
存档可查的(USC毕业证)南加利福尼亚大学毕业证成绩单制做办理存档可查的(USC毕业证)南加利福尼亚大学毕业证成绩单制做办理
存档可查的(USC毕业证)南加利福尼亚大学毕业证成绩单制做办理
 
国外证书(Lincoln毕业证)新西兰林肯大学毕业证成绩单不能毕业办理
国外证书(Lincoln毕业证)新西兰林肯大学毕业证成绩单不能毕业办理国外证书(Lincoln毕业证)新西兰林肯大学毕业证成绩单不能毕业办理
国外证书(Lincoln毕业证)新西兰林肯大学毕业证成绩单不能毕业办理
 
留学学历(UoA毕业证)奥克兰大学毕业证成绩单官方原版办理
留学学历(UoA毕业证)奥克兰大学毕业证成绩单官方原版办理留学学历(UoA毕业证)奥克兰大学毕业证成绩单官方原版办理
留学学历(UoA毕业证)奥克兰大学毕业证成绩单官方原版办理
 
一比一原版(USYD毕业证)悉尼大学毕业证如何办理
一比一原版(USYD毕业证)悉尼大学毕业证如何办理一比一原版(USYD毕业证)悉尼大学毕业证如何办理
一比一原版(USYD毕业证)悉尼大学毕业证如何办理
 
办理毕业证(UPenn毕业证)宾夕法尼亚大学毕业证成绩单快速办理
办理毕业证(UPenn毕业证)宾夕法尼亚大学毕业证成绩单快速办理办理毕业证(UPenn毕业证)宾夕法尼亚大学毕业证成绩单快速办理
办理毕业证(UPenn毕业证)宾夕法尼亚大学毕业证成绩单快速办理
 
Design Thinking NETFLIX using all techniques.pptx
Design Thinking NETFLIX using all techniques.pptxDesign Thinking NETFLIX using all techniques.pptx
Design Thinking NETFLIX using all techniques.pptx
 
Discover the benefits of outsourcing SEO to India
Discover the benefits of outsourcing SEO to IndiaDiscover the benefits of outsourcing SEO to India
Discover the benefits of outsourcing SEO to India
 
制作毕业证书(ANU毕业证)莫纳什大学毕业证成绩单官方原版办理
制作毕业证书(ANU毕业证)莫纳什大学毕业证成绩单官方原版办理制作毕业证书(ANU毕业证)莫纳什大学毕业证成绩单官方原版办理
制作毕业证书(ANU毕业证)莫纳什大学毕业证成绩单官方原版办理
 
重新申请毕业证书(RMIT毕业证)皇家墨尔本理工大学毕业证成绩单精仿办理
重新申请毕业证书(RMIT毕业证)皇家墨尔本理工大学毕业证成绩单精仿办理重新申请毕业证书(RMIT毕业证)皇家墨尔本理工大学毕业证成绩单精仿办理
重新申请毕业证书(RMIT毕业证)皇家墨尔本理工大学毕业证成绩单精仿办理
 
不能毕业如何获得(USYD毕业证)悉尼大学毕业证成绩单一比一原版制作
不能毕业如何获得(USYD毕业证)悉尼大学毕业证成绩单一比一原版制作不能毕业如何获得(USYD毕业证)悉尼大学毕业证成绩单一比一原版制作
不能毕业如何获得(USYD毕业证)悉尼大学毕业证成绩单一比一原版制作
 
假文凭国外(Adelaide毕业证)澳大利亚国立大学毕业证成绩单办理
假文凭国外(Adelaide毕业证)澳大利亚国立大学毕业证成绩单办理假文凭国外(Adelaide毕业证)澳大利亚国立大学毕业证成绩单办理
假文凭国外(Adelaide毕业证)澳大利亚国立大学毕业证成绩单办理
 
Gen Z and the marketplaces - let's translate their needs
Gen Z and the marketplaces - let's translate their needsGen Z and the marketplaces - let's translate their needs
Gen Z and the marketplaces - let's translate their needs
 
可查真实(Monash毕业证)西澳大学毕业证成绩单退学买
可查真实(Monash毕业证)西澳大学毕业证成绩单退学买可查真实(Monash毕业证)西澳大学毕业证成绩单退学买
可查真实(Monash毕业证)西澳大学毕业证成绩单退学买
 
Search Result Showing My Post is Now Buried
Search Result Showing My Post is Now BuriedSearch Result Showing My Post is Now Buried
Search Result Showing My Post is Now Buried
 
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
 
留学挂科(UofM毕业证)明尼苏达大学毕业证成绩单复刻办理
留学挂科(UofM毕业证)明尼苏达大学毕业证成绩单复刻办理留学挂科(UofM毕业证)明尼苏达大学毕业证成绩单复刻办理
留学挂科(UofM毕业证)明尼苏达大学毕业证成绩单复刻办理
 
制作原版1:1(Monash毕业证)莫纳什大学毕业证成绩单办理假
制作原版1:1(Monash毕业证)莫纳什大学毕业证成绩单办理假制作原版1:1(Monash毕业证)莫纳什大学毕业证成绩单办理假
制作原版1:1(Monash毕业证)莫纳什大学毕业证成绩单办理假
 

How to stop being Rails Developer