[go: up one dir, main page]

0% found this document useful (0 votes)
12 views21 pages

Ruby Rails 100 Full Programs Practice

Just it is document about ruby it's program and all

Uploaded by

raajkale100
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views21 pages

Ruby Rails 100 Full Programs Practice

Just it is document about ruby it's program and all

Uploaded by

raajkale100
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 21

100 Ruby & Ruby on Rails Practice Programs (Full Detailed)

This PDF contains 100 practice programs covering Core Ruby and Ruby on Rails topics. Each entry includes: Problem
statement, 1–3 implementation approaches (where applicable), example input/output, explanation, and Rails-specific
notes if relevant. If you want expanded runnable examples or more variants for specific items, tell me the program
numbers.

1. Reverse a String
Approach 1:
str = 'Rails'
puts str.reverse

Approach 2:
puts str.each_char.to_a.reverse.join

Input / Output: Input: 'Rails' → Output: 'sliaR'


Explanation: Built-in String#reverse is simplest; second approach shows manual reversal by converting to array of
chars.

2. Palindrome Check (ignore non-alphanum & case)


Approach 1:
def palindrome?(s)
s2 = s.downcase.gsub(/[^a-z0-9]/,'')
s2 == s2.reverse
end

Approach 2:
def palindrome?(s)
chars = s.downcase.scan(/[a-z0-9]/)
chars == chars.reverse
end

Input / Output: Input: 'Madam, I'm Adam' → true


Explanation: Normalize string then compare with reverse; second uses scan for only allowed chars.

3. Factorial (iterative & recursive)


Approach 1:
def fact_iter(n)
(1..n).reduce(1,:*)
end

Approach 2:
def fact_rec(n)
return 1 if n<=1
n * fact_rec(n-1)
end

Input / Output: Input: 5 → 120


Explanation: Iterative uses Enumerable#reduce; recursive shows mathematical definition (may overflow for large n).

4. Fibonacci (recursive, iterative, memoized)


Approach 1:
def fib_rec(n)
return n if n<2
fib_rec(n-1) + fib_rec(n-2)
end
Approach 2:
def fib_iter(n)
a,b=0,1
n.times{a,b=b,a+b}
a
end

Approach 3:
def fib_memo(n, memo={})
return n if n<2
memo[n] ||= fib_memo(n-1,memo)+fib_memo(n-2,memo)
end

Input / Output: Input: 6 → 8


Explanation: Recursive is exponential; iterative is O(n); memoized recursive is O(n) using caching.

5. Find duplicates in array


Approach 1:
arr = [1,2,2,3,4,4]
dups = arr.group_by{|x| x}.select{|k,v| v.size>1}.keys

Approach 2:
dups = arr.select.with_index{|x,i| arr.index(x)!=i}.uniq

Input / Output: Input: [1,2,2,3,4,4] → [2,4]


Explanation: Group_by approach counts occurrences; select-with-index identifies repeated items.

6. Unique elements
Approach 1:
arr.uniq

Approach 2:
Hash[arr.map{|e| [e,true]}].keys # alternative using hash keys to dedupe

Input / Output: Input: [1,2,2] → [1,2]


Explanation: Array#uniq is idiomatic and preserves order of first occurrences.

7. Sum of array (reduce vs sum)


Approach 1:
arr.inject(0,:+)

Approach 2:
arr.sum # Ruby 2.4+

Input / Output: Input: [1,2,3] → 6


Explanation: Use Enumerable#sum when available; inject is universal.

8. Prime check (trial division and optimized)


Approach 1:
def prime?(n)
return false if n<2
(2..Math.sqrt(n)).none?{|i| n % i == 0}
end

Approach 2:
def prime_opt?(n)
return false if n<2
return true if [2,3].include?(n)
return false if n%2==0 || n%3==0
i=5
while i*i<=n
return false if n%i==0 || n%(i+2)==0
i += 6
end
true
end

Input / Output: Input: 13 → true


Explanation: Optimized checks reduce iterations using 6k±1 rule.

9. Sort hash by value


Approach 1:
h = {a:3,b:1,c:2}
sorted = h.sort_by{|k,v| v}.to_h

Approach 2:
sorted_pairs = h.to_a.sort_by{|k,v| v}; Hash[sorted_pairs]

Input / Output: Result: {b:1,c:2,a:3}


