All notes
Rails

Intro

rubyOnRails.org: getting started.

Rails philosophy

Command line

runner



##### scripts/run.rb
require 's_job'
SJob.new(ARGV[0]).run_manually

##### lib/s_job.rb
Dir[Rails.root.join("lib/s_jobs/*")].each {|file| require file unless File.directory?(file)}

class SJob
  def initialize command
    @command = command
  end

  def run
  # Do something.
  end

  def run_manually
  # Do something with @command (which is actually "command_str").
  end
end

rails runner scripts/run.rb command_str

Run a rb file



# https://stackoverflow.com/questions/10313181/pass-ruby-script-file-to-rails-console
rails new AppName
# Short for: rails runner
rails r PATH_TO_RUBY_FILE

# Or run it with load inside the rails console
load './path/to/foo.rb'

# Run a script:
# http://stackoverflow.com/questions/9757261/how-do-i-run-a-ruby-file-in-a-rails-environment
rails runner "MyModule.run 'input_str'"

server

-p, --port=port Default: 3000
-b, --binding=IP

Rails s not working, only allow new

On 3.2, it checks for a file at "script/rails". Now that 4.0 has been released, it looks for either "script/rails" or "bin/rails". SO: why doesn't rails s work from the app directory.

generate



rails generate scaffold post title:string body:text
# create  app/models/post.rb
# create  test/unit/post_test.rb
# create  test/fixtures/posts.yml

rails generate integration_test user_flows
# exists  test/integration/
# create  test/integration/user_flows_test.rb

#---------- Controller and its test:

bin/rails generate scaffold_controller article title:string body:text
# create  app/controllers/articles_controller.rb
# ...
# invoke  test_unit
# create    test/controllers/articles_controller_test.rb

#### Just create controller test:
# Use singular here: article.
bin/rails generate test_unit:scaffold article
# invoke  test_unit
# create test/controllers/articles_controller_test.rb

#---------- Models

rails generate model NAME [field[:type][:index] field[:type][:index]] [options]
# Timestamps are added by default, so you don't have to specify them by hand as 'created_at:datetime updated_at:datetime'.
# if --parent option is given, it's used as superclass of the created model. This allows you create Single Table Inheritance models.

rails g model PreAuthLandingPage --parent LayoutPage

#---------- Migrations

rails g migration AddPageRefToCompany page:references
# Generate - add_reference :companies, :page, foreign_key: true


#---------- All

rails g --help

# All generators
Rails:
  assets
  channel
  controller
  generator
  helper
  integration_test
  jbuilder
  job
  mailer
  migration
  model
  observer
  resource
  responders_controller
  scaffold
  scaffold_controller
  task

ActiveRecord:
  active_record:oauth_consumer
  active_record:oauth_provider
  active_record:observer

Annotate:
  annotate:install

Bullet:
  bullet:install

DelayedJob:
  delayed_job
  delayed_job:active_record
  delayed_job:upgrade

Erb:
  erb:oauth_consumer
  erb:oauth_provider

Geocoder:
  geocoder:config
  geocoder:maxmind:geolite_city
  geocoder:maxmind:geolite_country

Haml:
  haml:oauth_consumer
  haml:oauth_provider

Js:
  js:assets

Minitest:
  minitest:controller
  minitest:generator
  minitest:helper
  minitest:install
  minitest:integration
  minitest:job
  minitest:mailer
  minitest:model
  minitest:scaffold

Mongoid:
  mongoid:oauth_consumer
  mongoid:oauth_provider

OauthConsumer:
  oauth_consumer

OauthProvider:
  oauth_provider

Qunit:
  qunit

Responders:
  responders:install

RpushConfig:
  rpush_config

RpushMigration:
  rpush_migration

TestUnit:
  test_unit:generator
  test_unit:oauth_provider
  test_unit:observer
  test_unit:plugin

WebpackRails:
  webpack_rails:install

Installation

Rerequisites:

Install development kit. github: development kit.


# Extract develop kits by clicking on the sfx.exe.
cd /path/to/extracted
ruby dk.rb init
ruby dk.rb review
ruby dk.rb install
# Test installation
gem install json --platform=ruby

Install rails:


gem install rails
# Install specific version:
gem install rails -v 4.1

rails -v

Debugger

byebug

rubyOnRails: debugging.


require "byebug"; byebug

# you can make them conditional:
byebug if foo == “bar”

fleebleWidget.co.uk.

Display

e[val] — a.k.a. “p” <expression>
  Evaluate <expression> and display result. By default, you can also just type the expression without any command and get the same thing (disabled by using set noautoeval).
pp
  Evaluate expression and pretty-print the result.
putl
  Evaluate an expression with an array result and columnize the output.
ps
  Evaluate an expression with an array result, sort and columnize the output.

disp[lay] <expression>
  Automatically display <expression> every time the program halts. With no argument, lists the current display expressions.

info display
  List all current display expressions.
undisp[lay] <number>
disable display <number>
enable display <number>
help

l=
l-
l startLine-endLine

b [nnn]
delete [nnn]
info break

where
frame [nnn]

instance_variables
var all/args/const/global/instance/local

# Watch
display varName
undisplay [nnn]

enable/disable breakpoints

# List all active catchpoints:
catch

continue
# Set a one-time breakpoint on line 'n'
continue n
finish [n]

edit [file:n]

Useful rails functions

# List all locals:
local_variables

Features

Autoloading

urbanAutomaton.com: rails autoloading hell.



C = "At the top level"

module A
  C = "In A"
end

module A
  module B
    puts Module.nesting # => [A::B, A]
    puts C              # => "In A"
  end
end

module A::B
  puts Module.nesting # => [A::B]
  puts C              # => "At the top level"
end

File Lookup Rules:


MyModule::SomeClass # => my_module/some_class.rb, looks within $autoload_paths.

rubyOnRails: autoloading.

Assets

Turnning debugging off

rails guide. You can turn off debug mode by updating config/environments/development.rb to include:


config.assets.debug = false

# With regards to Rails 4.2 and sprockets-rails 2.3.3 this is working:
config.asset.debug = false
# and then optionally to reopen it:
?debug_assets=1

Refresh release bundle

guides.rubyOnRails.org: precompiling assets.


rake assets:precompile

Manifest Files and Directives

guides.rubyOnRails.org.

Sprockets uses manifest files to determine which assets to include and serve. These manifest files contain directives - instructions that tell Sprockets which files to require in order to build a single CSS or JavaScript file.

