====== Ruby theory questions ====== ===== 1. What are Ruby Gems? ===== This is a very open ended question and you might be better of to start with the basics first: * A gem is nothing more than a piece of ruby code packaged as a library so that it can be imported and used by others in their programs, * A Ruby gem is therefore simply a library that is written in the ruby programming language, * You can add that you often look for ruby gems on rubygems.org. If you have downloaded any recent gems it might be a good idea to mention those. ===== 2. What is the difference between a Symbol and String? ===== * Symbols are faster and immutable strings, * once a string is used up it is marked for cleaning by the Garbage Collector but it is not cleaned up immediately and it cannot be reused, symbols live for the duration of the session. This leads to increased memory usage however by keeping the symbol alive a bit longer it can be reused again. > "string".object_id => 5263280 > "string".object_id => 5220980 > "string".object_id => 5179720 > :symbol.object_id => 329128 > :symbol.object_id => 329128 > :symbol.object_id => 329128 Notice that the object_id stays the same when symbols are created. This happens because the ruby interpreter uses the same heap memory location each time. The symbol was never completely released. In the case of strings the memory is marked for cleanup each time and a new memory is allocated. * strings can be modified, symbols are not. ===== 3. What is the purpose of yield? ===== * The interpreter essentially invokes a separate piece of code and places it in the location, * FIXME ===== 4. What are class variables? How do you define them? ===== * Class variables are created using the ''@@'' prefix, * It works just like any other variable, however in the case of inheritance it works more like a static variable that is accessed across all variable instances: class DemoClass @@my_var = nil def initialize @@my_var = "hello world" end def my_var puts @@my_var end end class Demo2Class < DemoClass def initialize @@my_var = "goodbye world" end end demo1 = DemoClass.new demo1.my_var # => hello world demo2 = Demo2Class.new demo2.my_var # => goodbye world demo1.my_var # => goodbye world * FIXME ===== 5. How do you define instance variables? ===== * Instance variables are defined using ''@'' symbol, * FIXME ===== 6. How do you define global variables? ===== * Global variables are defined using ''$'' symbol, * it can be declared anywhere and used anywhere, (8-O) * it can be used to trigger a procedure if it’s value changes: trace_var :$foo, proc{puts "$foo is now #{$foo}"} $foo = 7 # => $foo is now 7 ===== 7. Does Ruby support constructors? How are they declared? ===== * They are declared as the method ''initialize'' which is called automatically when object is instanciated: class Picture def initialize puts "In a constructor" end end Picture.new # => In a constructor ===== 8. How can you dynamically define a method body? ===== * Instance method can be defined dynamically with ''Module#define_method(name, body)'', where ''name'' is a method's name and ''body'' is a ''Proc'', ''Method'', ''UnboundMethod'' or a block literal, allowing methods to be defined at runtime, class Conjure def self.conjure(name, body) define_method(name, body) end end Conjure.conjure(:glark, ->{ (3..5).to_a * 2}) Conjure.new.glark #=> [3, 4, 5, 3, 4, 5] * ''Module#define_method'' is a private method so it must be called from within the class the method is being defined on, * Alternatively, it can be incoked inside ''class_eval'': Array.class_eval do define_method(:second, ->{self.[](1)}) end [3, 4, 5].second #=> 4 * ''Kernel#define_singleton_method'' is called to define a singleton method on the receiver: Array.define_singleton_method(:second) do |array| array[1] end Array.second([2, 3, 4]) #=> 3 FIXME ===== 9. What is a Range? ===== * ''Range'' is used to declare continuous variables: numerical_range = (1..4).to_a #=> [1, 2, 3, 4] character_range = ('bar'..'bat').to_a #=> ["bar", "bas", "bat"] * it can be iterated like an ''Array''. ===== 10. How can you implement method overloading? ===== * Method overloading means multiple methods having the same name but different parameters, * no support for this in Ruby, * variable number of parameters can be sent to the same method using a hash: class MyClass def initialize(*args) if args.size < 2 || args.size > 3 puts 'This method takes either 2 or 3 arguments' else if args.size == 2 puts 'Found two arguments' else puts 'Found three arguments' end end end end MyClass.new([10, 23], 4, 10) #=> Found three arguments MyClass.new([10, 23], [14, 13]) #=> Found two arguments ===== 11. What is the difference between ''&&'', ''and'' and '&'? ===== * First two are both logical AND statements, * ''&&'' has higher precedence than ''and'': foo = 3 bar = nil a = foo and bar # => nil a # => 3 a = foo && bar # => nil a # => nil Acts like ''(a = foo) and bar'', ''and'' has lower precendence than ''='', * ''&'' operator works differently depending on the context: * Bitwise AND is boolean AND for each bit: 14 & 13 => 12 # 1110 & 1101 = 1100 (in binary) FIXME: http://ablogaboutcode.com/2012/01/04/the-ampersand-operator-in-ruby/ ===== 12. How can you create setter and getter methods in Ruby? ===== ^ Method ^ Effect ^ | ''attr_reader :v'' | ''def v; @v; end'' | | ''attr_writer :v'' | ''def v=(value); @v=value; end'' | | ''attr_accessor :v'' | attr_reader :v; attr_writer :v | ===== 13. What is the convention for using ‘!’ at the end of a method name? ===== * ''!'' indicates that the method is destructive in some way (for example it changes the object itself) ===== 14. What is a module? ===== * ''Module'' is like a class, but it can't be instantiated or subclassed, FIXME ===== 15. Does Ruby support multiple inheritance? ===== * Nope. But Ruby offers a technique called mixin. Modules can be mixed-in with the class in which they are imported: module Logger def log(msg) puts "Message: #{msg} from #{self.to_s}" end end class Program include Logger end ph = Program.new ph.log("Hello!") #=> Message: Hello! from # ===== 16. How will you implement singleton pattern? ===== * The goal of singleton pattern is to write a class definition that only allows the creation of single instance of that class, * singleton pattern is commonly used with database drivers or loggers, where only one instance is allowed, * Ruby Standard Library includes a module called ''Singleton'': require 'singleton' class Logger include Singleton def log(msg) puts(msg) end end Logger.instance.log("Test message") #=> Test message Logger.new.log("Will it work?") #=> singleton.rb:12:in `
': private method `new' called for Logger:Class (NoMethodError) ===== 17. How will you implement an observer pattern? ===== * Observer pattern means that object (subject) maintains a list of its dependents (observers) and notifies them automatically of any state changes, * it is mainly used to implement distributed event handling systems, * Ruby Standard Library already includes a module that implements Observer pattern: require 'observer' # Periodically fetch stock price class Ticker include Observable attr_accessor :price def initialize(symbol, price) @symbol = symbol @price = price end def run last_price = nil loop do @price = @price + Random.rand(11) puts "Current price: #{price}" unless @price == last_price # Notify observers changed last_price = @price notify_observers(Time.now, @price) end end end end # All Warners are observers class Warner def initialize(ticker) ticker.add_observer(self) end end class SMSAlert < Warner def update(time, price) puts "--- #{time.to_s}: SMS Alert for price: #{price}" end end class EmailAlert < Warner # Callback for observer def update(time, price) puts "+++ #{time.to_s}: Email Alert Price changed to #{price}" end end ticker = Ticker.new("MSFT", 307) SMSAlert.new(ticker) EmailAlert.new(ticker) ticker.run #=> Current price: 317 #=> --- 2013-06-11 19:28:21 +0200: SMS Alert for price: 317 #=> +++ 2013-06-11 19:28:21 +0200: Email Alert Price changed to 317 #=> Current price: 323 #=> --- 2013-06-11 19:28:21 +0200: SMS Alert for price: 323 #=> +++ 2013-06-11 19:28:21 +0200: Email Alert Price changed to 323 #=> Current price: 332 #=> --- 2013-06-11 19:28:21 +0200: SMS Alert for price: 332 #=> +++ 2013-06-11 19:28:21 +0200: Email Alert Price changed to 332 ===== 18. How can you define a constant? ===== ===== 19. How can you define an Exception? ===== ===== 20. What is the default access modifier for a method? What are the differences between access modifiers? ===== ===== 21. How does .map() and .reduce() work in Ruby? What about .map(&:downcase) ? ===== * ''map'' goes through each element in a collection and replaces it with the value returned from a block of code, * ''reduce'' accumulates a value across the members of a collection, * by using ''.map(&xxx)'' syntax, you're telling Ruby to pass the ''Proc'' object held in ''xxx'' to ''map'' method as a block.If ''xxx'' is not a ''Proc'' object, Ruby tries to coearce it into one by sending it a ''to_proc'' message. If a symbol is passed, ''to_proc'' is called on the symbol. This method would look like so if it was implemented in Ruby: def to_proc proc {|obj, *args| obj.send(self, *args) } end * using short syntax like this is half as fast as the more explicitly coded block. ===== What is new in Ruby 2.0? ===== * Bitmap Garbage Collection, * ''require()'' speed improvements, * keyword arguments, def foo(foo: 'bar', baz: 'qux', **rest) # Do something end foo(baz: 'qux', foo: 'frob') * module prepend: module IncludableModule def something; end end class MyClass prepend IncludableModule end * lazy enumerators: to_infinity = (0..Float::Infinity) beyond = to_infinity.lazy.select do |n| num % 42 == 0 end 100.times do {|n| puts beyond.next } * tracepoint, object oriented alternative to ''set_trace_func'': trace = TracePoint.new(:raise) do |t| puts "Alert: Exception raised!" end trace.enable * refinements, localised and contained monkey patching: module MyString refine String do def palindrome? self == self.reverse end end end using MyString # Monkey patch now active for context * literal symbol lists: ''%i{eeny meeny miny moe}'', * binary search: ''(1..9999999).bsearch(12345)'' * source code in utf-8 by default, * ''__DIR__'', shows absolute path to file's directory, * ''.to_h'', useful for converting ''Structs''. TODO: http://magazine.rubyist.net/?Ruby200SpecialEn ===== What is new in Ruby 2.1? ===== ==== Frozen String Literals ==== * Strings in ruby are mutable, so each time a string is modified, a new String object is created, * if you want to compare user input to a symbol, you either will have to convert symbol to string (additional string creation) or string to symbol (DoS attack, since they are not garbage collected), * Strings can be frozen, preventing changes done to it: MAREK = "Marek".freeze def marek?(name) name == MAREK end or, in Ruby 2.1: def marek?(name) name == "marek"f end ==== Required Keyword Arguments ==== * Keyword Arguments were added in Ruby 2.0: def foo(a: 10) puts a end foo(a: 20) # => 20 foo # => 10 * this always needs default value. In Ruby 2.1, you can have required keyword arguments: def foo(a:) puts a end foo(a: 20) # => 20 foo # => ArgumentError: missing keyword: a ==== Method definition returns method name ==== # Ruby 2.0 def foo() end # => nil # Ruby 2.1 def foo() end # => :foo Useful for metaprogramming. ==== Remove garbage bytes from Strings ==== "abc\u3042\x81".scrub("*") #=> "abc\u3042*" ==== Others ==== * Partially generational GC, SEE: https://github.com/ruby/ruby/blob/v2_1_0/NEWS ===== 23. What are the differences between Proc, lambda and block? ===== * Blocks, ''Procs'' and ''lambdas'' are all closures. This means that they hold the values of any variables that were around when they were created. ==== Blocks ==== * Block is a code that is implicitly passed to a method through the use of either curly braces (''{...}'') or ''do...end'' syntax, * ''yield'' defers the execution of the calling method in order to evaluate the block; the result of the block, if any, is then evaluated by any remaining code in the method; ''yield'' accepts parameters, which are then passed into and evaluated within the block, * calling ''yield'' will execute the code within the block provided to the method, * single use, can't be assigned to a variable, * can only send one block to a method, but multiple ''Procs'' (in an ''Array'' for example), ==== Procedures ==== * Can be used to store blocks of code. Then, they can be passed to any method that accepts a callable object, ==== Lambdas ==== * Almost identical to ''Procs'', but ''lambda'' checks the number of arguments it receives and returns ''ArgumentError'' if they don't match, * ''->'' can also be used to create ''lambdas'', * it provides diminutive returns, meaning it returns its value and allows method to continue, while ''Procs'' stop the method execution: def lambda_return lambda {return "I'm a lambda!"}.call return "Still running after lambda!" end def proc_return Proc.new {return "I'm just a Proc. :-("}.call return "Still running after proc!" end puts lambda_return puts proc_return * ''lambdas'' conceptually work like methods, they enforce correct number of arguments and do not override the calling methods return, ''Procs'' are more like drop-in code snippets, * in Ruby, arguments cannot have a ''return'' keyword in them, so a ''Proc'' with ''return'' passed into a method would give a ''LocalJumpError'', but a ''lambda'' acts like a method, and this in turn can have ''return'' in it: def generic_return(code) one, two = 1, 2 three, four = code.call(one, two) return "Give me a #{three} and a #{four}" end puts generic_return(lambda { |x, y| return x + 2, y + 2 }) puts generic_return(Proc.new { |x, y| return x + 2, y + 2 }) puts generic_return(Proc.new { |x, y| x + 2; y + 2 }) puts generic_return(Proc.new { |x, y| [x + 2, y + 2] }) # => Give me a 3 and a 4 # => unexpected return (LocalJumpError) # => Give me a 4 and a # => Give me a 3 and a 4 * we can pass methods as an argument to other methods with the use of ''method'' keyword: class Array def iterate!(code) self.each_with_index do |n, i| self[i] = code.call(n) end end end def square(n) n ** 2 end array = [1, 2, 3, 4] array.iterate!(method(:square)) puts array.inspect # => [1, 4, 9, 16] INFO: * http://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/ * https://gist.github.com/mislav/4508988 ===== 24. Describe Ruby data structures and their advantages. ===== ==== Array ==== * holds a collection of object references, * each object reference occupies a position in the array, identified by a non-negative integer index, * with the use of ''pop'' and ''push'', ''Array'' can be treated like a stack, * with the use of ''push'' and ''shift'', ''Array'' can be used like a first-in first-out (FIFO) queue, ==== Hash (or associative array, map, dictionary) ==== * indexed collections of object references, * index can by any object, not just ''Integer'' * storing value in a ''Hash'' means storing two things: index (the key) and the value, * Ruby remembers the order in which items were added to a hash, * ==== Set ==== * implements a collection of unordered values with no duplicates, * a hybrid of Hash's fast lookup and Array's intuitive inter-operation, * the equality is determined according to ''Object#eql?'' and ''Object#hash'' since ''Set'' uses ''Hash'' as storage, * no fixed ordering, so no ability to access elements by index, Useful when: * need an array with no duplicate values, * useful to find out if two differently sorted arrays are equal INFO: http://spin.atomicobject.com/2012/09/04/when-is-a-set-better-than-an-array-in-ruby/ ==== Struct ==== * is something between hashes and classes, * needs to have its attributes defined when you create it, * both ''Struct'' and ''OpenStruct'' imply more concrete relationship amongst the data than ''Hash'', but they don't have the instance methods as would ''Class'', * faster than ''OpenStruct'', take less memory, Use case: * you need a data container and fields are fixed and known beforehand (i.e. at time of writing of the code), * you need a structured Hash key, * you want to quickly define a class with a few fields, * you need to detect errors caused by misspelled field names. ==== OpenStruct ==== INFO: * http://blog.steveklabnik.com/posts/2012-09-01-random-ruby-tricks--struct-new * http://blog.rubybestpractices.com/posts/rklemme/017-Struct.html ===== 25. What is the difference between equal?, eql?, ===, and == ? ===== * ''=='', a generic "equality", at ''Object'' level, it only returns ''true'' if compared objects are the same object. This method is typically overridden in descendant classes to provide class-specific meaning, * ''==='', a case equality, at ''Object'' level it effectively is the same as calling ''#=='', it is typically overriden to provide meaningful semantics in ''case'' statements, * ''eql?'' - generic equality, returns ''true'' if compared objects have the same value. Used by ''Hash'' to test members for equality. For objects of class ''Object'', ''eql?'' is synonymous with ''=='', * ''equal?'' - identity comparison, this should never be overriden, it is used to determine object identity (''a.equal?(b)'' iff ''a'' is the same object as ''b''). ===== 26. What are the most popular Ruby implementations? ===== ---- ====== Rails specific questions ====== ===== 1. Explain Rails MVC implementation. ===== * MVC (model, view, controller) architecture is at the core of Rails, * benefits: * isolation of business logic from the user interface, * ease of keeping code dry, * makes it clear where different types of code belong for easier maintenance, * model represents the information (data) of the application and the rules to manipulate that data. In case of Rails, models are primarily used for managing the rules of interaction with a corresponding database table. Most of application's business logic will be there, * views represent the user interface of the application, views handle the job of providing data to the web browser or other tool that is used to make requests from the application, * controllers glue models and views; are responsible for processing the incoming requests from the wbe browser, interrogating the models for data and passing that data on to the views for presentation. ===== 2. What is a scope? ===== * Scopes are nothing more than SQL fragments. By using these fragments one can cut down on having to write long queries each time you access content. ===== 3. What deployment tools do you know? How do they work? ===== * Capistrano is a popular deployment tool. It allows you to copy code from your source control repository to your server via SSH and perform pre and post-deploy functions like restarting a webserver, busting cache, renaming files, running database migrations and so on. It is also possible to deploy to many machines at once. More info: * http://guides.beanstalkapp.com/deployments/deploy-with-capistrano.html * https://github.com/capistrano/capistrano/wiki/2.x-Getting-Started * https://help.github.com/articles/deploying-with-capistrano ===== 4. How can you migrate your database schema one level down? ===== rake db:rollback rake db:rollback STEP=1 # Rollback to the beginning rake db:reset # or if you're not worried about data rake db:purge ===== 5. What is a sweeper? ===== * Sometimes you want to have control over how often and when the cache expires, * sometimes it is a good idea to have the system determine that on a logical basis, * Say you have a list of product on your site and you want to reload the cache each time a new product is added/updated/deleted, then you can achieve this by using the sweeper: class ProductSweeper < ActionController::Caching::Sweeper observe Product# This sweeper is going to keep an eye on the Product model # If our sweeper detects that a Product was created call this def after_create(product) expire_cache_for(product) end # If our sweeper detects that a Product was updated call this def after_update(product) expire_cache_for(product) end # If our sweeper detects that a Product was deleted call this def after_destroy(product) expire_cache_for(product) end private def expire_cache_for(product) # Expire the index page now that we added a new product expire_page(:controller => 'products', :action => 'index') # Expire a fragment expire_fragment('all_available_products') end end ===== 6. How can you implement caching in Rails? ===== * **Fragment caching** gives you the choice to fragment to pull a portion from the cache and the remaining from a real-time DB call. Say you wanted to show all the orders placed on your website in real time and didn’t want to cache that part of the page, but did want to cache the part of the page which lists all products available, you could use this piece of code: <% Order.find_recent.each do |o| %> <%= o.buyer.name %> bought <%= o.product.name %> <% end %> <% cache do %> All available products: <% Product.all.each do |p| %> <%= link_to p.name, product_url(p) %> <% end %> <% end %> * **Page caching** is often used for home pages and is super fast: class ProductsController < ActionController caches_page:index def index @products = Products.all end end ===== 7. What is a filter? When it is called? ===== * Filters are methods that are called either before or after a controller action is called. ===== 8. What is RESTful routing? ===== REST is a set of principles that define how Web standards, such as HTTP and URIs, are supposed to be used (which often differs quite a bit from what many people actually do). The promise is that if you adhere to REST principles while designing your application, you will end up with a system that exploits the Web’s architecture to your benefit. In summary, the key principles are: * using resource identifiers such as URLs to represent resources, * transferring representations of the state of that resource between system components * Give every “thing” an ID * Link things together * Use standard methods * Resources with multiple representations * Communicate statelessly ===== 9. What is the purpose of layouts? ===== ===== 10. Is it possible to embed partial views inside layouts? ===== ===== 11. How can you create a REST API for your application? ===== ===== 12. How can you define a new environment called 'staging'? ===== ===== 13. What is the difference between has_one and belongs_to? ===== ===== 14. What is a has and belongs to many association? ===== ===== 15. How can you implement single table inheritance? ===== * ActiveRecord allows inheritance by storing the name of the class in a column that by default is named ''type'', * you then can create models like so: class Company < ActiveRecord::Base; end class Firm < Company; end class Client < Company; end class PriorityClient < Client; end When you do ''Firm.create(name: "sqTech")'', this record will be saved in the companies table with type ''Firm'', * if you have many fields in the table that are not shared by all types, STI may be not the best direction, ===== 16. What is a polymorophic association? ===== ===== 17. What is eager loading? ===== ===== 18. How does validation work? ===== ===== 19. Why is fields_for used for? ===== ===== 20. What is the purpose of a helper method? ===== ===== 21. What is flash? ===== ===== 22. How can you implement internationalization? ===== ===== 23. What is and how can you implement a state machine? ===== ===== 24. How can you upload a file to a server? ===== ===== 25. How can you show SEO friendly URLs instead of using only numeric IDs? ===== ===== 26. Is Rails scalable? ===== Yes Rails gives you complete freedom to use all traditional means of scaling an application. Things like memcached, caching full pages, caching fragments are all supported. You can use any standard CDN to serve your media and static content as well. Database scaling using sharding is supported. Finally heroku makes your life easier by giving you the flexibility to scale up/down based on your need. Mostly websites have a peak time during which you need more servers and then there is a sleep time. Heroku makes that on-demand scaling process simpler. Companies such as HireFireApp.com makes the autoscale process easier. ===== 27. What are the key deployment challenges? ===== * mismatched gem version sbetween local and production environments ===== 28. How can you secure a rails application? ===== * Common web security issues involve SQL Injection, Cross-Site Scripting (XSS) and session fixation/hijacking. TODO: http://guides.rubyonrails.org/security.html ==== SQL injection ==== Use: User.where("login = ? AND password = ?", entered_user_name, entered_password).first # or User.where(:login => entered_user_name, :password => entered_password).first instead of: User.first("login = '#{params[:name]}' AND password = '#{params[:password]}'") because of: SELECT * FROM users WHERE login = '' OR '1'='1' AND password = '' OR '2'>'1' LIMIT 1 ===== 29. How can rails engage with a SOA platform? ===== ===== 30. What kinds of associations are available in ActiveRecord ===== * Association is a connection between two ActiveRecord models, * associations are implemented with macro-style calls so it is possible to add features to the models declaratively, * Rails supports six types of associations: * ''belongs_to'' * ''has_one'' * ''has_many'' * ''has_many :through'' * ''has_one :through'' * ''has_and_belongs_to_many'' * all association methods are build around caching, which keeps the result of the most recent query available for further operations, the cache is even shared across methods: customer.orders # retrieves orders from the database customer.orders.size # uses the cached copy of orders customer.orders.empty? # uses the cached copy of orders * passing ''true'' to the assocition call will reload the cache: customer.orders # retrieves orders from the database customer.orders.size # uses the cached copy of orders customer.orders(true).empty? # discards the cached copy of orders # and goes back to the database * by default, ActiveRecord doesn't know about the connection between associations. This can lead to two copies of an object getting out of sync: class Customer < ActiveRecord::Base has_many :orders end class Order < ActiveRecord::Base belongs_to :customer end This happens because ''c'' and ''o.customer'' are two different in-memory representations of the same data, and neither one is automatically refreshed from changes to the other. Active Record provides the '':inverse_of'' option so that you can inform it of these relations. It won't work with: ''through'', ''polymorphic'', ''as'' associations. For ''belongs_to'' associations, ''has_many'' inverse associations are ignored. ==== belongs_to ==== * sets up a one-to-one connection with another model meaning that each instance of declaring model "belongs to" one instance of another model, * on this side, foreign key is set, ==== has_one ==== * sets up one-to-one connection with another model, similarily to ''belongs_to'' but with different semantics, * it indicates, that each instance of a model contains or possesses one instance of another model, * the foreign key is set on target model, ==== has_many ==== * indicates one-to-many connection with another model, meaning that each instance of the model has zero or more instances of another model, ==== has_many :through ==== * sets up many-to-many connection with another model, meaning that the declaring model can be matched with zero or more instances of another model by proceeding //through// a third model, * automatic deletion of join model is direct, no destroy callbacks are triggered, * useful for setting up shortcuts through nested ''has_many'' associations, * if you need validations, callbacks or extra attributes on the join model, you should use this instead of ''has_and_belongs_to_many'', ==== has_one :through ==== * sets up one-to-one connection with another model, meaning that the declaring model can be matched with one instance of another model by proceeding //through// a third model, ==== has_and_belongs_to_many ==== * creates direct many-to-many connection with another model, without intervening model, * if you don't need to do anything with the relationship model, it might be simplier to set up this than ''has_many :through'', * you need to remember to create the joining table in the database, ==== Polymorphic association ==== * a model can belong to more than one other model, on a single association, * you need to declare both a foreign key column and a type column in the model that declares the polymorphic interface, ==== Self joins ==== * sometimes a model should have a relation to itself, * example: all employees in a single database model, but you want to trace relationships such as between a manager and his subordinates: class Employee < ActiveRecord::Base has_many :subordinates, :class_name => "Employee", :foreign_key => "manager_id" belongs_to :manager, :class_name => "Employee" end ===== 31. Advantages of NoSQL (MongoDB) databases over SQL ===== * has no formally described tables, stores structured data in JSON like documents with dynamic schemas - columns with no values will be set as ''NULL'' in SQL wasting space, while in NoSQL they won't, * querying works by passing a document explaining what needs to be queried - no parsing is necessary, no need to worry about injection attacks, * no support for ''JOIN''s in NoSQL, but documents can be embedded within another document, * no support for transactions, * MongoDB supports master-slave replication with automated failover and built-in horizontal scaling via automated range-based partitioning, * MongoDB scales horizontally using sharding. Developer selects a shard key, which determines how the data in a collection will be distributed. The data is split into ranges (based on the shard key) and distributed across multiple shards. (A shard is a master with one or more slaves.) * MapReduce ( Map() procedure that performs filtering and sorting (such as sorting students by first name into queues, one queue for each name) and a Reduce() procedure that performs a summary operation (such as counting the number of students in each queue, yielding name frequencies). The "MapReduce System" (also called "infrastructure", "framework") orchestrates by marshaling the distributed servers, running the various tasks in parallel, managing all communications and data transfers between the various parts of the system, providing for redundancy and failures, and overall management of the whole process) can be used for batch processing of data and aggregation operations. The aggregation framework enables users to obtain the kind of results for which the SQL GROUP BY clause is used, * JavaScript can be used in queries, aggregation functions (for example MapReduce) are sent directly to the database to be executed, ===== 32. What is new in Rails 4.0? ===== * Strong parameters - instead of ''attr_accessible'' in model, we use ''params.requir(:model).permit(:name, :email)'', it protects you from unexpected mass assignment, * Turbolinks - in browsers with ''pushState'' support, clicking a link causes an AJAX request, updates the URL with ''pushState'' (so back button works) and uses JS to update the '''' and the ''<body>'' in the DOM, so no CSS and JS are needed to be redownloaded; with Turbolinks page load events won't fire when user navigates from page to page, because DOM never actually reloads, so new events are added (fetch, change, load, restore), * Russian doll caching, nested fragment caching: <code ruby> class Milestone < ActiveRecord::Base has_many :todos end class Todo < ActiveRecord::Base belongs_to :milestone, :touch => true end # app/views/milestones/show.html.erb <% cache @milestone do %> <h1><%= @milestone.name %></h1> <div class="description"><%= @milestone.description %></div> <ul class="todos"> <%= render @milestone.todos %> </ul> <% end %> # app/views/todos/_todo.html.erb <% cache todo do %> <li class="todo"> <%= todo.description %> <span class="status"><%= todo.status %></span> </li> <% end %> </code> '':touch'' option is required for this caching stratego to work properly. If a Todo is added to a milestone, we need to break cache on the milestone to avoid serving stale views. Suppose we have amilestone with ten todos. Editing only one todo causes the milestone's cache to break, but when generating the HTML, all but one of the todo partials can be fetched from the cache, improving render times. We're trading time for space, as this generates a lot of cruft in our cache, * Straming, through ''ActionController::Live'' - new module provides the ability to stream data to clients, this needs a threaded server (thin, puma) so that stream data actioms from streaming controllers run in a separate thread, * ''Article.all'' is now ''ActiveRecord::Relation'' - lazy loaded, * ''Article.none'' returns Relation with no records, * ''Article.load'' will trigger the SQL query but will return a relation - useful if we want to execute the query for caching behaviour but still need a relation, * it is possible to call ''not'' on a ''where'' scope to invert it: <code ruby> >> Article.where.not(name: "Hello") Article Load (107.6ms) SELECT "articles".* FROM "articles" WHERE ("articles"."name" != 'Hello') </code> * ''order'' clause now accepts a hash, * ''find_by'' method which works like ''find_by_something'' but doesn't rely on ''method_missing'' and is faster: <code ruby> >> Article.find_by name: "Hello" </code> * ''ActiveModel::Model'' - works like ActiveRecord model but without the database stuff, we can add validations, ''attr_accessors'', * ''update'' action now responds to either ''PUT'' or ''PATCH'' request, * controllers and models directories now have a ''concerns'' directory. It is designed for modules that we can include in our models to help reduce their size, * ''collection_check_boxes'' and ''collection_radio_buttons'' helper methods to generate lists of checkboxes or radio buttons for an association, * supplying ''constraints'' to a route will make them default attributes when generating the URL: <code ruby> get 'foo', to: 'articles#index', constraints: {protocol: "https", subdomain: "test"} >> app.foo_url => "https://test.example.com/foo" </code> * New PostgreSQL features: * ''hstore'' ===== 33. What is the difference between _path and _url route helpers? ===== ''_url'' methods generate entire URL, including protocol and domain, ''_path'' generates just the path part. ===== 20. ===== ====== General object-oriented and programming questions ====== ===== 1. What is polymorphism? ===== * formally, it is the ability to create an object that has more than one form, * the purpose of polymorphism is to implement a ''message-passing'' style of programming, where objects of various types define a common interface of operations for user, * primary usage in industry is the ability of objects belonging to different types to respond to method, field or property calls of the same name, each one according to an appropriate type-specific behavior, * one way to achieve this kind of behavior is through inheritance: <code ruby> class Bird def initialize(name) @name = name end def speak puts 'Tweet' end def fly puts 'Up up and away...' end end class Duck < Bird def speak puts "Quack I am #{@name}" end end class Penguin < Bird def speak puts "Squak I am #{@name}" end def fly puts 'Nope. I swim...' end end </code> And now we can do something like this: <code ruby> birds = [Bird.new('Tweetie'), Duck.new('Donald'), Penguin.new('Mumbo')] birds.each do |b| b.fly end # Up up and away... # Up up and away... # Nope. I swim... birds.each do |b| b.speak end # Tweet # Quack I am Donald # Squak I am Mumbo </code> * in Ruby, //duck typing// is preferred to this kind of inheritance polymorphism. "If it walks like a duck and quacks like a duck, then it is a duck". We do this like so: <code ruby> class Duck def speak puts "Quack I am #{@name}" end def fly puts 'Up up and away...' end end class Penguin def speak puts "Squak I am #{@name}" end def fly puts 'Nope. I swim...' end end </code> We put any shared methods in a module and then include them in our classes: <code ruby> module Bird def initialize(name) @name = name end end class Duck include Bird ... end class Penguin include Bird ... end </code> http://www.runtime-era.com/2012/08/polymorphism-in-ruby.html ===== 2. What are SOLID principles? ===== * **S**ingle Responsibility Principle, * **O**pen for extension, closed to modification, * **L**iskov Substitution Principle, * **I**nterface Segregation, * **D**ependency Inversion. ==== Single Responsibility Principle ==== ==== Open for extension, closed to modification ==== ==== Liskov Substitution Principle ==== ==== Interface Segregation ==== ==== Dependency Inversion ==== ====== Algorithm and data structure questions ====== TODO: * http://www.reddit.com/r/learnprogramming/comments/1i1zkl/what_are_some_programming_problems_that_all/ * http://www.reddit.com/r/learnprogramming/comments/1j0mo1/what_are_10_neat_algorithms_to_teach/ * ===== 1. Reverse an interger, e.g. 12345 => 54321, without converting to a string. ===== <code ruby> def get_number_digits(number) digits = [] modulo = 1 loop do modulo *= 10 digits << (number % modulo) / (modulo / 10) break if number < modulo end digits end def assemble_digits(ary) number = 0 multiplier = 1 ary.reverse.each do |digit| number += digit * multiplier multiplier *= 10 end number end digits = get_number_digits(1923434) assemble_digits(digits) </code> ===== 2. Peform a binary search on an array of numbers to find a number. ===== <code ruby> ARRAY = [1, 1, 1, 1, 5, 6, 8, 9, 10, 11] def binary_search(ary, number) low_index = 0 high_index = ary.size - 1 while low_index <= high_index mid_index = (low_index + high_index) / 2 value = ary[mid_index] if value < number low_index = mid_index + 1 elsif value > number high_index = mid_index - 1 else return mid_index end end nil end puts binary_search(ARRAY, 1) </code> Notes: * With duplicates, it will return first one found, not neccesarily the lowest indexed one, * array needs to be sorted, ===== 3. What data structures are you familiar with? ===== * ''Queue'' - entities in the collection are kept in order and the principal (or only) operations on the collection are the addition of entities to the rear terminal position, known as enqueue, and removal of entities from the front terminal position, known as dequeue. This makes the queue a First-In-First-Out (FIFO) data structure. In a FIFO data structure, the first element added to the queue will be the first one to be removed. This is equivalent to the requirement that once a new element is added, all elements that were added before have to be removed before the new element can be removed. Often a peek or front operation is also implemented, returning the value of the front element without dequeuing it. A queue is an example of a linear data structure, or more abstractly a sequential collection, * ''Stack'' - principal (or only) operations on the collection are the addition of an entity to the collection, known as push and removal of an entity, known as pop.[1] The relation between the push and pop operations is such that the stack is a Last-In-First-Out (LIFO) data structure. In a LIFO data structure, the last element added to the structure must be the first one to be removed. This is equivalent to the requirement that, considered as a linear data structure, or more abstractly a sequential collection, the push and pop operations occur only at one end of the structure, referred to as the top of the stack. Often a peek or top operation is also implemented, returning the value of the top element without removing it, ===== 4. Fibonacci ===== <code ruby> # From https://github.com/mruby/mruby/blob/master/benchmark/fib39.rb def fib n return n if n < 2 fib(n-2) + fib(n-1) end puts fib(39) </code> ====== Real Questions ===== ===== 1. What kind of SQL Joins you know? ===== * Cross join - each row from first table with each row from second table: <code sql> # explicit SELECT * FROM employee CROSS JOIN department; # implicit SELECT * FROM employee, department; </code> * Inner join - compares each row from first table with each row of second table to find all pairs of rows which satisfy the join-predicate. When it is, column values for each matched pair of rows from first and second table are combined into a result row: <code sql> # explicit SELECT * FROM employee INNER JOIN department ON employee.DepartmentID = department.DepartmentID; # implicit SELECT * FROM employee, department WHERE employee.DepartmentID = department.DepartmentID; </code> * Equi-join - similar to Inner join, but only equality comparisons can be used in the join-predicate, * Natural join - compares all columns in both tables that have the same column names in the joined tables, the resulting table contains only one column for each pair of equally named columns. The use of this join is discouraged (a column is inadvertently added with the name that exists in other table): <code sql> SELECT * FROM employee NATURAL JOIN department; </code> * Left outer join - always contains all records of the "left" table (first), even if the join-predicate does not find any matching record in the "right" table (second). In such case, fields from right table are filled with NULL: <code sql> SELECT * FROM employee LEFT OUTER JOIN department ON employee.DepartmentID = department.DepartmentID; </code> * Right outer join - reversed left outer join: <code sql> SELECT * FROM employee RIGHT OUTER JOIN department ON employee.DepartmentID = department.DepartmentID; </code> * Full outer join - combines left outer join and right outer join, returning all rows: <code sql> SELECT * FROM employee FULL OUTER JOIN department ON employee.DepartmentID = department.DepartmentID; </code> * Self-join - joins a table to itself: <code sql> SELECT F.EmployeeID, F.LastName, S.EmployeeID, S.LastName, F.Country FROM Employee F INNER JOIN Employee S ON F.Country = S.Country WHERE F.EmployeeID < S.EmployeeID ORDER BY F.EmployeeID, S.EmployeeID; </code> ===== 2. What is oAuth? ===== ===== 3. Find highest singular number from a given range. ===== ===== 4. What kind of HTTP actions do you know? How Rails uses them? ===== There are several described in RFC2616 for HTTP/1.1: * ''OPTIONS'' allows the client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval, * ''GET'' means retrieve whatever information (in the form of an entity) is identified by the Request-URI, * ''HEAD'' is identical to GET except that the server MUST NOT return a message-body in the response, * ''POST'' is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line, * ''PUT'' requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server, * ''DELETE'' requests that the origin server delete the resource identified by the Request-URI, * ''TRACE'' is used to invoke a remote, application-layer loop-back of the request message, * ''CONNECT'' method is reserved for use with a proxy that can dynamically switch to being a tunnel. ^ HTTP Verb ^ Path ^ Action ^ | GET | ''/photos'' | index | | GET | ''/photos/new'' | new | | POST | ''/photos'' | create | | GET | ''/photos/:id'' | show | | GET | ''/photos/:id/edit'' | edit | | PATCH/PUT | ''/photos/:id'' | update | | DELETE | ''/photos/:id'' | destroy | ===== 5. How Rails simulates HTTP actions other than POST and GET? ===== Forms in web browsers can only send ''POST'' and ''GET'' requests. Any other request (''PUT'', ''DELETE'') is send as a ''POST'' request with a hidden field called ''_method'', set either to ''put'' or ''delete''. Rails application detects it and route the request to ''update'' or ''destroy'' action respectively. ===== 6. What is AJAX? What is it used for and what are the limitations of AJAX? ===== * AJAX, (Asynchronous JavaScript and XML), is a set of technologies, that allow an interaction with user to be made without complete page reload, * relies on ''XMLHttpRequestObject'', XHR, API available in all modern browsers, that allows JavaScript code on the browser to exchange data with the server and use it to change the user interface of the application on the fly, without a page refresh, * some people block the use of JavaScript (slow computer) and those elements of a web application will be inaccessible to them * traditional "Back/Forward" browser navigation is no longer possible, * JSON (JavaScript Object Notation) is commonly used in AJAX as a "language-independent, compact, human-readable and versatile data format", it supplies an easy way to encode JavaScript objects, * JSONP (JSON with padding) provides a method to request data from a server in a different domain, something prohibited by typical web browsers because of the same origin policy. ===== 7. How would you implement Ruby Object#tap() method? How does it work? ===== <code ruby> class Object def tap yield self self end end </code> It allows you do do something with an object inside of a block, and always have that block return the object itself. INFO: http://www.seejohncode.com/2012/01/02/ruby-tap-that/ ===== 8. What is the difference between include and extend? ===== * ''include'' makes the module's methods available to the instance of a class, included module is added as a superclass of the class being defined: <code ruby> module Logger def log(msg) STDERR.puts Time.now.strftime("%H:%M:%S: ") + "#{self} (#{msg})" end end class Song include Logger end s = Song.new s.log("created") </code> * ''extend'' makes the methods available to the class itself: <code ruby> module Humor def tickle "#{self} says hee, hee!" end end obj = "Grouchy" obj.extend Humor obj.tickle # => "Grouchy says hee, hee!" </code> ===== 9. What is the difference between .find and .find_by_id in Rails? ===== * ''.find'', if passed an ID or array of ID's will try to find them all. Failing that, it will raise an exception, * ''.find_by_id'' is a dynamically generated method (hence slower) and if it doesn't find given records, returns ''nil''. ===== 10. What is the difference between after_commit and after_safe callback? ===== ===== 11. What is pJax? ===== ===== 12. If a class inherits from another class and a module, and they all have the same method, how the inheritance chain will look like? ===== ===== How do you evaluate a gem for production environment? ===== There are a couple of criteria that should be considered when evaluating a gem: * test coverage, * scalabilty, * popularity, * extendibility, * frequent updates. ===== How a singleton pattern is implemented in Ruby? ===== This is achieved by: * making ''Klass.new'' and ''Klass.allocate'' private, * overriding ''Klass.inherited(sub_klass)'' and ''Klass.clone()'' to ensure that the Singleton properties are kept when inherited and cloned, * providing the ''Klass.instance()'' method that returns the same object each time it is called, * overriding ''Klass._load(str)'' to call ''Klass.instance()'', * overriding ''Klass#clone'' and ''Klass#dup'' to raise ''TypeErrors'' to prevent cloning or duping. ===== How is a Observer pattern implemented in Ruby? ===== FIXME: http://www.ruby-doc.org/stdlib-2.1.1/libdoc/observer/rdoc/Observable.html, https://github.com/ruby/ruby/blob/trunk/lib/observer.rb ====== Source ====== * http://anilpunjabi.tumblr.com/post/25948339235/ruby-and-rails-interview-questions-and-answers * https://github.com/gregstallings/ruby-trivia * http://thereq.com/q/best-ruby-software-interview-questions/programming * http://www.geekinterview.com/Interview-Questions/J2EE/Ruby * http://rorguide.blogspot.com/search/label/Interview%20Questions * http://careerride.com/Ruby-Interview-Questions.aspx * http://ruby.megasolutions.net/ * http://theprofessionalspoint.blogspot.com/2013/02/basic-ruby-on-rails-ror-interview.html * http://blog.firsthand.ca/2010/08/questions-asked-in-ruby-on-rails-job.html ====== IRC ====== <code> 20:36 < jastix> sqbell: i was asked this kind of question only once. I was asked to think how to sort an array. 20:36 < dhoss> sqbell: do you know anything about basic data structures? sorting, searching trees, etc 20:36 < terrellt> sqbell: I'm not sure what they'd ask. If they're trying to find someone with a classic CS degree you're looking at hash tables, linked lists, dynamic arrays. Sorting algorithms. Most of that's dealt with in Ruby though. 20:37 < terrellt> Search trees are potentially useful in Rails land. Hash tables too. 20:38 < brownies> sqbell: at a bare minimum you should know your way around Hashes and Arrays (duh) and i'd also like to see knowledge of handy Ruby things like OpenStruct 20:39 < brownies> sqbell: from there it really depends on who is interviewing you and the company, but i would be mildly satisfied if you could then go on to talk about calling #map and #reduce on both of those things and how those work, and maybe i would make you write some basic algorithms using those methods 20:37 < joshuawscott> sqbell: if it's a Rails position, you'll likely be asked what you don't like about RoR. 20:40 < brownies> and perhaps since it's an RoR position that's a nice segue into talking about activeRecord things and DB structures 20:42 < jastix> sqbell: often people ask about fibonacci numbers and prime numbers 20:43 < joshuawscott> sqbell: http://codility.com/train/ is a good place to see what you don't know </code>