Explanation: Use sort_by then convert back to hash; original order preserved in Ruby 1.9+ hashes.

10. Count words in string


Approach 1:
s.split(/\s+/).reject(&:empty?).size

Approach 2:
s.scan(/\w+/).size

Input / Output: Input: 'hello world' → 2


Explanation: split on whitespace or scan word characters; scan ignores punctuation.

11. Anagram check


Approach 1:
def anagram?(a,b)
a.downcase.chars.sort == b.downcase.chars.sort
end

Approach 2:
def anagram?(a,b)
a.downcase.chars.tally == b.downcase.chars.tally
end

Input / Output: Input: 'listen','silent' → true


Explanation: Sorting compares canonical forms; tally (Ruby 2.7+) compares counts without sorting.

12. Reverse words in sentence


Approach 1:
'hello world'.split.reverse.join(' ')

Approach 2:
s.split(' ').reverse.join(' ') # preserves simple cases

Input / Output: → 'world hello'


Explanation: Split words into array, reverse, then join.

13. Swap two variables without temp


Approach 1:
a,b = b,a

Approach 2:
a ^= b; b ^= a; a ^= b # works for integers only

Input / Output: Swaps values of a and b


Explanation: Multiple assignment is idiomatic Ruby; XOR trick is only for integers and less readable.

14. Map to squares and select


Approach 1:
[1,2,3].map{|n| n*n}

Approach 2:
arr.map(&->(n){ n*n }) # using lambda to demonstrate passing

Input / Output: → [1,4,9]


Explanation: Use map for functional transformation.

15. Flatten nested array (with levels)


Approach 1:
[1,[2,3],[4,[5]]].flatten # full flatten

Approach 2:
[1,[2,[3]]].flatten(1) # flatten one level

Input / Output: → [1,2,3,4,5]


Explanation: Array#flatten accepts level argument to control depth.

16. Array intersection & difference


Approach 1:
[1,2,3] & [2,3,4] # intersection

Approach 2:
[1,2,3] - [2] # difference

Input / Output: Intersection → [2,3]; Difference → [1,3]


Explanation: Operators & and - provide set-like operations on arrays.

17. Rotate string by n (Caesar cipher)


Approach 1:
def caesar(s,n)
s.chars.map{|c|
if ('a'..'z').include?(c)
(((c.ord - 97 + n)%26)+97).chr
elsif ('A'..'Z').include?(c)
(((c.ord - 65 + n)%26)+65).chr
else c end}.join
end

Approach 2:
Using tr: s.tr('A-Za-z', shifted_range) # build mapping with ranges

Input / Output: 'abc',2 → 'cde'


Explanation: Manual ord/chr math or use tr for mapping ranges.

18. Merge two sorted arrays (merge step)


Approach 1:
def merge(a,b)
i=j=0; out=[]
while i<a.size && j<b.size
out << (a[i] <= b[j] ? a[i++] : b[j++])
end
out + a[i..-1].to_a + b[j..-1].to_a
end

Approach 2:
(a+b).sort # simpler but less efficient (O((m+n)log(m+n)))

Input / Output: Merges two sorted arrays into a sorted array


Explanation: Merge step is O(m+n); concatenation+sort is simpler but less optimal.

19. Count character frequency


Approach 1:
s.chars.tally # Ruby 2.7+

Approach 2:
s.each_char.with_object(Hash.new(0)){|c,h| h[c]+=1}

Input / Output: 'aabbc' → {'a'=>2,'b'=>2,'c'=>1}


Explanation: tally is concise; manual hash accumulation works in older Ruby versions.

20. Find second largest element


Approach 1:
arr.uniq.sort[-2]

Approach 2:
arr.uniq.max(2).last # uses Enumerable#max

Input / Output: Input: [1,3,4,4] → 3


Explanation: uniq to avoid duplicate largest affecting result; max(2) returns two largest values.

21. Binary search (iterative)


Approach 1:
def bsearch(a, x)
l=0; r=a.size-1
while l<=r
m=(l+r)/2
return m if a[m]==x
a[m] < x ? l = m+1 : r = m-1
end
nil
end

Approach 2:
# Ruby's Array#bsearch can be used for monotonic functions: a.bsearch{|v| v>=x}

Input / Output: Returns index of x or nil


Explanation: Classic binary search implementation; Ruby provides bsearch for convenience.

22. Rotate array by k