For example, a new Rails application includes a default app/assets/javascripts/application.js containing the following lines:


// ...
//= require rails-ujs
//= require turbolinks
//= require_tree .

Rails also creates a default app/assets/stylesheets/application.css file which contains these lines:


/* ...
*= require_self
*= require_tree .
*/

Directory structure

Any assets under "public" will be served as static files by the application or web server when config.public_file_server.enabled is set to true.

You should use "app/assets" for files that must undergo some pre-processing before they are served. In production, Rails precompiles these files to public/assets by default. The precompiled copies are then served as static assets by the web server.

Rails JS include. Here are guidelines for selecting a location for your scripts:

Use app/assets/javascripts for JavaScript you create for your application.
Use lib/assets/javascripts for scripts that are shared by many applications (but use a gem if you can).
Use vendor/assets/javascripts for copies of jQuery plugins, etc., from other developers.


<%= javascript_include_tag params[:controller] %> or <%= stylesheet_link_tag
params[:controller] %>

Search Path

When a file is referenced from a manifest or a helper, Sprockets searches the three default asset locations for it.

The default locations are: the images, javascripts and stylesheets directories under the app/assets folder, but these subdirectories are not special - any path under assets/* will be searched. For example, these files would be referenced in a manifest like this:

app/assets/javascripts/home.js
lib/assets/javascripts/moovinator.js
vendor/assets/javascripts/slider.js
vendor/assets/somepackage/phonebox.js

//= require home
//= require moovinator
//= require slider
//= require phonebox
Assets inside subdirectories can also be accessed.

app/assets/javascripts/sub/something.js
is referenced as:

//= require sub/something
You can view the search path by inspecting Rails.application.config.assets.paths in the Rails console.

Language Reference

Data types

String


# Capitalizes the first word, turns underscores into spaces, and strips a trailing ‘_id’ if present.
'employee_salary'.humanize              # => "Employee salary"
'author_id'.humanize                    # => "Author"
'author_id'.humanize(capitalize: false) # => "author"
'_id'.humanize                          # => "Id"

# titleize
'man from the boondocks'.titleize # => "Man From The Boondocks"
'x-men: the last stand'.titleize  # => "X Men: The Last Stand"

'Module'.constantize  # => Module
'Class'.constantize   # => Class
'blargle'.constantize # => NameError: wrong constant name blargle

# "rails c" in rails project root to enter the rails console:
a="page_version"
a.classify
# "PageVersion"
a.camelize
# "PageVersion"

#----- underscore
# The reverse of camelize. It will also change ‘::’ to ‘/’ to convert namespaces to paths.
'ActiveModel'.underscore         # => "active_model"
'ActiveModel::Errors'.underscore # => "active_model/errors"

Modules

Functions



# http://stackoverflow.com/questions/619840/rails-i-cant-call-a-function-in-a-module-in-lib-what-am-i-doing-wrong
module Foo
  def self.method_one
  end

  def Foo.method_two
  end

  class << self
    def method_three
    end
  end
end

# http://apidock.com/ruby/Module/module_function
module Mod
  def one
    "This is one"
  end
  module_function :one
end
class Cls
  include Mod
  def call_one
    one
  end
end
Mod.one     #=> "This is one"
c = Cls.new
c.call_one  #=> "This is one"
module Mod
  def one
    "This is the new one"
  end
end
Mod.one     #=> "This is one"
c.call_one  #=> "This is the new one"

Functions

extract_options!



# https://apidock.com/rails/Array/extract_options%21

def options(*args)
  p args
  args.extract_options!
end

options(1, 2)        # => {}
options(1, 2, a: :b, c: :c) # => {:a=>:b, :c=>:c}
# Output from "p args"
# [1, 2]
# [1, 2, {:a=>:b, :c=>:c}]

Configuration

edgeGuides: configuration.

In "config/database.yml":


development:
  adapter: mysql2
  encoding: utf8
  database: blog_development
  pool: 5
  username: root
  password:
  socket: /tmp/mysql.sock

Rails packages

github.com: rails.

What is the naming rule behind action and active

SO: what is the naming rule behind rails parts.

Action* like ActionPack or ActionMailer, they pertain to an action performed within the Rails application.
Active* like ActiveRecord, ActiveSupport or ActiveModel etc., it somehow relates to providing some useful functionality to your Rails applications business logic.

DB

Basics

SO: how to find a model class from its table name.


# Convert table_name into TableName and use it for DB query:
# classify: convert "table_name" to "TableName".
# constantize: convert your string to a constant.
"table_name".classify.constantize.where(CONDITION)

codeTheory.in: rails escaping values.


Model.connection.quote("hel'lo")
# "'hel\\'lo'"
Model.sanitize("hel'lo")
# "'hel\\'lo'"

# So you can also do this:

ActiveRecord::Base.connection.quote("hel'lo")
# "'hel\\'lo'"
ActiveRecord::Base.sanitize("hel'lo")
# "'hel\\'lo'"

Callbacks

Avoid triggering callbacks

Another way to update fields without triggering after_save and other callbacks is update_column.

after_update called not after the object updating ended

SO: understand after_update callback in Rails 4.

"after_save, after_create, after_update" are called within the transaction block, so they will be executed before executing the SQL statement.

If you want to do something when the statement execution is completed, you should use "after_commit" callback.

Code walkthrough

In the begging comments in "activemodel-4.2.7.1/lib/active_model/callbacks.rb", there are lots of explanations.

Here is how you can make your own class having callbacks by means of active_model:



class MyModel
  extend ActiveModel::Callbacks

  # Then define a list of methods that you want callbacks attached to:
  define_model_callbacks :create, :update

  # This will provide all three standard callbacks (before, around and after)
  # for both the <tt>:create</tt> and <tt>:update</tt> methods. To implement,
  # you need to wrap the methods you want callbacks on in a block so that the
  # callbacks get a chance to fire:
  def create
    run_callbacks :create do
      # Your create action methods here
    end
  end

  # Then in your class, you can use the +before_create+, +after_create+ and +around_create+ methods, just as you would in an Active Record model.
  before_create :action_before_create
  def action_before_create
    # Your code here
  end

  # When defining an around callback remember to yield to the block, otherwise it won't be executed:
  around_create :log_status
  def log_status
    puts 'going to call the block...'
    yield
    puts 'block successfully called.'
  end

end

Callback debug

From "lib/active_record/callbacks.rb":



# To find all callbacks in the before_save callback chain:
Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }

# To further check if the before_save chain contains a proc defined as <tt>rest_when_dead</tt> use the <tt>filter</tt> property of the callback object:
Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }.collect(&:filter).include?(:rest_when_dead)

Query



User.order(:name, email: :desc)
=> SELECT "users".* FROM "users" ORDER BY "users"."name" ASC, "users"."email" DESC

User.order('name DESC, email')
=> SELECT "users".* FROM "users" ORDER BY name DESC, email

Force load association on model instance

SO: force load association on model instance.



class Post < ActiveRecord::Base
  has_many :comments

  def last_comment
    comments.load_target unless comments.loaded?
    comments.last
  end
end

NQuery, N+1

SO: rails includes method and avoiding N+1 query.



# This code executes a database call 11 times to do something pretty trivial, because it has to do each lookup, one at a time.
clients = Client.limit(10)
clients.each do |client|
  puts client.address.postcode
end

# Compare the above code to this example:
# This code executes a database call twice, because all of the necessary associations are included at the onset.
clients = Client.includes(:address).limit(10)
clients.each do |client|
  puts client.address.postcode
end 

Create, new



# Create generates the object and saves. new only generates the object.

o = Object.new(:foo => 'bar')
o.save
## is the same as
o = Object.create(:foo => 'bar')

# build is an alias for new.
# https://github.com/rails/rails/blob/959fb8ea651fa6638aaa7caced20d921ca2ea5c1/activerecord/lib/active_record/relation.rb#L84
alias build new

# Difference between create and create!
# For create!, an exception is raised instead of just failing and returning false.
# https://stackoverflow.com/questions/6316821/rails-create-and-create-methods-ror-3-tutorial

# Similarly,
# save! will raise an error if not successful.
# save will return true or false.

Migrations


rails g migration AddTimestampsToUser created_at:datetime updated_at:datetime

class AddTimestampsToUser < ActiveRecord::Migration
  def change
    add_column :users, :created_at, :datetime
    add_column :users, :updated_at, :datetime
  end
end

You can always go to db/schema.rb to see how to write migrations after rake db:migrate.


## Seeing that the db/schema.rb has this:
#  t.binary   "uuid",                  limit: 255
#  add_index "my_tables", ["uuid"], name: "index_my_tables_on_uuid", unique: true, length: {"uuid"=>23}, using: :btree

unless column_exists? :my_tables, :uuid
  add_column :my_tables, :uuid, :binary, limit: 255, unique: true
end

unless index_exists? :my_tables, :uuid
  add_index :my_tables, :uuid, unique: true, length: {:uuid=>23}
  # index name is supposed to be: "index_my_tables_on_uuid"
end

Table already exists


# Firstly, manually delete the database, e.g. my_test

RAILS_ENV=test bundle exec rake db:create
RAILS_ENV=test bundle exec rake db:migrate
# RAILS_ENV=test bundle exec rake db:populate # test doesn't need population?

Seeding

xyzpub.com.

With the file db/seeds.rb, the Rails gods have given us a way of feeding default values easily and quickly to a fresh installation.

wcfNote: what's the difference between db/seeds and fixtures? db/seeds can be used in development environment.

Just ruby code



country_list = [
  [ "Germany", 81831000 ],
  [ "France", 65447374 ],
  [ "Belgium", 10839905 ],
  [ "Netherlands", 16680000 ]
]

country_list.each do |name, population|
  Country.create( name: name, population: population )
end

Generating seeds.rb From Existing Data




UTF-8


#--- If you want to use UTF-8 characters in your db/seeds.rb, then you need to enter the line
# ruby encoding: utf-8

ActionController

Base

render

apidock.com.



#---------- Rendering a template

render template: "posts/index.html"
render template: "posts/index.html", layout: false

#---------- Render json

# Renders '{"name": "David"}'
render :json => {:name => "David"}.to_json
# not necessary to call to_json on the object you want to render, since render will automatically do that for you:
# Also renders '{"name": "David"}'
render :json => {:name => "David"}

# Sometimes the result isn’t handled directly by a script (such as when the request comes from a SCRIPT tag), so the :callback option is provided for these cases.
# Renders 'show({"name": "David"})'
render :json => {:name => "David"}.to_json, :callback => 'show'

#---------- Render JS

# Renders "alert('hello')" and sets the mime type to text/javascript
render :js => "alert('hello')"

#---------- Rendering with status and location headers

render :xml => post.to_xml, :status => :created, :location => post_url(post)

#---------- Render inline

# Renders "hello, hello, hello, again"
render :inline => "<%= 'hello, ' * 3 + 'again' %>"

# Renders "<p>Good seeing you!</p>" using Builder
render :inline => "xml.p { 'Good seeing you!' }", :type => :builder

# Renders "hello david"
render :inline => "<%= 'hello ' + name %>", :locals => { :name => "david" }

DoubleRender error



# The following will construct DoubleRender error
render_not_found
self.response.status = 200

Parameters

permit

apidock.com: permit.



params = ActionController::Parameters.new(user: { name: 'Francesco', age: 22, role: 'admin' })
permitted = params.require(:user).permit(:name, :age)
permitted.permitted?      # => true
permitted.has_key?(:name) # => true
permitted.has_key?(:age)  # => true
permitted.has_key?(:role) # => false. Only permitted scalars pass the filter.

#----------

params = ActionController::Parameters.new({
  person: {
    contact: {
      email: '[email protected]',
      phone: '555-1234'
    }
  }
})

params.require(:person).permit(:contact)
# => {}
# You also need to specify which attributes inside the hash should be whitelisted. So the the following works:

params.require(:person).permit(contact: :phone)
# => {"contact"=>{"phone"=>"555-1234"}}

params.require(:person).permit(contact: [ :email, :phone ])
# => {"contact"=>{"email"=>"[email protected]", "phone"=>"555-1234"}}

CSRF

medium.com.



#---------- To enable CSRF protection

# in application_controller.rb
protect_from_forgery with: :exception

# in application.html.erb:
<%= csrf_meta_tags %>

#---------- In detail

# actionview/lib/action_view/helpers/csrf_helper.rb
def csrf_meta_tags
  if protect_against_forgery?
    [
      tag("meta", name: "csrf-param", content: request_forgery_protection_token),
      tag("meta", name: "csrf-token", content: form_authenticity_token)
    ].join("\n").html_safe
  end
end

Guides

Passing Data From the Controller to the View

docs.oracle.com.



# Open <JRUBY_HOME>/samples/hello/app/controllers/home_controller.rb in a text editor.

class HomeController < ApplicationController
  def index
  @hello_message = "Welcome to JRuby on Rails on the Sun GlassFish Enterprise Server"
  end
end

# Open <JRUBY_HOME>/samples/hello/app/views/home/index.html.erb file in a text editor.

 <%= @hello_message %>

ActionView

Helpers

AssetTagHelper

javascript_include_tag

apidock.com: javascript_include_tag.

Relative paths are assumed to be relative to "assets/javascripts", full paths are assumed to be relative to the document root.



javascript_include_tag "xmlhr"
# => <script src="/assets/xmlhr.js?1284139606"></script>

javascript_include_tag "common.javascript", "/elsewhere/cools"
# => <script src="/assets/common.javascript?1284139606"></script>
#    <script src="/elsewhere/cools.js?1423139606"></script>

javascript_include_tag "http://www.example.com/xmlhr"
# => <script src="http://www.example.com/xmlhr"></script>

CaptureHelper

content_for


#----- create a layout with multiple yielding regions:
<html>
  <head>
  <%= yield :head %>
  </head>
  <body>
  <%= yield %>
  </body>
</html>

#----- The content_for method allows you to insert content into a named yield block in your layout.
<% content_for :head do %>
  <title>A simple page</title>
<% end %>
<p>Hello, Rails!</p>

# The result of rendering this page into the supplied layout would be this HTML:
<html>
  <head>
  <title>A simple page</title>
  </head>
  <body>
  <p>Hello, Rails!</p>
  </body>
</html>


<% content_for :not_authorized do %>
  alert('You are not authorized to do that!')
<% end %>

#----- You can then use content_for :not_authorized anywhere in your templates.
<%= content_for :not_authorized if current_user.nil? %>
# This is equivalent to:
<%= yield :not_authorized if current_user.nil? %>
# But calling yield doesn’t work in helper modules, while content_for does.

#----- content_for, however, can also be used in helper modules.

module StorageHelper
  def stored_content
    content_for(:storage) || "Your storage is empty"
  end
end

# This helper works just like normal helpers.
<%= stored_content %>

url_helper

check_box, check_box_tag

apidock.com.

Use "check_box" preferably:

The HTML specification says unchecked check boxes are not successful, and thus web browsers do not send them. Unfortunately this introduces a gotcha: if an Invoice model has a paid flag, and in the form that edits a paid invoice the user unchecks its check box, no paid parameter is sent.
To prevent this the helper generates an auxiliary hidden field before the very check box. The hidden field has the same name and its attributes mimic an unchecked check box.
This way, the client either sends only the hidden field (representing the check box is unchecked), or both fields. Since the HTML specification says key/value pairs have to be sent in the same order they appear in the form, and parameters extraction gets the last occurrence of any repeated key in the query string, that works for ordinary forms.


#---------- check_box

# This object must be an instance object (@object) and not a local object. It’s intended that method returns an integer and if that integer is above zero, then the checkbox is checked.

# Let's say that @post.validated? is 1:
check_box("post", "validated")
# => <input name="post[validated]" type="hidden" value="0" />
#    <input checked="checked" type="checkbox" id="post_validated" name="post[validated]" value="1" />

# Let's say that @puppy.gooddog is "no":
check_box("puppy", "gooddog", {}, "yes", "no")
# => <input name="puppy[gooddog]" type="hidden" value="no" />
#    <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" />

check_box("eula", "accepted", { class: 'eula_check' }, "yes", "no")
# => <input name="eula[accepted]" type="hidden" value="no" />
#    <input type="checkbox" class="eula_check" id="eula_accepted" name="eula[accepted]" value="yes" />

#----- No hidden field?

# wcfNote: the key is, always use "true" "false" instead of just true, false.

= f.check_box :public, {}, true, false
# <input id="event_public" name="event[public]" type="checkbox" value="true" />

and:

= f.check_box :public, {}, "true", "false"
# <input name="event[public]" type="hidden" value="false" />
# <input id="event_public" name="event[public]" type="checkbox" value="true" />


#---------- check_box_tag

check_box_tag(name, value = "1", checked = false, options = {})

check_box_tag 'receive_email', 'yes', true
# => <input checked="checked" id="receive_email" name="receive_email" type="checkbox" value="yes" />

check_box_tag 'tos', 'yes', false, class: 'accept_tos'
# => <input class="accept_tos" id="tos" name="tos" type="checkbox" value="yes" />

check_box_tag 'eula', 'accepted', false, disabled: true
# => <input disabled="disabled" id="eula" name="eula" type="checkbox" value="accepted" />

link_to



link_to "Profile", @profile
# => <a href="/profiles/1">Profile</a>
# in place of the older more verbose, non-resource-oriented (e.g. the following is NOT RECOMMENDED)
link_to "Profile", controller: "profiles", action: "show", id: @profile
# => <a href="/profiles/show/1">Profile</a>

link_to "Profiles", profiles_path
# => <a href="/profiles">Profiles</a>
# is better than
link_to "Profiles", controller: "profiles"
# => <a href="/profiles">Profiles</a>

<%= link_to(@profile) do %>
  <strong><%= @profile.name %></strong> -- <span>Check it out!</span>
<% end %>
# => <a href="/profiles/1">
       <strong>David</strong> -- <span>Check it out!</span>
     </a>

# Classes and ids for CSS are easy to produce:
link_to "Articles", articles_path, id: "news", class: "article"
# => <a href="/articles" class="article" id="news">Articles</a>

# Be careful when using the older argument style, as an extra literal hash is needed:
link_to "Articles", { controller: "articles" }, id: "news", class: "article"
# => <a href="/articles" class="article" id="news">Articles</a>

# Leaving the hash off gives the wrong link:
link_to "WRONG!", controller: "articles", id: "news", class: "article"
# => <a href="/articles/index/news?class=article">WRONG!</a>

# +link_to+ can also produce links with anchors or query strings:
link_to "Comment wall", profile_path(@profile, anchor: "wall")
# => <a href="/profiles/1#wall">Comment wall</a>

link_to "Ruby on Rails search", controller: "searches", query: "ruby on rails"
# => <a href="/searches?query=ruby+on+rails">Ruby on Rails search</a>

link_to "Nonsense search", searches_path(foo: "bar", baz: "quux")
# => <a href="/searches?foo=bar&amp;baz=quux">Nonsense search</a>

# The only option specific to +link_to+ (<tt>:method</tt>) is used as follows:
link_to("Destroy", "http://www.example.com", method: :delete)
# => <a href='http://www.example.com' rel="nofollow" data-method="delete">Destroy</a>

# You can also use custom data attributes using the <tt>:data</tt> option:
link_to "Visit Other Site", "http://www.rubyonrails.org/", data: { confirm: "Are you sure?" }
# => <a href="http://www.rubyonrails.org/" data-confirm="Are you sure?">Visit Other Site</a>

# Also you can set any link attributes such as <tt>target</tt>, <tt>rel</tt>, <tt>type</tt>:
link_to "External link", "http://www.rubyonrails.org/", target: "_blank", rel: "nofollow"
# => <a href="http://www.rubyonrails.org/" target="_blank" rel="nofollow">External link</a>

ActionDispatch

Assertions

assert_redirected_to



# assert that the redirection was to the "index" action on the WebLogController
assert_redirected_to controller: "web_log", action: "index"

# assert that the redirection was to the named route login_url
assert_redirected_to login_url

# assert that the redirection was to the url for @customer
assert_redirected_to @customer

# asserts that the redirection matches the regular expression
assert_redirected_to %r(\Ahttp://example.org)
Can't save a record to db https://stackoverflow.com/questions/21094219/rails-4-cant-save-a-record-to-db user.errors

flash

api.rubyOnRails.org.

The flash provides a way to pass temporary primitive-types (String, Array, Hash) between actions. Anything you place in the flash will be exposed to the very next action and then cleared out. This is a great way of doing notices and alerts, such as a create action that sets flash[:notice] = "Post successfully created" before redirecting to a display action that can then expose the flash to its template. Actually, that exposure is automatically done.



class PostsController < ActionController::Base
  def create
    # save post
    flash[:notice] = "Post successfully created"
    redirect_to @post
  end

  def show
    # doesn't need to assign the flash notice to the template, that's done automatically
  end
end

show.html.erb
  <% if flash[:notice] %>
    <div class="notice"><%= flash[:notice] %></div>
  <% end %>

#---------- Since the notice and alert keys are a common idiom, convenience accessors are available:

flash.alert = "You must be logged in"
flash.notice = "Post successfully created"

#---------- More

# https://api.rubyonrails.org/classes/ActionDispatch/Flash/FlashHash.html

flash.discard              # discard the entire flash at the end of the current action
flash.discard(:warning)    # discard only the "warning" entry at the end of the current action

flash.keep            # keeps the entire flash
flash.keep(:notice)   # keeps only the "notice" entry, the rest of the flash is discarded

#---------- now

# Sets a flash that will not be available to the next action, only to the current.
# To pass an object to the next action, you use the standard flash assign ([]=).
flash.now[:message] = "Hello current action"

Loggin

FilterParameters

Allows you to specify sensitive parameters which will be replaced from the request log by looking in the query string of the request and all sub-hashes of the params hash to filter.



env["action_dispatch.parameter_filter"] = [:password]
=> replaces the value to all keys matching /password/i with "[FILTERED]"

env["action_dispatch.parameter_filter"] = [:foo, "bar"]
=> replaces the value to all keys matching /foo|bar/i with "[FILTERED]"

env["action_dispatch.parameter_filter"] = [ "credit_card.code" ]
=> replaces { credit_card: {code: "xxxx"} } with "[FILTERED]", does not
change { file: { code: "xxxx"} }

env["action_dispatch.parameter_filter"] = -> (k, v) do
  v.reverse! if k =~ /secret/i
end
=> reverses the value to all keys matching /secret/i

Match

rubyOnRails: match.



# Expose your action to both GET and POST, use:
# sets :controller, :action and :id in params
match ':controller/:action/:id', via: [:get, :post]

# Instead of:
match ":controller/:action/:id"
# Do:
get ":controller/:action/:id"

# A pattern can also map wildcard segments (globs) to params:
get 'songs/*category/:title', to: 'songs#show'
# 'songs/rock/classic/stairway-to-heaven' sets
#  params[:category] = 'rock/classic'
#  params[:title] = 'stairway-to-heaven'

Cookies

api.rubyOnRails.org.



# Sets a simple session cookie.
# This cookie will be deleted when the user's browser is closed.
cookies[:user_name] = "david"

# Cookie values are String based. Other data types need to be serialized.
cookies[:lat_lon] = JSON.generate([47.68, -122.37])

# Sets a cookie that expires in 1 hour.
cookies[:login] = { value: "XJ-122", expires: 1.hour.from_now }

# Sets a signed cookie, which prevents users from tampering with its value.
# The cookie is signed by your app's `secrets.secret_key_base` value.
# It can be read using the signed method `cookies.signed[:name]`
cookies.signed[:user_id] = current_user.id

# Sets an encrypted cookie value before sending it to the client which
# prevent users from reading and tampering with its value.
# The cookie is signed by your app's `secrets.secret_key_base` value.
# It can be read using the encrypted method `cookies.encrypted[:name]`
cookies.encrypted[:discount] = 45

# Sets a "permanent" cookie (which expires in 20 years from now).
cookies.permanent[:login] = "XJ-122"

# You can also chain these methods:
cookies.permanent.signed[:login] = "XJ-122"

#---------- Examples of reading:
cookies[:user_name]           # => "david"
cookies.size                  # => 2
JSON.parse(cookies[:lat_lon]) # => [47.68, -122.37]
cookies.signed[:login]        # => "XJ-122"
cookies.encrypted[:discount]  # => 45

#----------Example for deleting:
cookies.delete :user_name

Session

guides.rubyOnRails.org: session.

Your application has a session for each user in which you can store small amounts of data that will be persisted between requests. The session is only available in the controller and the view and can use one of a number of different storage mechanisms:


ActionDispatch::Session::CookieStore - Stores everything on the client.
ActionDispatch::Session::CacheStore - Stores the data in the Rails cache.
ActionDispatch::Session::ActiveRecordStore - Stores the data in a database using Active Record. (require activerecord-session_store gem).
ActionDispatch::Session::MemCacheStore - Stores the data in a memcached cluster (this is a legacy implementation; consider using CacheStore instead).

All session stores use a cookie to store a unique ID for each session (you must use a cookie, Rails will not allow you to pass the session ID in the URL as this is less secure).

For most stores, this ID is used to look up the session data on the server.

Rails sets up (for the CookieStore) a secret key used for signing the session data in config/credentials.yml.enc. This can be changed with bin/rails credentials:edit.

Request



# actionpack-4.2.7.1/lib/action_dispatch/http/request.rb
def raw_post
  unless @env.include? 'RAW_POST_DATA'
    raw_post_body = body
    @env['RAW_POST_DATA'] = raw_post_body.read(content_length)
    raw_post_body.rewind if raw_post_body.respond_to?(:rewind)
  end
  @env['RAW_POST_DATA']

Routing

resource, resources, collection, member



resources :photos
# creates seven different routes in your application, all mapping to
# the +Photos+ controller:
#
#   GET       /photos
#   GET       /photos/new
#   POST      /photos
#   GET       /photos/:id
#   GET       /photos/:id/edit
#   PATCH/PUT /photos/:id
#   DELETE    /photos/:id

resources :photos
# creates seven different routes in your application, all mapping to the Photos controller:
# HTTP Verb	Path	Controller#Action	Used for
# ----------
# GET	/photos	photos#index	display a list of all photos
# GET	/photos/new	photos#new	return an HTML form for creating a new photo
# POST	/photos	photos#create	create a new photo
# ----------
# GET	/photos/:id	photos#show	display a specific photo
# GET	/photos/:id/edit	photos#edit	return an HTML form for editing a photo
# PATCH/PUT	/photos/:id	photos#update	update a specific photo
# DELETE	/photos/:id	photos#destroy	delete a specific photo

#---------- Generated path

resources :users

users_path #=> /users
edit_user_path(user) #=> /users/:id/edit
user_path(user) #=> /users/:id  (show action)
new_user_path(user) #=> /users/new

#---------- Resource

# https://apidock.com/rails/ActionDispatch/Routing/Mapper/Scoping/Resources/resource

# A resource that clients always look up without referencing an ID.
# A common example, /profile always shows the profile of the currently logged in user. In this case, you can use a singular resource to map /profile (rather than /profile/:id) to the show action:
resource :profile

# all mapping to the Profiles controller (note that the controller is named after the plural):
GET       /profile/new
POST      /profile
GET       /profile
GET       /profile/edit
PATCH/PUT /profile
DELETE    /profile

#---------- Add a custom action: collection, member

# To add a route to the collection:
resources :photos do
  collection do
    get 'search'
  end
end
# This will enable Rails to recognize paths such as /photos/search with GET, and route to the search action of +PhotosController+. It will also create the search_photos_url and search_photos_path route helpers.

# To add a member route, add a member block into the resource block:
resources :photos do
  member do
    get 'preview'
  end
end
# This will recognize /photos/1/preview with GET, and route to the preview action of +PhotosController+. It will also create the preview_photo_url and preview_photo_path helpers.


#---------- Options

resources :posts, path_names: { new: "brand_new" }
#   The above example will now change /posts/new to /posts/brand_new

resources :posts, path: 'postings'
#   The resource and all segments will now route to /postings instead of /posts

#   Only generate routes for the given actions.
resources :cows, only: :show
resources :cows, only: [:show, :index]

#   Generate all routes except for the given actions.
resources :cows, except: :show
resources :cows, except: [:show, :index]

resources :posts, shallow: true do
  resources :comments
end
#   Is the same as:
resources :posts do
  resources :comments, except: [:show, :edit, :update, :destroy]
end
resources :comments, only: [:show, :edit, :update, :destroy]
#   This allows URLs for resources that otherwise would be deeply nested such
#   as a comment on a blog post like /posts/a-long-permalink/comments/1234
#   to be shortened to just /comments/1234.

# routes call Admin::PostsController
resources :posts, module: "admin"

scope

Scopes a set of routes to the given default options.



scope path: ":account_id", as: "account" do
  resources :projects
end

# This generates helpers such as +account_projects_path+, just like +resources+ does.
# The difference here being that the routes generated are like /:account_id/projects, rather than /accounts/:account_id/projects.

# === Options
# Takes same options as <tt>Base#match</tt> and <tt>Resources#resources</tt>.

url_helpers



class ThingsController < ApplicationController
  include Rails.application.routes.url_helpers

  thing_url(i, host: 'localhost')
end

ActiveRecord, DB

queries

exists?



Person.exists?(5)
Person.exists?('5')
Person.exists?(['name LIKE ?', "%#{query}%"])
Person.exists?(id: [1, 4, 8])
Person.exists?(name: 'David')
Person.exists?(false) # Returns always false.
Person.exists? # Returns false if the table is empty, true otherwise.

pluck



Person.pluck(:id)
# SELECT people.id FROM people
# => [1, 2, 3]

Person.pluck(:id, :name)
# SELECT people.id, people.name FROM people
# => [[1, 'David'], [2, 'Jeremy'], [3, 'Jose']]

Person.pluck('DISTINCT role')
# SELECT DISTINCT role FROM people
# => ['admin', 'member', 'guest']

Person.where(age: 21).limit(5).pluck(:id)
# SELECT people.id FROM people WHERE people.age = 21 LIMIT 5
# => [2, 3]

# Error: this will not work!
# Person.find_by_id(1).pluck(:id)
# Use this instead:
Person.find_by_id(1).id

where

apidock.com: where.



#---------- Pass a string
Client.where("orders_count = '2'")
# SELECT * from clients where orders_count = '2';

#---------- Pass an array

# ? as placeholders.
User.where(["name = ? and email = ?", "Joe", "[email protected]"])
# SELECT * FROM users WHERE name = 'Joe' AND email = '[email protected]';
# Active Record takes care of building the query to avoid injection attacks.

# named placeholders.
User.where(["name = :name and email = :email", { name: "Joe", email: "[email protected]" }])
# SELECT * FROM users WHERE name = 'Joe' AND email = '[email protected]';

#---------- Pass a hash

User.where({ name: "Joe", email: "[email protected]" })
# SELECT * FROM users WHERE name = 'Joe' AND email = '[email protected]'

User.where({ name: ["Alice", "Bob"]})
# SELECT * FROM users WHERE name IN ('Alice', 'Bob')

User.where({ created_at: (Time.now.midnight - 1.day)..Time.now.midnight })
# SELECT * FROM users WHERE (created_at BETWEEN '2012-06-09 07:00:00.000000' AND '2012-06-10 07:00:00.000000')

Associations

belongs_to



class Book < ApplicationRecord
  belongs_to :author
end

# Each instance of the Book model will have these methods:
# author
# author=
# build_author
# create_author
# create_author!
# reload_author

#---------- one-to-one
# Used together with has_one. See "has_one" below.

#---------- one-to-many
class Manager < ActiveRecord::Base
  has_many :employees
end
class Employee < ActiveRecord::Base
  belongs_to :manager     # foreign key - manager_id
end

#---------- many-to-many

# The first way uses a has_many association with the :through option and a join model, so there are two stages of associations.
class Assignment < ActiveRecord::Base
  belongs_to :programmer  # foreign key - programmer_id
  belongs_to :project     # foreign key - project_id
end
class Programmer < ActiveRecord::Base
  has_many :assignments
  has_many :projects, through: :assignments
end
class Project < ActiveRecord::Base
  has_many :assignments
  has_many :programmers, through: :assignments
end

# For the second way, use has_and_belongs_to_many in both models. This requires a join table that has no corresponding model or primary key.
class Programmer < ActiveRecord::Base
  has_and_belongs_to_many :projects       # foreign keys in the join table
end
class Project < ActiveRecord::Base
  has_and_belongs_to_many :programmers    # foreign keys in the join table
end

#---------- polymorphic
# https://apidock.com/rails/ActiveRecord/Associations/ClassMethods/belongs_to
# http://guides.rubyonrails.org/association_basics.html#polymorphic-associations

class Picture < ApplicationRecord
  belongs_to :imageable, polymorphic: true
end
 
class Employee < ApplicationRecord
  has_many :pictures, as: :imageable
end
 
class Product < ApplicationRecord
  has_many :pictures, as: :imageable
end

has_one

api.rubyOnRails.org: associations.



class Employee < ActiveRecord::Base
  has_one :office
end
class Office < ActiveRecord::Base
  belongs_to :employee    # foreign key - employee_id
end

#---------- Deep dive: has_one and belongs_to

# The difference is mostly where to place the foreign key, which goes on the table for the class declaring the belongs_to relationship.

class User < ActiveRecord::Base
  belongs_to :account
end
class Account < ActiveRecord::Base
  has_one :user
end
# The tables for these classes could look something like:
CREATE TABLE users (
  id int NOT NULL auto_increment,
  account_id int default NULL, /* here goes the foreign key. */
  name varchar default NULL,
  PRIMARY KEY  (id)
)
CREATE TABLE accounts (
  id int NOT NULL auto_increment,
  name varchar default NULL,
  PRIMARY KEY  (id)
)

