119 liens privés
Bundler behavior changed.
A great change, probably the one change I was expecting.
In other terms :
a = 2
=> 2
Assignment can be used in a condition :
example = "lorem ipsum"
if (my_var = example.length) > 10
my_var/2
else
myvar * 2
end
I restart local database (postgres in a docker container) and then my server bundle exec bin/rails s
After that I go to the console with bundle exec bin/rails c
(or bin/rails c
or bundle exec rails c
),
being in the project root folder.
Sometimes (not sure exactly why yet), environment get messed up.
When trying a request such as : User.count
I get a weird error.
could not connect to server: No such file or directory (ActiveRecord::ConnectionNotEstablished)
Is the server running locally and accepting
connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
While the server is running locally and could connect to the database.
It happens the console explicitly starts with the following announcement :
Running via Spring preloader in process 1720240
Hey ! That's a good hint.
Of course, I did disregard it completly for a couple hours -- more than once.
The solution is so often related though. You reload the database and the server,
under spring preloader's feet.
spring prelaoder is so lost ! Let's restart it too.
Solution :
spring stop
bin/rails console
and voilà ! It works again.
Edit 2022-01-23 :
Beware, in the new console, if you do User
and get this answer :
User (call 'User.connection' to establish a connection)
Solution is very simple : User.last
and there you go. Connexion established, problem solved
Just a great resource
Simple to use :
- Read csv using headers to name symbols
- Parse table like each row is a hash where each column header is a symbol's name.
- do whatever you want with value.
Example :
require 'smarter_csv'
# Class CodePostaux
class CodePostaux
attr_accessor :csv_file_path, :cp_hash
def initialize(csv_file_path)
@csv_file_path = csv_file_path
@cp_hash = Hash.new
end
def read_csv
SmarterCSV.process(@csv_file_path, {col_sep: ';'})
end
end
output = File.open('./test/minitest/fixtures/code_postaux_provisioning.rb', 'w')
codes_postaux.each do |value|
output.write("PostCode.create(code: '#{value[:code_postal]} #{value[:nom_commune]}')\n")
end
output.close
Not much to say, is 2.6.x compliant
It took me some time to understand that sugar syntax.
First of : it's &
:to_s
obviously.
Operator is &
.
What does it do ?
it turns
mythings.map(& :upcase)
# is the same as
mythings.map(&:upcase)
into
mythings.map { |mything| mything.upcase }
Remark : sugar syntax can be a pain in the butt. I hope you do see it.
The map
method applies the "block" { |mything| mything.upcase }
on each and every elements of mythings
and returns an enumerable of class mythings.class
containing each result.
The operator is &
and the argument in my example is :upcase
. :upcase
is a Symbol
.
Symbols have a smart to_proc
method.
Another example :
require 'date'
[1,DateTime.now,3].map(&:to_s)
# => ["1", "2021-09-05T12:06:54+02:00", "3"]
So how does it work ?
-
&̀
when a parameter of a method is prepended with&
then ruby knows this parameter to be a Proc -
:upcase is a symbol.
So the &:myproc
is a smart shortcut implemented to turn the symbol :myproc
into a proc.
Let's try it :
def call_my_block ( my_parameter, &myblock)
myblock.call.myblock
end
The parameter &myblock
is known to be a block.
When I use method call_my_block
with the argument &:my_symbol
:
- The second parameter is known to be a block.
- The argument will be translated into
:my_symbol.to_proc
If the first argument is of classKlass
andKlass
actually has amy_symbol
method, then it will call it.
Example :
call_my_block DateTime.now , &:to_s
translates into :
:to_s.to_proc.call DateTime.now
note that :
a = :to_s.to_proc
#=> #<Proc:0x000055e77c191c98(&:to_s)>
a.call(13)
#=> "13"
a.class
#=> Proc
Hence :
call_my_block DateTime.now , &:to_s
# => "2021-09-05T12:06:00+02:00"
[1,DateTime.now,3].map { |val| call_my_block(val,&:to_s) }
#=> ["1", "2021-09-05T12:21:54+02:00", "3"]
[1,DateTime.now,3].map(&:to_s)
["1", "2021-09-05T12:23:22+02:00", "3"]
Note ::
- A function/methods has parameters.
- When called the function is given arguments
In other terms, an argument is the value of a parameter.
gem TVA
Yet another online store framework in ruby
On github. Book about gem development.
A collection of awesome Ruby gems, tools, frameworks and software.
Excellent website to know what's updated, followed etc.
Quick & dirty test of mastodon api
require 'mastodon'
require 'oauth2'
require 'fileutils'
APP_NAME = "tcmasto"
SCOPE = "read write follow"
## INITIALISATION
def init
url = "your_domain_url" # exemple : https://framapiaf.org
tcmasto_client = Mastodon::REST::Client.new(base_url: url)
tcmasto_app = tcmasto_client.create_app( APP_NAME, "urn:ietf:wg:oauth:2.0:oob", SCOPE)
oauth_client = OAuth2::Client.new( tcmasto_app.client_id,
tcmasto_app.client_secret,
site: url)
email = "yourmail@whatever.com"
password= "yourpassword"
token = oauth_client.password.get_token(email, password, scope: SCOPE)
return {
"url" => url,
"client_id" => tcmasto_app.client_id,
"client_secret" => tcmasto_app.client_secret,
"email" => email,
"access_token" => token.token
}
end
class TCMasto
attr_accessor :client
def initialize config
@client = Mastodon::REST::Client.new(base_url: config["url"],
bearer_token: config["access_token"])
end
def pouet (msg)
resp = @client.create_status( msg )
end
end
config = init()
myClient = TCMasto.new config
myClient.pouet ("Hello world")
#lotr.txt
Three Rings for the Elven-kings under the sky,
Seven for the Dwarf-lords in their halls of stone,
Nine for Mortal Men doomed to die,
One for the Dark Lord on his dark throne
In the Land of Mordor where the Shadows lie.
readline accepts chomp flag
IO.readlines('lotr.txt', chomp: true)
#=> ["Three Rings for the Elven-kings under the sky,", "Seven for the Dwarf-lords in their halls of stone,", "Nine for Mortal Men doomed to die,", "One for the Dark Lord on his dark throne", "In the Land of Mordor where the Shadows lie."]
(example from big binaryblog)
This gem implements a flexible time-ordered activity feeds commonly used within social networking applications. As events occur, they are pushed into the Feed and distributed to all users that need to see the event. Upon the user visiting their "feed page", a pre-populated ordered list of events is returned by the library.
Easy enough API to encrypt/decrypt.
Only works with ruby 2.2.2 for now.
Source is here : https://github.com/loureirorg/rb2exe
Also works with rails apparently.
I have not tested this gem. But it's worth mentioning it exists.
And yes... this is not a snippet
(this snippet was tested with ruby 2.3)
RUBY helps a lot to write DRY code.
This feature is both great and very disturbing.
ruby on Rails, for example, is full of meta-programming.
That's how the rails "magic" happens.
Let's point out it's not magicall, and pretty simple to explain.
NB : This snippet requires some basic understanding of Object Oriented Programming.
I tried to take baby steps to explain it.
It should be very easy to understand.
Meta-programming, what is it ?
Let's assume we play with different living-dead species : Zombies and Vampires, Werevamps. Vampires have appetite for blood, whereas Zombies have appetite for brains, and Werevamps crave for blood and/or flesh.
We would like to be able to define a "macro" that let's us define what a class has appetite for, so we could write :
class Zombie < LivingDead
has_appetite_for :brains
end
class Vampire < LivingDead
has_appetite_for :blood
end
class Werevamp < LivingDead
has_appetite_for :blood
has_appetite_for :flesh
end
bob = Werevamp.new
bob.regime
#=> [:blood, :flesh]
bob.hunt_blood
#=> "bob is hunting for blood"
bob.hunt_flesh
#=> "bob is hunting for flesh"
The "regime, " methods exists just because Werevamp is derived from LivingDead.
But how do we make that happening ?
The answer is "Meta-programming", also known as "macro".
This is precisely what rails classes are doing beind the hood. It's no magic.
For instance, your has_many :persons
in your Company
model gives you methods like Company.first.persons
wich returns a collection of Person objects. Let's see how this is done, step by step
Monkey patching an object
We know how to monkey patch an object :
fred = "Zombie"
#=> "Zombie"
fred.class
#=> String
def fred.has_appetite_for
"brains"
end
#=> :has_appetite_for
fred.has_appetite_for
#=> "brains"
We monkey patched the fred
object.
It now has a new method called :has_appetite_for
fred is an object. It's a simple String.
Since a class is an object of class Class, we could do the same on the class itself.
Patching a class
class Zombie
end
#=> nil
Zombie.class
#=> Class
my_zombie_classs = Zombie
#=> Zombie
my_zombie_class.class
#=> Class
def my_zombie_class.has_appetite_for
"brain"
end
#=> :has_appetite_for
Zombie.has_appetite_for
#=> "brain"
Pushing it into the class
We could put that the class itself.
Let's do that with the Vampire class
class Vampire
def self.has_appetite_for
"blood"
end
self.has_appetite_for
end
#=> "blood"
Vampire.has_appetite_for
#=> "blood"
Within the class definition, self refers to the Vampire class itself. Therefore, we could replace self
with Vampire
in the above example, it would do the same thing.
Now we would like to have a method called "has_appetite_for" that gets the food as an argument. Let's assume we have a new kind of living-dead called "Werevamp". A Werevamp has taste for either blood or flesh.
class Werevamp
def self.has_appetite_for(food)
puts "#{self} has appetite for #{food}"
end
has_appetite_for :flesh
has_appetite_for :blood
end
#=> "Werevamp has appetite for flesh"
#=> "Werevamp has appetite for blood"
bob = Werevamp.new
#=> "Werevamp has appetite for flesh"
#=> "Werevamp has appetite for blood"
If we remove the "self" call, ruby assumes that has_appetite_for
is called on self
One last step : define a method within our method : to do that we use
define_method
class Werevamp
def self.has_appetite_for(name)
puts "#{self} has appetite for #{name}"
define_method("hunts_#{name}") do
puts "A #{self.class} is now hunting for #{name}"
end
end
has_appetite_for :flesh
has_appetite_for :blood
end
#=> "Werevamp has appetite for flesh"
#=> "Werevamp has appetite for blood"
#=> => :hunts_blood
bob = Werevamp.new
#=> => #<Werevamp:0x00000001e244c8>
bob.hunts_blood
#=> A Werevamp is now hunting for blood
#=> =>nil
# reminder : puts returns nil
Pushing it on a parent class
Now we have everything we need to push the behavior a parent class.
class LivingDead
attr :name, :food # this too is meta-programming, by the way.
def initialize(name)
@name = name
end
def self.has_appetite_for(food_name)
puts "#{name} has appetite for #{food_name}"
define_method("hunts_#{food_name}") do
puts "#{self.name} is hunding for #{food_name}"
end
end
end
class Zombie < LivingDead
has_appetite_for :brain
end
john = Zombie.new("J")
#=> => #<Zombie:0x00000002ad8610 @name="J">
john.hunts_brain
#=> J is hunting for brain
#=> => [:brain]
Important note :
One does NEED to understand the meaning of self here.
When ruby executes code, the self variable is contextual.
Wich means that in the class definition, self refers to the class itself.
In a class definition, self.class is a Class.
While when the code is being executed on the instance, self refers to the instance.
Let's push that to a module
Now we can create a LivingDead module.
Let's add a feature : we want to keep track of who eats what.
module LivingDead
attr :regime
@regime = a = Hash.new{ |hash, key| hash[key] = [] }
def self.add_to_regime name, sender
@regime["#{sender}"] << name
end
def self.get_regime sender
@regime["#{sender}"]
end
private
def self.regimes
@regimes
end
public
class Base
include LivingDead
attr :name; :regime
def initialize(name)
@name = name
end
def self.has_appetite_for(food_name)
puts "#{name} has appetite for #{food_name}"
# send :add_to_regime, food_name
LivingDead::add_to_regime food_name, self
define_method("hunts_#{food_name}") do
puts "#{name} is now hunting for #{food_name}"
end
define_method (:get_regime) do
LivingDead::get_regime "#{self.class}"
end
end
def regimes
LivingDead::regime
end
end
end
class Zombie < LivingDead::Base
has_appetite_for :brain
end
class Vampire < LivingDead::Base
has_appetite_for :blood
end
class Werevamp < LivingDead::Base
has_appetite_for :flesh
has_appetite_for :blood
end
john = Zombie.new("John")
bob = Vampire.new("Bob")
jenny = Werevamp.new("Jenny")
john.get_regime
#=> => [:brain]
bob.get_regime
#=> => [:blood]
jenny.get_regime
#=> => [:flesh, :blood]
john.hunts_brain
bob.hunts_blood
jenny.hunts_flesh
include LivingDead
LivingDead::regime
#=> => {"Zombie"=>[:brain], "Vampire"=>[:blood], "Werevamp"=>[:flesh, :blood]}
jenny.regimes
#=> => {"Zombie"=>[:brain], "Vampire"=>[:blood], "Werevamp"=>[:flesh, :blood]}
LivingDead::regimes
#=> => nil because private !
Important note :
See how the "self" is behaving. When it's interpreted as a code from the class, it's the class. When it's interpreted from within the object, it's the object name.I included a private sample so we can also see here that it does work as expected.
A good example of the above note :
define_method (:get_regime) do
LivingDead::get_regime "#{self.class}"
end
We have to consider here that the "self" will be interpreted WITHIN the object.
Therefore, the self.class is now being used.
in bash :
ruby -v
in ruby :
puts "Ruby version : #{$RUBY_VERSION}"
require 'forwardable'
class ObjectFowardingCallsToThing
def initialize(thing = [])
@thing = thing
end
extend Forwardable
def_delegators :@thing, :join, :<<
end
x = ObjectFowardingCallsToThing.new([1,2,3])
x.join
# => "123"
x << 4
x.join
# => "1234"
the def_delegators :@thing, :join, :<<
means that calling #join or #<< on the Object will forward the call to the @thing object.
a = %[Now this is a string "#{ 1+1 }" or even with 'simple' quotes]
=> "Now this is a string \"2\" or even with 'simple' quotes"
SO usefull, why did I not know that before ?