Approach 1:
def rotate(a,k)
k = k % a.size
a[-k..-1] + a[0...-k]
end
Approach 2:
a.rotate(k) # built-in Array#rotate

Input / Output: [1,2,3,4],2 → [3,4,1,2]


Explanation: Array#rotate is simplest; slice+concat shows manual behavior.

23. Check power of two (bit trick)


Approach 1:
def power_of_two?(n)
n>0 && (n & (n-1)) == 0
end

Approach 2:
def power_of_two?(n)
(1..Math.log2(n).to_i).include?(n)
end # less ideal

Input / Output: 8 → true


Explanation: Bitwise trick is constant time and idiomatic for integers.

24. Find missing number in 1..n


Approach 1:
def missing(a)
n = a.size+1
(1..n).sum - a.sum
end

Approach 2:
Use XOR trick for constant space: xor all 1..n and array elements and result is missing number

Input / Output: [1,2,4] → 3


Explanation: Sum formula uses arithmetic series; XOR avoids large sums and overflow.

25. Remove nils and blanks from array


Approach 1:
arr.compact.reject{|x| x.to_s.strip==''}

Approach 2:
arr.reject(&:blank?) # Rails active_support provides blank?

Input / Output: Removes nil and empty strings


Explanation: Use compact then reject empty strings; Rails' blank? simplifies this.
Rails note: In Rails use Object#blank? provided by ActiveSupport.

26. Transpose matrix


Approach 1:
matrix.transpose

Approach 2:
Manual: (0...cols).map{|j| (0...rows).map{|i| matrix[i][j]}}

Input / Output: [[1,2],[3,4]] → [[1,3],[2,4]]


Explanation: Array#transpose requires rectangular matrix; manual method demonstrates logic.

27. Depth of nested arrays (recursive)


Approach 1:
def depth(x)
return 0 unless x.is_a?(Array)
1 + x.map{|e| depth(e)}.max.to_i
end

Approach 2:
# Alternative using stack BFS/DFS iterative approach for large depths

Input / Output: [[1,[2]]] → depth 3


Explanation: Recursively compute depth; iterative approach can avoid recursion limits.

28. String compression (run-length encoding)


Approach 1:
def compress(s)
s.gsub(/(.)\1+/){|m| m[0] + m.length.to_s}
end

Approach 2:
Manual: iterate and count runs accumulating into output string

Input / Output: 'aaabb' → 'a3b2'


Explanation: Regex-based approach is concise; manual iteration gives control and is language-agnostic.

29. LRU cache (conceptual using ordered hash)


Approach 1:
# Use Hash which preserves insertion order; implement eviction
class LRU
def initialize(size)
@size=size; @h={}
end
def get(k)
return nil unless @h.key?(k)
v=@h.delete(k); @h[k]=v; v
end
def set(k,v)
@h.delete(k) if @h.key?(k)
@h[k]=v
@h.shift if @h.size> @size
end
end

Approach 2:
# Use gems or deque for better perf

Input / Output: Conceptual behavior: caches limited size, evicts least recently used
Explanation: Hash insertion order lets us move accessed keys to end; shift removes oldest.

30. Generate permutations and combinations


Approach 1:
[1,2,3].permutation.to_a

Approach 2:
[1,2,3].combination(2).to_a

Input / Output: Permutations: [[1,2,3],...], Combinations: [[1,2],[1,3],[2,3]]


Explanation: Enumerable provides permutation and combination methods.

31. Sum of digits of number


Approach 1:
n.to_s.chars.map(&:to_i).sum

Approach 2:
while n>0; sum+=n%10; n/=10; end # arithmetic method

Input / Output: 123 → 6


Explanation: String method is simple; arithmetic avoids allocations.

32. GCD (Euclidean)


Approach 1:
def gcd(a,b)
b==0 ? a : gcd(b, a%b)
end

Approach 2:
Iterative version using while b!=0 swap modulo

Input / Output: gcd(12,8) → 4


Explanation: Recursive Euclid is concise and efficient.

33. LCM using GCD


Approach 1:
def lcm(a,b)
(a*b)/gcd(a,b)
end

Input / Output: lcm(4,6) → 12


Explanation: Use gcd to compute lcm safely; beware overflow for big numbers.

34. Binary to decimal and vice versa


Approach 1:
'101'.to_i(2) # => 5

Approach 2:
5.to_s(2) # => '101'