Multiple records for has_one?

SO.

Specifically, the has_one relationship executes a LIMIT 1 sql clause, so technically the "first" record is dependent on however your database was ordering the records (usually by order of entry)

ActiveSupport

Concern

The Concern is a tool provided by the ActiveSupport lib for including modules in classes, creating mixins.

rubyOnRails.org: concern.



module M
  def self.included(base)
    base.extend ClassMethods
    base.class_eval do
      scope :disabled, -> { where(disabled: true) }
    end
  end

  module ClassMethods
    ...
  end
end

#-- By using ActiveSupport::Concern the above module could instead be written as:

require 'active_support/concern'

module M
  extend ActiveSupport::Concern

  included do
    scope :disabled, -> { where(disabled: true) }
  end

  class_methods do
    ...
  end
end

With ActiveSupport::Concern, module dependencies are properly resolved:



#---------- Old

module Foo
  def self.included(base)
    base.class_eval do
      def self.method_injected_by_foo
        ...
      end
    end
  end
end

module Bar
  def self.included(base)
    base.method_injected_by_foo # Here Bar is dependent on Foo.
  end
end

class Host
  include Foo # We need to include this dependency for Bar
  include Bar
end

#---------- New

require 'active_support/concern'

module Foo
  extend ActiveSupport::Concern
  included do
    def self.method_injected_by_foo
      ...
    end
  end
