How do I increment/decrement a character in Ruby for all possible values?
Depending on what the possible values are, you can use String#next
:
"\x0".next
# => "\u0001"
Or, to update an existing value:
c = "\x0"
c.next!
This may well not be what you want:
"z".next
# => "aa"
The simplest way I can think of to increment a character's underlying codepoint is this:
c = 'z'
c = c.ord.next.chr
# => "{"
Decrementing is slightly more complicated:
c = (c.ord - 1).chr
# => "z"
In both cases there's the assumption that you won't step outside of 0..255
; you may need to add checks for that.
Rails before_create increment in alphabetical order
There is actually a pretty cool way to do this in Postgres by applying a computed default value to the column.
First we want to define a Postgres function that gives you a letter given an integer (1 = A, 26 = Z) so that we can get a letter given an ID.
class CreateIdToLetterFunction < ActiveRecord::Migration[5.2]
def up
execute <<-SQL
CREATE OR REPLACE FUNCTION id_to_letter(integer) RETURNS varchar
AS 'select chr(64 + $1)'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;
SQL
end
def down
execute <<-SQL
DROP FUNCTION id_to_letter(integer);
SQL
end
end
chr(int)
returns the character with the given ASCII code. In ASCII A is at 65 so we need to pad the value with 64.
We then add function that counts the exposures so that we can use it the default:
class AddExposureCountFunction < ActiveRecord::Migration[5.2]
def up
execute <<-SQL
CREATE OR REPLACE FUNCTION count_exposures() RETURNS bigint
AS 'select count(*) from exposures'
LANGUAGE SQL
VOLATILE;
SQL
end
def down
execute <<-SQL
DROP FUNCTION count_exposures();
SQL
end
end
We then want to alter the exposures.setup_code column to add a default value.
class AddDefaultSetupCodeToExposures < ActiveRecord::Migration[5.2]
def change
change_column_default(
:exposures,
:setup_code,
from: nil,
to: -> {"id_to_letter(CAST(count_exposures() AS integer) + 1)"}
)
end
end
We wrap the new default in a lambda (->{}
) as this tells ActiveRecord that the value is not a literal value and should be added to the statement as SQL.
As this is handled on the DB level no additional model code is needed. Note that the caveat regarding default values set by the DB applies - the value will be nil until you reload the instance from the db.
added
However if you want something functionally equal to the epically bad code from your comment you just need:
class Exposure < ApplicationRecord
SETUP_CODES = %w{ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z A2 B2 C2 D2 E2 F2 G2 H2 }
def self.next_setup_code(current_code)
if !SETUP_CODES.index(current_code) || current_code == SETUP_CODES.last
"error"
else
SETUP_CODES[ SETUP_CODES.index(current_code) + 1 ]
end
end
end
Ruby converting letters in string to letters 13 places further in the alphabet
From here -> How do I increment/decrement a character in Ruby for all possible values?
you should do it like:
def increment_char(char)
return 'a' if char == 'z'
char.ord.next.chr
end
def increment_by_13(str)
conc = []
tmp = ''
str.split('').each do |c|
tmp = c
13.times.map{ |i| tmp = increment_char(tmp) }
conc << tmp
end
conc
end
Or close.
Ruby how to increment a string number
You can convert that string to integer, call #next
and then convert it back to string
'-3'.to_i.next.to_s
Does Ruby/Rails have a ++ equivalent?
Try this:
x += 1
Just for fun, how do I write a ruby program that slowly prints to stdout one character at a time?
Two things:
- You need to use
.each_char
to iterate over the characters. In Ruby 1.8,String.each
will go line-by-line. In Ruby 1.9,String.each
is deprecated. - You should manually flush
$stdout
if you want the chars to appear immediately. Otherwise, they tend to get buffered so that the characters appear all at once at the end.
.
#!/usr/bin/env ruby
"a b c d d e f g h i j k".each_char {|c| putc c ; sleep 0.25; $stdout.flush }
How to write negative loop in ruby like for(i=index; i = 0; i --)
There are many ways to perform a decrementing loop in Ruby:
First way:
for i in (10).downto(0)
puts i
end
Second way:
(10).downto(0) do |i|
puts i
end
Third way:
i=10;
until i<0
puts i
i-=1
end
Increment variable in ruby
From the documentation,
Ruby has no pre/post increment/decrement operator. For instance, x++ or x-- will fail to parse
So, you can do
i += 1
which is equivalent of i = i + 1
How to update a counter or multiple counters in a single transaction?
you could use update_counters
User.update_counters(user_id, :sales_count => 1, :friend_count => 3, :other_count => -2)
Related Topics
Could Not Find Rake-10.1.0 in Any of the Sources
Yielding in an Anonymous Block
How to Share State Between Scenarios Using Cucumber
Grabbing Snapshots from Webcams in Ruby
Ror - How to Remove Rails 4.1.1 Version
What's the Best Background Job Management Library for Rails
How to Render a String as an Erb File
How to Update Rails Locale Yaml File Without Loosing Comments and Variables
Why Do Ruby Procs/Blocks with Splat Arguments Behave Differently Than Methods and Lambdas
Grouping Consecutive Numbers in an Array
Alter $Path in Vim/Macvim So as to Find the Right Ruby Binary
Script to Run Against Stdin If No Arg; Otherwise Input File =Argv[0]
How to Source Environment Variables for a Command Shell in a Ruby Script
Setting Mime Type for .Ogv Files in Rails Development Environment