Input / Output: Conversions between bases using to_i and to_s with base argument
Explanation: Ruby provides direct base conversions via to_i(base) and to_s(base).

35. URL-safe base64 encode/decode


Approach 1:
require 'base64'
Base64.urlsafe_encode64('data')
Base64.urlsafe_decode64(s)

Input / Output: Encode/decode without '+'/'/' characters


Explanation: Useful for tokens in URLs; Ruby standard lib supports this.

36. Regex: extract capture groups


Approach 1:
m = 'item:123'.match(/item:(\d+)/)
id = m[1]

Approach 2:
'item:123'[/item:(\d+)/,1] # direct capture
Input / Output: Extract id '123' from string
Explanation: Use match object or String#[] with regex to fetch groups.

37. HTTP request (Net::HTTP and Faraday)


Approach 1:
require 'net/http'
res = Net::HTTP.get(URI('https://api.example.com'))

Approach 2:
require 'faraday'
Faraday.get('https://api.example.com').body

Input / Output: Fetch remote resource


Explanation: Faraday is higher-level and nicer for complex requests; Net::HTTP is stdlib.

38. JSON parse/serialize


Approach 1:
require 'json'
h = JSON.parse('{"a":1}')
JSON.generate(h)

Approach 2:
Use ActiveSupport::JSON in Rails for additional features

Input / Output: Parse JSON strings to Ruby hashes and back


Explanation: Use stdlib JSON or ActiveSupport extensions in Rails.

39. ActiveRecord: where with LIKE and parameterization


Approach 1:
User.where('email LIKE ?', '%@gmail.com')

Approach 2:
User.where('name ILIKE ?', '%john%') # Postgres case-insensitive

Input / Output: Find users matching pattern


Explanation: Always use parameterized queries to avoid SQL injection.

40. ActiveRecord: scopes and chaining


Approach 1:
class User < ApplicationRecord
scope :active, ->{ where(active:true) }
scope :recent, ->{ order(created_at: :desc) }
end
# usage: User.active.recent.limit(10)

Approach 2:
Use lambda scopes to compose queries

Input / Output: Compose reusable query fragments


Explanation: Scopes return Relations enabling lazy chaining and SQL composition.

41. ActiveRecord: associations basics (belongs_to, has_many)


Approach 1:
class Post < ApplicationRecord
belongs_to :user
end
class User < ApplicationRecord
has_many :posts
end

Approach 2:
# Access: user.posts, post.user

Input / Output: Model associations allow navigation and joins


Explanation: Ensure foreign keys and indices for performance.

42. ActiveRecord: eager loading to avoid N+1


Approach 1:
users = User.includes(:posts).where(active:true)
users.each{|u| u.posts.each{|p| p.title}}

Approach 2:
Use preload or eager_load depending on use-case

Input / Output: Prevent extra queries when iterating associations


Explanation: includes decides between JOIN or separate queries; analyze logs for behavior.

43. ActiveRecord: find vs find_by vs find_by!


Approach 1:
User.find(1) # raises if missing
User.find_by(id:1) # nil if missing
User.find_by!(id:1) # raises ActiveRecord::RecordNotFound

Input / Output: Choosing appropriate finder depending on error handling needs


Explanation: Use find_by! when you want exceptions handled by Rails rescue handlers.

44. Validations: presence, uniqueness, format


Approach 1:
class User < ApplicationRecord
validates :email, presence:true, uniqueness:true, format: { with: /@/ }
end

Input / Output: Model validation examples


Explanation: Uniqueness should be enforced at DB level as well (unique index).

45. Transactions and save! vs save


Approach 1:
ActiveRecord::Base.transaction do
user.save!
order.save!
end

Approach 2:
Use save to avoid exceptions and handle return values

Input / Output: Transactional operations roll back on exceptions


Explanation: Use bang methods inside transactions to ensure rollback on failure.

46. Callbacks: before_save and pitfalls


Approach 1:
before_save :normalize_name
def normalize_name; self.name = name.strip.titleize; end

Input / Output: Callbacks run during model lifecycle


Explanation: Avoid heavy logic in callbacks; prefer service objects for complex flows.

47. Serializing attributes (JSON/text)


Approach 1:
serialize :preferences, JSON # stores hash in text column

Approach 2:
Use json column type in Postgres and store as real JSON for querying

Input / Output: Store structured data in columns