end

module Bar
  extend ActiveSupport::Concern
  include Foo

  included do
    self.method_injected_by_foo
  end
end

class Host
  include Bar # It works, now Bar takes care of its dependencies
end

Concern vs helpers

SO.

Concerns are modules that get mixed into controller or model classes for instance. DHH's post focused on models, but the same applies to controllers. It helps slim down the model or controller classes, and makes it easier to reuse common code across multiple classes.

Helpers are for short presentation-oriented methods that you want to call from your views, or very occasionally from your controllers, maybe.

Numeric

megabytes, weeks, minutes

api.rubyOnRails.org: Numeric.


5.minutes # 300 seconds
2.hours #  7200 seconds

2.weeks # 14 days
14.days # 14 days

2.megabytes # 2097152

Routing

rubyOnRails: routing.

Resources

Nested resources



##### Model definitions.
class Magazine < ApplicationRecord
  has_many :ads
end
class Ad < ApplicationRecord
  belongs_to :magazine
end

##### Nested Resources.
resources :magazines do
  resources :ads
end

##### Routes
# HTTP Verb	Path	Controller#Action	Used for
# ----------
# GET	/magazines/:magazine_id/ads	ads#index	display a list of all ads for a specific magazine
# GET	/magazines/:magazine_id/ads/new	ads#new	return an HTML form for creating a new ad belonging to a specific magazine
# POST	/magazines/:magazine_id/ads	ads#create	create a new ad belonging to a specific magazine
# ----------
# GET	/magazines/:magazine_id/ads/:id	ads#show	display a specific ad belonging to a specific magazine
# GET	/magazines/:magazine_id/ads/:id/edit	ads#edit	return an HTML form for editing an ad belonging to a specific magazine
# PATCH/PUT	/magazines/:magazine_id/ads/:id	ads#update	update a specific ad belonging to a specific magazine
# DELETE	/magazines/:magazine_id/ads/:id	ads#destroy	delete a specific ad belonging to a specific magazine
# This will also create routing helpers such as magazine_ads_url and edit_magazine_ad_path. These helpers take an instance of Magazine as the first parameter (magazine_ads_url(@magazine)).

