Ruby on rails tips

Preview:

DESCRIPTION

some tips for ruby on rails

Citation preview

Ruby on Rails tips2013.04.29

hebinbin.herokuapp.com

Object::try - 1Sometimes you write down the code like: user ? user.name : ‘No name’ We can use try function to optimize code user.try(:name) || ‘No name’

-> if user is not nil, display user.name -> if user is nil, nil.try(:name) will be nil nil || ‘No name’ will be ‘No name’

Object::presence1) nil.presence #=> nil2) [].presence #=> nil3) {}.presence #=> nil4) “” .presence #=> nil5) ‘’ .presence #=> nil

6) false.presence #=> nilSo you can change code like

params[:name].present? ? params[:name] : ‘No name’

Toparams[:name].presence || ‘No name’

Object::send -1class Hoge def test; puts ‘test’; endend

Hoge.new.test #=> ‘test’Hoge.new.send(:test) #=> ‘test’Hoge.new.send(‘test’) #=> ‘test’Hoge.new.send(‘testother’) #=> NoMethodError

So object uses send to read method

Object::send -2Why we need to use send method:1. By using send method, we can read private

method. If you want to test private method, you can use send method

class Hoge def private_test; puts ‘private’; end private :private_test end Hoge.new.private_test #=> NoMethodError Hoge.new.send(:private_test) #=> ‘private’

Object::send -3Why we need to use send method:2. We can pass method name as method parameter: class Hoge def send_test(method_name) self.send(method_name) end def other_method ‘test’ end endHoge.new.send_test(:other_method) #=> ‘test’

freezeWhen you do not want to change some constants or instance variables in the program, you can use freeze.

DAYS=[‘Mon’, ‘Tues’, ‘Wes’] DAYS << ‘Sat’ puts DAYS #=> =[‘Mon’, ‘Tues’, ‘Wes’, ‘Sat’] DAYS=[‘Mon’, ‘Tues’, ‘Wes’].freeze DAYS << ‘Sat’ #=> can't modify frozen Array (RuntimeError)

inject -1If you are familiar with C or Java, when you want to get sum from 1 to 10, maybe you will write ruby code like: sum = 0 (1..10).each { |i| sum = sum + I } puts sum #=> 55

In ruby, you can use the other ways: puts (1..10).inject(0) { |sum, i| sum + I }

inject -2You can also use inject like:

my_hash = { a: 'foo', b: 'bar' } # => {:a=>"foo", :b=>"bar"}

a_new_hash = my_hash.inject({}) { |h, (k, v)| h[k.upcase] = v.upcase; h } # => {:A=>"FOO", :B=>"BAR"}

tap -1When you want to change object itself and return this object, you can use tap method.

The source code look like:class Object def tap yield(self) self end end

tap -2ary = [3, 7, 6, 12]{}.tap {|h| ary.each{|x| h[x] = x**2} } # => {3=>9, 7=>49, 6=>36, 12=>144}{} changes itself to {3=>9, 7=>49, 6=>36, 12=>144}

tryrubyIf you do not want to install ruby on your pc,You can use online ruby:

http://tryruby.org/levels/1/challenges/0

define numberIn ruby, if the number is too bigger to make mistake easily, you can write code like:Irb > 100_000# => 100000Irb >  

HashWithIndifferentAccess

In some cases, you will find that:

x = {"key1" => "value1"}x["key1"] #=> "value1" x[:key1] #=> nil

How can you use both x["key1"] and x[:key1] to get same result ?

x = {"key1" => "val1"} x = x.with_indifferent_access x[:key1] #=> "val1“ x["key1"] #=> "val1"

assert_valid_keysSometimes, you will see some codes like:Image_tag(sym, options={})

When you get options, nomrally we should check the keys are existed or not. So you can use assert_valid_keys

def do_something(options = {}) options.assert_valid_keys :x, :y # do the real something end

If the options contains any other keys, an ArgumentError will be raised.

PS: the better way should be delete other keys.

Extend ruby class -1Back to example which we given before, you want to create a new method for hash to get_valid_keys: class Hash def get_valid_keys(*args) end end

So in ruby on rails, how to extend it ?

Extend ruby class -21. Put the code into lib/core_ext/hash.rbYou also need the following code in your initializer config:

Dir[File.join(Rails.root, "lib", "core_ext", "*.rb")].each {|l| require l }

At last, restart your app.

2. Put the code into config/initializers/hash.rbThen restart your app.

Set union• Join two arrays and remove duplicates with pipe

operator (|)

[ "a", "b", "c" ] | [ "c", "d", "a" ] # => ["a", "b", "c", "d"]

RubyInlineWhen you want to run C or C++ language in your ruby code to improve performance , plz check following website.

https://github.com/seattlerb/rubyinline

Use chainIn ruby, we can use chain to avoid using temp variables for example: #bad code hoge = Hoge.new puts hoge.name #good code puts Hoge.new.name

performance1. Ruby is an interpreted language and

interpreted languages will tend to be slower than compiled ones

2. Ruby uses garbage collection3. Ruby (with the exception of JRuby) does not

support true multithreading.4. Ruby is heavy memory.5. Instantiating too many active record objects is a

place where rails app's memory footprint really grows. (Flyweight Pattern: http://en.wikipedia.org/wiki/Flyweight_pattern#Example_in_Ruby)

Why ruby does not support ture multi-threading?

• In Ruby you have got Global Interpreter Lock, so only one Thread can work at a time. So, Ruby spend many time to manage which Thread should be fired at a moment (thread scheduling). So in your case, when there is no any IO it will be slower!

• You can use Rubinius or JRuby to use real Threads.

• Jruby implements threads with JVM threads, which in turn uses real threads.