Explanation: Prefer native JSON types for queryability and efficiency when DB supports it.

48. Enum usage for status fields


Approach 1:
class Order < ApplicationRecord
enum status: { pending: 0, paid: 1, shipped: 2 }
end

Approach 2:
Use integer-backed enums for efficient storage

Input / Output: Provides helper methods like order.paid? and Order.paid


Explanation: Be careful when changing enum order; use explicit mapping to integers.

49. Pluck for selecting columns


Approach 1:
User.pluck(:id, :email) # returns array of arrays or values

Approach 2:
User.select(:id,:email).map{|u| [u.id, u.email]} # loads AR objects

Input / Output: Efficient column extraction without instantiating full AR objects


Explanation: Use pluck for large datasets to minimize memory.

50. find_in_batches & find_each for large datasets


Approach 1:
User.find_in_batches(batch_size: 1000) do |batch| batch.each{|u| process(u)} end

Approach 2:
User.find_each(batch_size: 1000) {|u| process(u)} # yields single records

Input / Output: Process large tables without loading all rows


Explanation: find_each is convenient for per-record processing; find_in_batches gives batch arrays.

51. Upsert (insert or update) - rails 6+


Approach 1:
User.upsert({id:1, name:'A'}, unique_by: :id)

Approach 2:
Model.insert_all([...]) for bulk insert with conflict handling

Input / Output: Insert or update depending on existing keys


Explanation: Upsert uses DB features; behavior may vary by adapter (Postgres best supported).
52. Counter cache for association counts
Approach 1:
class Comment < ApplicationRecord
belongs_to :post, counter_cache: true
end

Approach 2:
# Add posts.comments_count integer column with default 0

Input / Output: Keeps cached count in parent record


Explanation: Avoids COUNT queries for frequently displayed counts; ensure counter updated on delete/create.

53. Polymorphic association example


Approach 1:
class Image < ApplicationRecord
belongs_to :imageable, polymorphic: true
end
class Product < ApplicationRecord
has_many :images, as: :imageable
end

Input / Output: Single Image model belongs to different parents


Explanation: Useful for attachments; index on imageable_type and imageable_id recommended.

54. Nested attributes: accepts_nested_attributes_for


Approach 1:
class Post < ApplicationRecord
has_many :comments
accepts_nested_attributes_for :comments
end

Approach 2:
# In form: fields_for :comments to edit nested resources

Input / Output: Allows saving parent and children in one form


Explanation: Strong params must permit nested attributes (eg. comments_attributes: [...])

55. ActiveModel::Serializer / Jbuilder basics


Approach 1:
class UserSerializer < ActiveModel::Serializer
attributes :id, :name
end

Approach 2:
# Jbuilder: json.extract! @user, :id, :name in view

Input / Output: Serialize AR objects into JSON responses


Explanation: Choose serializer approach per project standards; AMS, Jbuilder, or Blueprinter are options.

56. Background jobs: ActiveJob with Sidekiq adapter


Approach 1:
class MyJob < ApplicationJob
def perform(user_id)
UserMailer.welcome(user_id).deliver_now
end
end
# enqueue: MyJob.perform_later(user.id)

Approach 2:
Use Sidekiq worker directly for performance and middleware features

Input / Output: Process async work decoupled from web requests


Explanation: Configure adapter (Sidekiq, Resque) in environment configs.

57. Send files: send_file vs send_data


Approach 1:
send_file user.avatar_path, disposition: 'attachment'

Approach 2:
send_data binary_data, filename: 'export.csv'

Input / Output: Serve files to clients from controller


Explanation: Use send_file for server files and send_data for generated content.

58. Pagination examples (kaminari/will_paginate)


Approach 1:
User.page(params[:page]).per(20) # kaminari

Approach 2:
User.paginate(page: params[:page], per_page: 20) # will_paginate

Input / Output: Return paginated AR relations


Explanation: Use gem of choice and render pagination controls in views.

59. Form helpers: form_with vs form_for


Approach 1:
<%= form_with(model: @post) do |f| %>
<%= f.text_field :title %>
<% end %>

Approach 2:
<%= form_for @post do |f| %> ... <% end %> # older style

Input / Output: Build HTML forms tied to models


Explanation: form_with is default in modern Rails (remote: true by default for AJAX).

60. Partial rendering and locals


Approach 1:
render partial: 'comment', locals: { c: comment }