magazine_ads_url(magazine_id: 1)
# "https://test.cubetree.com/magazine/1/ads"
magazine_ads_path(magazine_id: 1)
# "/magazine/1/ads"

##### Test nested routes
# https://stackoverflow.com/questions/17089410/how-to-test-nested-routes-in-rails

test "should create record" do
  assert_difference('Record.count') do
    post :create, user_id: @user.id, record: { comment: 'Some comment', device: 'Some device', status: 'Some status'}
  end

  assert_redirected_to user_record_path(@user.id, assigns(:record))
end

collection

To add a route to the collection:


resources :photos do
  collection do
    get 'search'
  end
end
# This will enable Rails to recognize paths such as /photos/search with GET, and route to the "search" action of PhotosController. It will also create the search_photos_url and search_photos_path route helpers.

Related functions

url_for

apiDock.com: url_for.



# :only_path - If true, returns the relative URL (omitting the protocol, host name, and port) (true by default unless :host is specified).
url_for(action: 'login', controller: 'members', only_path: false, protocol: 'https')
# => https://www.example.com/members/login/

url_for(action: 'play', anchor: 'player')
# => /messages/play/#player

url_for(@workshop)
# calls @workshop.to_param which by default returns the id
# => /workshops/5

url_for(:back)
# if request.env["HTTP_REFERER"] is set to "http://www.example.com"
# => http://www.example.com
# if request.env["HTTP_REFERER"] is not set or is blank
# => javascript:history.back()

