why use ruby and rails?
DESCRIPTION
Why would you use Ruby or Ruby on Rails, and why they are cool and fun.TRANSCRIPT
RUBY (AND RAILS)Jan Berdajs @mrbrdo
RUBY
• Japan
• Yukihiro Matsumoto a.k.a. Matz
• 24. Feb. 1993
• Matz is nice and so we are nice (MINASWAN)
RAILS• Denmark
• David Heinemeier Hansson a.k.a DHH
• BaseCamp / 37 signals
• July 2004
• “The best frameworks are in my opinion extracted, not envisioned. And the best way to extract is first to actually do.”
STUFF ON RAILS
ECOSYSTEMRubyGems
PACKAGESASP.NET NuGet: PHP Pear : Packagist/Composer: Python PyPI: Node.JS NPM: Ruby RubyGems:
17,770 !595 21,754 38,607 53,740 68,500
!Honorable mention:
Java, Scala: Maven etc, too many to count
INTERACTIVE CONSOLE
MANY WAYS TO DO ITn = 15!!(1..n).each do |i|! n_zvezdic = (i - 1) * 2 + 1! n_presledkov = n - i! ! (1..n_presledkov).each do! putc " "! end!! (1..n_zvezdic).each do! putc "*"! end! ! putc "\n"!end! !
MANY WAYS TO DO ITn = 15!!(1..n).each do |i|! n_zvezdic = (i - 1) * 2 + 1! n_presledkov = n - i! ! n_presledkov.times do! print " "! end!! n_zvezdic.times do! print "*"! end! ! print "\n"!end! !
MANY WAYS TO DO ITn = 15!!(1..n).each do |i|! n_zvezdic = (i - 1) * 2 + 1! n_presledkov = n - i! ! print " " * n_presledkov! !!! print "*" * n_zvezdic!!! ! print "\n"!end! !
MANY WAYS TO DO ITn = 15!!(1..n).each do |i|! n_zvezdic = (i - 1) * 2 + 1! n_presledkov = n - i! ! puts " " * n_presledkov + "*" * n_zvezdic! !!!!!! !!end! !
MANY WAYS TO DO ITn = 15!!n.times do |i|! n_zvezdic = i * 2 + 1! n_presledkov = n - i - 1! ! puts " " * n_presledkov + "*" * n_zvezdic!end!!!!!! !!! !
MANY WAYS TO DO IT
n = 15!!n.times{|i| puts " "*(n-i-1) + "*"*(i*2+1)}!!!!!! !!! !
MANY WAYS TO DO ITn = 15!!(1..n).each do |i|! n_zvezdic = (i - 1) * 2 + 1! n_presledkov = n - i! ! (1..n_presledkov).each do! putc " "! end!! (1..n_zvezdic).each do! putc "*"! end! ! putc "\n"!end! !
MANY WAYS TO DO IT
n = 15!!n.times{|i| puts " "*(n-i-1) + "*"*(i*2+1)}!!!!!! !!! !
MANY WAYS TO DO IT
n = 15!!n.times{|i| puts " "*(n-i-1) + "*"*(i*2+1)}!!Java:!class Test { public static void main(String args[]) {} }!!!! !!! !
MANY WAYS TO DO IT
n = 15!!n.times{|i| puts " "*(n-i-1) + "*"*(i*2+1)}!!!!!! !!! !
JUST COOLDate.today.thursday? # => true!!10.seconds.ago # => 2014-01-09 09:15:10 +0100!!10.even? # => true!!102.megabytes + 24.kilobytes + 10.bytes # => 106,979,338!!10 + 1 # => 11!!class Fixnum! def +(i)! 42! end!end!!10 + 1 # => 42!
JUST COOLdef alive?! state != :dead!end!!def clear!! everything.remove!end!!def setting=(value)! raise "invalid value" unless value == 42!end!obj.setting = 5!!def [](key)! key + 1!end!obj[1] # => 2!!def []=(key, value)! whatevz!end!obj[1] = 2!
BEST PRACTICES
Short methods, self-commenting code + readability
+ testing !
You only need comments when you know your code is written so bad that people won’t understand it.
def payments_next_week! payments = []!! User.where(user_type: "client").each do |user|! next_week_start = Date.today + (8 - Date.today.cwday).days! next_week_end = next_week_start + 7.days! payments = user.payments.where("due_on >= ? AND due_on < 1.week.from_now", next_week_start, next_week_end)! payments.each do |payment|! next if payment.due_on.saturday? || payment.due_on.sunday?! payments << payment! end! end!end!
def clients! User.where(user_type: "client")!end!!def days_until_next_week(date)! 8 - date.cwday!end!!def next_week_start(after_date)! after_date + days_until_next_week(after_date).days!end!!def week_end(week_start)! week_start + 7.days!end!!def client_payments_between(client, range)! client.payments! .where("due_on >= ?", range.first)! .where("due_on < ?", range.last)!end!!def client_payments_next_week(client)! start_day = next_week_start(Date.today)! client_payments_between(client,! start_day..week_end(start_day))!end!!def payment_on_weekend?(payment)! payment.due_on.saturday? || payment.due_on.sunday?!end!!def payments_next_week! clients.flat_map do |client|! client_payments_next_week(client).reject do |payment|! payment_on_weekend?(payment)! end! end!end!
BEST PRACTICESTesting
describe "#decline!" do! subject { create :booking }!! context "without reason" do! before { subject.decline! }!! its(:status) { should == "declined" }! its(:declined?) { should be_true }! end!! context "with reason" do! before { subject.decline!("REASON!") }!! its(:status) { should == "declined" }! its(:declined?) { should be_true }! its(:status_reason) { should == "REASON!" }! end! end!
BEST PRACTICES
TEST FIRST => great object interfaces/APIsWrite how you want to use it, before you implement it.
BEST PRACTICESDon’t repeat yourself!
Extract duplicate logic
# file1.rb!!User.where(user_type: "client").first!!# file2.rb!!User.where(user_type: "client", active: false).first!
# user.rb!!class User! def self.client! where(user_type: "client")! end!end!!# file1.rb!!User.client.first!!# file2.rb!!User.client.where(active: false).first!
BEST PRACTICESDon’t repeat yourself!
Extract duplicate logic
# file1.rb!!User.where(user_type: "client").first!!# file2.rb!!User.where(user_type: "client", active: false).first!
# user.rb!!class User! def self.client! where(user_type: "client")! end!end!!# file1.rb!!User.client.first!!# file2.rb!!User.client.where(active: false).first!2 places to fix
1 place to fix
+ easier to test
BEST PRACTICESConvention over configuration
Sensible defaults
MY STUFF
MY JOB STUFF @ D-LABS
QUESTIONS