Approach 2:
render 'comment', comment: comment # shorthand

Input / Output: Render reusable partial with passed variables


Explanation: Use locals to avoid relying on instance variables for clearer components.

61. Layouts and content_for


Approach 1:
# in controller: layout 'admin'
# in view: <% content_for :head do %> ... <% end %>

Approach 2:
yield :head in layout file to inject content

Input / Output: Structure application layout and inject per-view content


Explanation: content_for helps place scripts/styles in correct layout sections.

62. Flash messages usage


Approach 1:
flash[:notice] = 'Saved'
redirect_to root_path

Approach 2:
flash.now[:alert] = 'Error' # use with render

Input / Output: Transient messages displayed to users


Explanation: use flash.now when rendering same request; flash persists to next request.

63. Respond_to and format negotiation


Approach 1:
respond_to do |format|
format.html
format.json { render json: @post }
end

Input / Output: Serve different formats depending on request


Explanation: APIs often use respond_to for HTML/JSON/XML variants.

64. Cookies vs session (basic usage)


Approach 1:
session[:user_id] = user.id
cookies[:theme] = { value: 'dark', expires: 1.year.from_now }

Input / Output: Persistent and session-based storage


Explanation: Sessions default to cookie store; be mindful of size and security.

65. Rate limiting using rack-attack (basic config)


Approach 1:
# Example config in config/initializers/rack_attack.rb
Rack::Attack.throttle('req/ip', limit: 300, period: 5.minutes) do |req|
req.ip
end

Input / Output: Throttle requests per IP over time window


Explanation: Use middleware to protect against abuse at edge level.

66. CSV read/write


Approach 1:
require 'csv'
CSV.foreach('file.csv', headers:true) {|row| puts row['name'] }

Approach 2:
CSV.open('out.csv','w') {|csv| csv << ['a','b'] }

Input / Output: Read and write CSV files


Explanation: Use headers option for easier column access.
67. Image processing with MiniMagick
Approach 1:
MiniMagick::Image.open('in.jpg').resize '100x100'.write('out.jpg')

Approach 2:
Use ActiveStorage variants in Rails for on-the-fly resizing

Input / Output: Resize or transform images


Explanation: Prefer ActiveStorage variants when using Rails' built-in file management.

68. Tempfile use for safe temporary files


Approach 1:
t = Tempfile.new('prefix')
begin
t.write('data')
t.flush
ensure
t.close
t.unlink
end

Input / Output: Create temporary files safely and clean up


Explanation: Tempfile ensures unique temp filenames and auto-cleanup patterns.

69. Zip archive creation (rubyzip)


Approach 1:
require 'zip'
Zip::File.open('out.zip', Zip::File::CREATE) do |zip|
zip.add('file.txt','file.txt')
end

Input / Output: Create zip archives programmatically


Explanation: Use rubyzip gem for archive operations.

70. Detect MIME type


Approach 1:
require 'mime/types'
MIME::Types.type_for('file.png').first.content_type

Input / Output: Determine MIME types from file extensions


Explanation: Useful for uploads and setting response content-type headers.

71. Mailers: basics and preview


Approach 1:
class UserMailer < ApplicationMailer
def welcome(user)
@user = user
mail(to: @user.email, subject: 'Welcome')
end
end

Approach 2:
# Preview: UserMailerPreview in test/mailers/previews

Input / Output: Send transactional emails


Explanation: Configure delivery methods per environment (smtp, sendgrid, etc.).
72. Generate PDF via Prawn (basic)
Approach 1:
Prawn::Document.generate('file.pdf') do
text 'Hello PDF'
end

Input / Output: Create simple PDF files with Prawn


Explanation: Prawn is a Ruby PDF generator; for Rails integrate into controllers to send PDFs.

73. Excel generation with axlsx


Approach 1:
# create xlsx using axlsx gem
Axlsx::Package.new do |p|
p.workbook.add_worksheet(name: 'Sheet1') do |sheet|
sheet.add_row ['A','B']
end
p.serialize('file.xlsx')
end

Input / Output: Generate .xlsx spreadsheets


Explanation: Use gem and serve as attachment; mind memory for large sheets (streaming options exist).

74. Regex substitution and groups


Approach 1:
'abc123'.gsub(/(\d+)/, 'X') # replace digits

Approach 2:
'Name: John'.match(/Name: (\w+)/)[1] # capture group