Test

Assertions

guides.rubyOnRails.org.



assert( test, [msg] )	Ensures that test is true.
assert_not( test, [msg] )	Ensures that test is false.
assert_equal( expected, actual, [msg] )	Ensures that expected == actual is true.
assert_not_equal( expected, actual, [msg] )	Ensures that expected != actual is true.
assert_same( expected, actual, [msg] )	Ensures that expected.equal?(actual) is true.
assert_not_same( expected, actual, [msg] )	Ensures that expected.equal?(actual) is false.

assert_nil( obj, [msg] )	Ensures that obj.nil? is true.
assert_not_nil( obj, [msg] )	Ensures that obj.nil? is false.
assert_empty( obj, [msg] )	Ensures that obj is empty?.
assert_not_empty( obj, [msg] )	Ensures that obj is not empty?.

assert_match( regexp, string, [msg] )	Ensures that a string matches the regular expression.
assert_no_match( regexp, string, [msg] )	Ensures that a string doesn't match the regular expression.

assert_includes( collection, obj, [msg] )	Ensures that obj is in collection.
assert_not_includes( collection, obj, [msg] )	Ensures that obj is not in collection.

assert_in_delta( expected, actual, [delta], [msg] )	Ensures that the numbers expected and actual are within delta of each other.
assert_not_in_delta( expected, actual, [delta], [msg] )	Ensures that the numbers expected and actual are not within delta of each other.
assert_in_epsilon ( expected, actual, [epsilon], [msg] )	Ensures that the numbers expected and actual have a relative error less than epsilon.
assert_not_in_epsilon ( expected, actual, [epsilon], [msg] )	Ensures that the numbers expected and actual don't have a relative error less than epsilon.

