All notes
Rails

Intro

rubyOnRails.org: getting started.

Rails philosophy:

Command line



o# 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'"

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

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

#### Create 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

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]

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

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"

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

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?

ActionController

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"}}

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



<% 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 %>

ActionDispatch

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'

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']

ActiveRecord

queries

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)
)

ActiveSupport

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:



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

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

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

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

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


# -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)