Input / Output: Use regex to find and replace or capture parts


Explanation: Ruby's regex engine is powerful; avoid catastrophic backtracking patterns.

75. Delegate pattern


Approach 1:
class Order < ApplicationRecord
belongs_to :user
delegate :email, to: :user
end

Input / Output: Delegate methods to associated objects


Explanation: Reduces boilerplate forwarding methods; helpful in presenters.

76. Use of service object pattern (conceptual)


Approach 1:
# app/services/create_order.rb
class CreateOrder
def initialize(params); @params=params; end
def call
# validate, create order, notify
end
end

Input / Output: Encapsulate business logic outside models/controllers


Explanation: Helps keep controllers thin and models focused on persistence.
77. Testing: RSpec model validation example
Approach 1:
RSpec.describe User, type: :model do
it { should validate_presence_of(:email) }
end

Input / Output: Model test checking validations


Explanation: Use shoulda-matchers for concise validation specs.

78. Testing: controller request spec basic


Approach 1:
RSpec.describe PostsController, type: :request do
it 'returns 200' do
get posts_path
expect(response).to have_http_status(:ok)
end
end

Input / Output: Test controller endpoints return expected statuses


Explanation: Use request specs to test full Rails stack behavior.

79. Devise basics: authenticate_user! filter


Approach 1:
before_action :authenticate_user! # provided by Devise

Input / Output: Require authentication for controller actions


Explanation: Devise provides helpers and routes for auth flows.

80. ActiveStorage attach and variants


Approach 1:
@user.avatar.attach(io: File.open('a.jpg'), filename: 'a.jpg')

Approach 2:
@user.avatar.variant(resize: '100x100').processed

Input / Output: Attach files and generate variants


Explanation: ActiveStorage handles storage backends (local, S3) and direct uploads.

81. ActionCable simple broadcasting


Approach 1:
ActionCable.server.broadcast 'room_channel', message: 'hi'

Input / Output: Broadcast realtime messages to subscribers


Explanation: Use channels for websockets; scale with Redis for multiple servers.

82. Middleware insertion example


Approach 1:
# config/application.rb
config.middleware.use MyCustomMiddleware

Input / Output: Insert or configure Rack middleware


Explanation: Useful for cross-cutting concerns like logging/authentication/throttling.

83. Internationalization (I18n) basics


Approach 1:
I18n.t('hello') # uses config/locales/*.yml

Input / Output: Translate strings using YAML locale files


Explanation: Use interpolation and pluralization features for robust locales.

84. Caching fragment & action caching basics


Approach 1:
<% cache(@post) do %>
render @post
<% end %>

Approach 2:
caches_action :index # for action caching via gem

Input / Output: Cache view fragments to reduce rendering cost


Explanation: Invalidate caches on model changes via touch or expire methods.

85. Securing file uploads (validate content type)


Approach 1:
validates :avatar, content_type: ['image/png','image/jpg'] # via ActiveStorage validations gem

Input / Output: Ensure only allowed types are accepted


Explanation: Combine client-side checks and server-side validations for security.

86. Background job retry and error handling


Approach 1:
class MyJob < ApplicationJob
retry_on SomeError, attempts: 3 do |job, err|
# handle
end
end

Input / Output: Configure retries for transient failures


Explanation: ActiveJob provides retry helpers; Sidekiq offers advanced retry/exponential backoff.

87. Webhooks: verify signature


Approach 1:
sig = request.headers['X-Signature']
expected = OpenSSL::HMAC.hexdigest('sha256', secret, request.raw_post)
head :unauthorized unless ActiveSupport::SecurityUtils.secure_compare(sig, expected)

Input / Output: Verify webhook body against shared secret to avoid spoofing
Explanation: Use constant-time compare to avoid timing attacks.

88. Rate-limited API endpoints (controller-level)


Approach 1:
def index
if request.ip_rate_exceeded?
head :too_many_requests
else
render json: Model.all
end
end

Input / Output: Implement simple per-IP rate limits


Explanation: Prefer middleware (rack-attack) for production-grade throttling.

89. OAuth flow concept (OmniAuth)


Approach 1:
# configure OmniAuth and handle callback
def callback
user = User.from_omniauth(auth_hash)
end

Input / Output: Third-party authentication using OAuth providers


Explanation: OmniAuth provides middleware to handle provider callbacks and info.

90. Secure headers and Content Security Policy (CSP)