assert_throws( symbol, [msg] ) { block }	Ensures that the given block throws the symbol.
assert_raises( exception1, exception2, ... ) { block }	Ensures that the given block raises one of the given exceptions.

assert_instance_of( class, obj, [msg] )	Ensures that obj is an instance of class.
assert_not_instance_of( class, obj, [msg] )	Ensures that obj is not an instance of class.
assert_kind_of( class, obj, [msg] )	Ensures that obj is an instance of class or is descending from it.
assert_not_kind_of( class, obj, [msg] )	Ensures that obj is not an instance of class and is not descending from it.

assert_respond_to( obj, symbol, [msg] )	Ensures that obj responds to symbol.
assert_not_respond_to( obj, symbol, [msg] )	Ensures that obj does not respond to symbol.

assert_operator( obj1, operator, [obj2], [msg] )	Ensures that obj1.operator(obj2) is true.
assert_not_operator( obj1, operator, [obj2], [msg] )	Ensures that obj1.operator(obj2) is false.

assert_predicate ( obj, predicate, [msg] )	Ensures that obj.predicate is true, e.g. assert_predicate str, :empty?
assert_not_predicate ( obj, predicate, [msg] )	Ensures that obj.predicate is false, e.g. assert_not_predicate str, :empty?

flunk( [msg] )	Ensures failure. This is useful to explicitly mark a test that isn't finished yet.

# -I directory   Used to tell Ruby where to load the library scripts.
ruby -I test path_to_test_file -n name_of_the_method

# If there were modifications to existing migrations, the test database needs to be rebuilt. This can be done by executing
bin/rails db:test:prepare.

Controller test



# https://stackoverflow.com/questions/529653/how-do-you-specify-post-params-in-a-rails-test
post :create, :user => { :email => '[email protected]' }
# The general form for all the test methods of get, post, put, delete are as follows:
def post(action, *args)
  process(action, "POST", *args)
end

# List all request parameters.
@request.parameters

# Test's request and response are assigned to controller's.
@controller.request  = @request
@controller.response = @response

Set content_type



# https://stackoverflow.com/questions/4036748/specifying-content-type-in-rspec
@request.env["CONTENT_TYPE"] = "application/json"
@request.env["HTTP_ACCEPT"] = "application/json"
@request.env["RAW_POST_DATA"] = {attr1: "Hello", attr2: true}.to_json
put :update, something_id: sth.id
assert_response :success

# wcfNote: I failed with the "format" method.
post :create, format: :json, param: 'Value of Param'
# In later versions of rails/rspec (v5.1 maybe?), "format: :json" got changed to "as: :json".

# The "as" option passes an “application/json” Accept header
# http://api.rubyonrails.org/v5.1/classes/ActionDispatch/IntegrationTest.html
post articles_path, params: { article: { title: "Ahoy!" } }, as: :json

Mock, Stub, Spy...

martinFowler: test double.

Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.
Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an InMemoryTestDatabase is a good example).
Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test.
Spies are stubs that also record some information based on how they were called. One form of this might be an email service that records how many messages it was sent.
Mocks are pre-programmed with expectations which form a specification of the calls they are expected to receive. They can throw an exception if they receive a call they don't expect and are checked during verification to ensure they got all the calls they were expecting.

Functions

assigns

SO: what's the purpose of assigns method in rails minitest.


# If a controller defined an instance variable @item="something", checks if the instance variable is a string
assert_kind_of String, assigns(:item)

FAQ

Find routes

Type "rails c" to enter console, and run:


Rails.application.routes.recognize_path "sthDir/sth"

Rails.application.routes.recognize_path "wiki/aI1b4kP703a9bVwQRINeaO", method: :put
 => {:controller=>"wiki", :action=>"update", :id=>"aI1b4kP703a9bVwQRINeaO"}

Allow remote access

SO: allow public connections to local Ruby on Rails.


rails s --binding=0.0.0.0

# Listen on port 8080
rails s -p 8080

Set port

SO: how to change default port of a rails app.

Append this to config/boot.rb:


require 'rails/commands/server'

module DefaultOptions
  def default_options
    super.merge!(Port: 3001)
  end
end

Rails::Server.send(:prepend, DefaultOptions)