Approach 1:
# config/initializers/content_security_policy.rb
policy.default_src :self
policy.script_src :self, :https

Input / Output: Mitigate XSS and resource injection by specifying CSP


Explanation: Adjust policies carefully to allow required external resources.

91. Performance: eager loading vs lazy loading


Approach 1:
User.includes(:posts).where(active:true) # eager load posts

Approach 2:
User.where(active:true) # lazy until accessed

Input / Output: Reduce N+1 queries by eager loading associations


Explanation: Measure SQL queries and optimize accordingly.

92. SQL injection avoidance: parameterized queries


Approach 1:
User.where('email = ?', params[:email])

Approach 2:
User.find_by(email: params[:email])

Input / Output: Avoid string interpolation in SQL fragments


Explanation: ActiveRecord parameterization protects against injection.

93. Database indexing basics: migration example


Approach 1:
add_index :users, :email, unique: true

Input / Output: Add DB index for faster lookups and uniqueness


Explanation: Indexes speed reads but add write overhead; choose columns wisely.
94. Using transactions with retry semantics
Approach 1:
ApplicationRecord.transaction(requires_new: true) do
# critical section
end

Input / Output: Wrap critical DB operations atomically


Explanation: Combine with optimistic locking for certain concurrency scenarios.

95. Optimistic locking with lock_version


Approach 1:
# migration: add_column :table, :lock_version, :integer, default: 0
# AR will raise ActiveRecord::StaleObjectError on conflicts

Input / Output: Prevent lost updates when multiple writers modify same row
Explanation: Use rescue to handle stale object exceptions and retry or show message.

96. Soft delete pattern (acts_as_paranoid or custom)


Approach 1:
# add deleted_at column and scope
scope :active, ->{ where(deleted_at: nil) }

Input / Output: Mark records as deleted instead of removing


Explanation: Keep indexes and uniqueness in mind; adjust queries to exclude soft-deleted records.

97. Background migration / data migration strategies


Approach 1:
# Use runners or background jobs to migrate large datasets gradually

Input / Output: Migrate large data without blocking app or causing downtime
Explanation: Break into batches and monitor progress; use feature flags if changing behavior.

98. Command line script with Thor or Rake task


Approach 1:
# lib/tasks/import.rake
task :import => :environment do
Importer.run
end

Approach 2:
Use Thor to build CLI with commands and options.

Input / Output: Create reusable tasks or CLIs for maintenance


Explanation: Rake tasks run in app context when needed.

99. Security: parameter filtering in logs


Approach 1:
# config/initializers/filter_parameter_logging.rb
Rails.application.config.filter_parameters += [:password, :token]

Input / Output: Avoid leaking sensitive params into logs


Explanation: Filter parameters to protect secrets in logs and error reports.

100. Monitoring: integrate Sentry or similar


Approach 1:
Raven.configure do |config|
config.dsn = ENV['SENTRY_DSN']
end

Input / Output: Capture exceptions and performance data in Sentry


Explanation: Set environment-specific configs and ignore noisy exceptions.

101. Deployment basics: Capistrano or Docker approach


Approach 1:
# Capistrano deploy scripts or Dockerfile + docker-compose for containerized deploy

Input / Output: Common deployment patterns for Rails apps


Explanation: Choose based on team expertise; use CI/CD pipelines for repeatable releases.

102. Data validation: custom validator class


Approach 1:
class EmailFormatValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
record.errors.add(attribute, 'invalid') unless value =~ /@/
end
end
# use: validates :email, email_format: true

Input / Output: Encapsulate complex validation logic in reusable validators


Explanation: Keeps models cleaner and validator can be reused across models.

103. Security: encrypt attributes using ActiveSupport::MessageEncryptor


Approach 1:
key = ActiveSupport::KeyGenerator.new('password').generate_key('salt', 32)
crypt = ActiveSupport::MessageEncryptor.new(key)
enc = crypt.encrypt_and_sign('sensitive')
crypt.decrypt_and_verify(enc)

Input / Output: Encrypt sensitive data before storing


Explanation: Rails 7 has ActiveRecord::Encryption for built-in support.

104. Refactoring: extract method and single responsibility principle


(conceptual)
Approach 1:
# Move repeated logic into private methods or service objects

Input / Output: Improve readability and testability by extracting methods


Explanation: Aim for small methods with clear responsibilities.

You might also like