Robo. Created in a Cinema 4D two and half years ago.

Ohhh… Today I’ve faced one great trouble: recently I reinstalled my Ubuntu, so I lost all my configurations. And when I tried to connect my Lenovo P780 to debug my Android application, I saw horrible error:

$ adb devices
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
List of devices attached
????????????    no permissions

Hey! Where did my smartphone gone?!

Fooling around in the internet, I found two simple steps to fix this:

  1. find the VendorID and ProductID for your device running lsusb two times (just find the difference line): a. when your device is disconnected b. when your device is connected

    This will give you two outputs:

    $ # disconnected device
    
    $ lsusb
    Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
    Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    Bus 001 Device 004: ID 064e:d213 Suyin Corp.
    Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
    Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
    Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    
    $ # connected device (via USB)
    
    $ lsusb
    Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
    Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    Bus 001 Device 004: ID 064e:d213 Suyin Corp.
    Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
    Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
    Bus 003 Device 006: ID 0bb4:0c03 HTC (High Tech Computer Corp.)
    Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    

    Note the row, which is present in the second output block and is absent in the first one:

    Bus 003 Device 006: ID 0bb4:0c03 HTC (High Tech Computer Corp.)
    

    For some reason, my phone is recognized as a HTC, but that does not bother me so much. We will need only two parts of that row:

    0bb4:0c03
    

    The 0bb4 is a VendorID and the 0c03 is the ProductID for my phone.

  2. Add the phone attributes to the system. Sudo-edit the file /lib/udev/rules.d/69-libmtp.rules and point it to your device. Add a line like this (without any newlines):

    ATTR{idVendor}=="0bb4", ATTR{idProduct}=="0c03", SYMLINK+="libmtp-%k", MODE="0666", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
    

    That should enable your system to see the device later.

  3. Enable write permissions for your device. Sudo-edit the file /etc/udev/rules.d/51-android.rules (you may need to create it) and add one line there:

    SUBSYSTEM=="usb", ATTRS{idVendor}=="0bb4", ATTRS{idProduct} =="0c03", MODE="0666", GROUP="plugdev"
    
  4. To check if your phone is recognized by adb, restart ABD server and check its device list:

    $ adb kill-server
    $ adb devices
    * daemon not running. starting it now on port 5037 *
    * daemon started successfully *
    List of devices attached
    0123456789ABCDEF    device
    

First of all, set up the Heroku Toolbelt. It is required for all the communications with the server.

The first step of communication with the Heroku servers is logging in. Just run heroku login and provide your credentials when asked.

Then, you need to create your application or go to the folder where it is located and tune it a bit. Tuning is divided into the following steps:

  • tuning the Gemfile to include the required gems
  • fixing the database.yml configurations
  • setting the server to handle static assets correctly

But let’s create out application on the Heroku servers first: heroku create [app_name]. If application name is not provided directly - it will be generated automatically.

Now, our application needs two gems to be included for the production gems’ group:

group :production do
    gem 'pg'
    gem 'rails_12factor'
    gem 'puma'
end

The third gem is used as a webserver instead of WebRick, which is default (puma is much, much faster!). The second one is required by Heroku. And the first one is used for PostgreSQL connectivity. If you do not wish to use database - skip it and a few next paragraphs.

Then, let’s add the database support for our application. It’s done simply, running

heroku addons:add heroku-postgresql:hobby-dev

Note: Heroku does not support sqlite since some times. This means you are forced to use either PostgreSQL or no database at all (yes, it’s possible! Yet, it works for simple or static web applications only…). You may want to change this if you would pay for your account. But this tutorial covers only free side of the Heroku deployment.

Now, there are two ways to set database connection options in Rails:

  1. set them directly at config/database.yml file
  2. set the environment variable DATABASE_URL

We will cover both cases. For the first one, you will need this section within your database.yml file:

production:
    adapter: postgresql
    encoding: unicode
    pool: 5
    url: URL_GOES_HERE

I will show how to get the <URL_GOES_HERE> value in a second. Just keep in mind to replace it with the correct value.

The second option, the environment variable, is set via the Heroku Toolbelt (did I tell you, it is used for almost every deploy operation you will perform?).

First you take the database URL from Heroku server:

heroku config | grep HEROKU_POSTGRESQL

Then, you copy the value you got (it starts with postgres://) and run the following:

heroku config:set DATABASE_URL=URL_GOES_HERE

Now let’s set our application to serve static assets. It is handy, because it is the easiest way to send images, stylesheets and javascripts to clients. Go to the config/environments/production.rb and change both config.serve_static_assets and config.assets.compile to true.

But beware: if your app/assets files directory contains files of other extensions than Rails’ Sprockets understands - Rails (and Heroku, particularly) will try to precompile them. And that may cause many troubles. You are recommended either to “teach” Sprockets to skip or precompile those files, or you should exclude them from project before deploying to Heroku.

And the last two steps separate us from our goal: first, you should push your project to Heroku’ Git repository, it created for you with the application (You do not use Git yet?! How dare you?!..).

Now, if you use database, run migrations with heroku run rake db:migrate.

And, finally, see your application running in the browser: heroku open.

Note: if you are using some assets from the outer web (GoogleFonts, for example) and are seeing your website through the https protocol, you should replace all those assets’ URL protocols with https too.

I have a T-SQL trigger creation script, which runs OK:

CREATE TRIGGER data_modified ON Northwind.dbo.Customers FOR INSERT, UPDATE, DELETE
AS

declare @rows as int;
set @rows = @@ROWCOUNT;

IF @rows = 0
BEGIN
    print 'no rows were affected';
    return;
end

if exists(select * from inserted)
begin
    if exists(select * from deleted)
    begin
        print 'updated ' + @rows + ' rows';
    end
    else
    begin
        print 'inserted ' + @rows + ' rows';
    end
end
else
begin
    print 'deleted ' + @rows + ' rows';
end

Yet, when I run some INSERT query, I got an error saying:

Msg 245, Level 16, State 1, Procedure data_modified, Line 21
Conversion failed when converting the varchar value 'inserted ' to data type int.

Let’s look onto the source of that trigger, at line 18:

USE [Northwind]
GO
/****** Object:  Trigger [dbo].[data_modified]    Script Date: 09.01.2015 18:18:14 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
    ALTER TRIGGER [dbo].[data_modified] ON [Northwind].[dbo].[Customers] FOR INSERT, UPDATE, DELETE
    AS

    declare @rows as int;
    set @rows = @@ROWCOUNT;

    IF @rows = 0
    BEGIN
        print 'no rows were affected';
        return;
    end

    if exists(select * from inserted)
    begin
        if exists(select * from deleted)
        begin
            print 'updated ' + @rows + ' rows';
        end
        else
        begin
            print 'inserted ' + @rows + ' rows';
        end
    end
    else
    begin
        print 'deleted ' + @rows + ' rows';
    end

Here’s the error:

if exists(select * from inserted)

But wait, that can’t be true!

The problem is a bit deeper, with the @rows variable:

print 'updated ' + @rows + ' rows';

while being declared as:

declare @rows as int;

It can not be printed right away, so it needs to be cast:

CREATE TRIGGER data_modified ON Northwind.dbo.Customers FOR INSERT, UPDATE, DELETE
AS

declare @rows as int;
declare @rows_s as varchar(10);
set @rows = @@ROWCOUNT;
set @rows_s = cast(@rows as varchar);

IF @rows = 0
BEGIN
    print 'no rows were affected';
    return;
end

if exists(select * from inserted)
begin
    if exists(select * from deleted)
    begin
        print 'updated ' + @rows_s + ' rows';
    end
    else
    begin
        print 'inserted ' + @rows_s + ' rows';
    end
end
else
begin
    print 'deleted ' + @rows_s + ' rows';
end

Try to guess where’s your mistake, using that error message! ;)

Rails Server Setting Up

Foreword

This tutorial I wrote when was quitting my previous job, almost one year ago. But it’s still handy!

Abstract Rails application setup

$ git clone .../project_name.git
$ cd project_name
$ [sudo] bundle install
$ cat config/database.yml
$ # create database and/or change config/database.yml settings
$ rake db:migrate RAILS_ENV=production
$ rake db:seed RAILS_ENV=production # don't worry if one fails
$ # start the server of your choice

Puma webserver

Application-wide settings

First you need to set up Puma for your specific project. For this purpose, add this line to the Gemfile:

gem 'puma'

Then, run [sudo] bundle install.

When you are done, you should be able to create a Puma config file at $PROJECT_DIR/config/puma.rb:

def home_dir
    '/home/user/$PROJECT_DIR/'
end

def path(p)
    File.join(home_dir, p)
end

directory home_dir
environment 'development'
daemonize
pidfile path('tmp/pids/puma.pid')
state_path path('tmp/pids/puma.state')
stdout_redirect path('log/puma.log'), path('log/error.puma.log'), true
threads 0, 1
bind 'tcp://0.0.0.0:5100'
activate_control_app

More details here: https://github.com/puma/puma/blob/master/examples/config.rb

Now, add project root path to the /etc/puma.conf file, e. g.:

/home/user/project_name

Start Puma at boot

There is a specific utility, called Jungle. It manages your applications’ instances at startup.

Ububtu-based systems

First of all, create /etc/init/puma.conf file and fill it with this:

# /etc/init/puma.conf - Puma config

# This example config should work with Ubuntu 12.04+.  It
# allows you to manage multiple Puma instances with
# Upstart, Ubuntu's native service management tool.
#
# See workers.conf for how to manage all Puma instances at once.
#
# Save this config as /etc/init/puma.conf then manage puma with:
#   sudo start puma app=PATH_TO_APP
#   sudo stop puma app=PATH_TO_APP
#   sudo status puma app=PATH_TO_APP
#
# or use the service command:
#   sudo service puma {start,stop,restart,status}
#

description "Puma Background Worker"

# no "start on", we don't want to automatically start
stop on (stopping puma-manager or runlevel [06])

# change apps to match your deployment user if you want to use this as a less privileged user (recommended!)
setuid apps
setgid apps

respawn
respawn limit 3 30

instance ${app}

script
# this script runs in /bin/sh by default
# respawn as bash so we can source in rbenv/rvm
# quoted heredoc to tell /bin/sh not to interpret
# variables
exec /bin/bash &lt;&lt;'EOT'
  # set HOME to the setuid user's home, there doesn't seem to be a better, portable way
  export HOME="$(eval echo ~$(id -un))"

  cd $app

  if [ -d "$HOME/.rbenv/bin" ]; then
    export PATH="$HOME/.rbenv/bin:$PATH"
  elif [ -f  /etc/profile.d/rvm.sh ]; then
    source /etc/profile.d/rvm.sh
  elif [ -f /usr/local/rvm/scripts/rvm ]; then
    source /etc/profile.d/rvm.sh
  elif [ -f "$HOME/.rvm/scripts/rvm" ]; then
    source "$HOME/.rvm/scripts/rvm"
  elif [ -f /usr/local/share/chruby/chruby.sh ]; then
    source /usr/local/share/chruby/chruby.sh
    if [ -f /usr/local/share/chruby/auto.sh ]; then
      source /usr/local/share/chruby/auto.sh
    fi
    # if you aren't using auto, set your version here
    # chruby 2.0.0
  fi

  logger -t puma "Starting server: $app"

  exec bundle exec puma -C config/puma.rb
EOT
end script

Now, create /etc/init/puma-manager.conf and fill it with this:

# /etc/init/puma-manager.conf - manage a set of Pumas

# This example config should work with Ubuntu 12.04+.  It
# allows you to manage multiple Puma instances with
# Upstart, Ubuntu's native service management tool.
#
# See puma.conf for how to manage a single Puma instance.
#
# Use "stop puma-manager" to stop all Puma instances.
# Use "start puma-manager" to start all instances.
# Use "restart puma-manager" to restart all instances.
# Crazy, right?
#

description "Manages the set of puma processes"

# This starts upon bootup and stops on shutdown
start on runlevel [2345]
stop on runlevel [06]

# Set this to the number of Puma processes you want
# to run on this machine
env PUMA_CONF="/etc/puma.conf"

pre-start script
  for i in `cat $PUMA_CONF`; do
    app=`echo $i | cut -d , -f 1`
    logger -t "puma-manager" "Starting $app"
    start puma app=$app
  done
end script

And create a blank /etc/puma.conf file. This will be filled for each application separately.

Caveat:

You need to customise /etc/init/puma.conf to:

  • Set the right user your app should be running on unless you want root to execute it!
    • Look for setuid apps and setgid apps, uncomment those lines and replace apps to whatever your deployment user is.
    • Replace apps on the paths (or set the right paths to your user’s home) everywhere else.
  • Uncomment the source lines for rbenv or rvm support unless you use a system wide installation of Ruby.

Now, start Jungle like this: sudo start puma-manager. And all your applications should be available when you reboot the machine.

More details at https://github.com/puma/puma/tree/master/tools/jungle/

Debian-based systems

PENDING

Starting up and shutting down

To start up the application is easy enough. Just navigate yourself to project directory and run the following: puma -C config/puma.rb.

If you want to shut down one, run this command in the project directory: [sudo] pumactl -S tmp/pids/puma.state halt.

Foreword

At my job, our current project has many bottle-necks, where Ruby really sucks on its performance. We were thinking on how to optimize them, and finally come to usage of Ruby Native API.

Our project uses Redis and MySQL hardly, so much of statistic data is stored in Redis. For speeding up. But one fine day made us use a reduce on a set of statistic data from Redis. And that’s where we got stuck on Ruby’ performance. Our server timed out in a minute of waiting for that reduce to complete.

Прєдупрєждєніє

Будь готов! В цій главі ми полностью переробим блог! Він не буде працювати (як раньше) аж до кінця домашнього заданія; код буде магічним; придеться пару раз удалять весь код з деяких файлів! Але в сухом остаткє, потом має стати ну дуже прикольно розробляти його дальше.

Моделі

Єсть така штука як MVC, Model-View-Controller. Це такий прінцип, по якому програма розділяється на три тіпа дєталєй:

  1. Model - отвічає за роботу чісто з базой даних
  2. View - отвічає чісто за отображеніє даних перед пользоватєльом (формочка, HTML, і так далєє)
  3. Controller - отвічає за обработку дєйствій пользоватєля, іспользує моделі і передає їх в’юхам

Так от, модель - це такій клас, який работає з рядочками одної таблички і другими табличками, шо прив’язані до нашої. Але тільки якшо та таблічка, з якою работає модель - главна в цій связі. Тоість, якшо у нас є модель Пост і модель Камєнтік, то модель Пост може вліять на Камєнтікі, а от модель Камєнтік вже нічо не може зробити з Постом. Тут таблічка Пост - главна, а таблічка Камєнтік - просто прив’язана до неї.

В общєм, модель - це такий удобний клас, в якому заникані всі запроси до бази даних. Ти визиваєш метод моделі, а получаєш - масив (або не масив, а тільки один його елємєнт) з запісями з бази даних. Або визиваєш другий мєтод і удаляєш/обновляєш/создаєш рядочки в базі.

Прєдісловіє

Дарагой друг! В цих статтях я розкажу тобі як зробить чоткій блог на чотком язику PHP. Розказувать буду просто, шоб всьо було понятно. Ну шо, паєхалі?

Сістємні трєбованія

Нехай у нас є який-небудь самий стандартний, простий, перший блог на PHP. Така собі кучка файлів для созданія постов, списка постов, перегляду оддєльного поста, реєстрації, логіна і логаута, камєнтіруванія… Просто купа файлів. В цих файлах у нас і HTML, і PHP код.

This short article covers some steps you need to implement to get your own ActiveRecord implementation.

Sample ActiveModel looks like this:

class Posting
  include ActiveModel::Validations

  attr_accessor :id, :title, :body, :tags

  validates :title, :presence => true
  validates :body, :presence => true

  def initialize(attributes = {})
    # ...
  end

  def save
    set_default_values

    # ...
  end

  def self.create(attributes = {})
    new(attributes).save
  end

  protected

  def set_default_values
    # ...
  end
end

First trouble is that ActiveModel does not provide any attribute access API. Or I did not google enough. So we need to create our own!

Let us have an instance variable @attributes where we will store our model’ data. We need to define getter and setter methods for all the attributes of our model. This may be done with the attr_accessor method. But when user sets the value for some attribute, we should store that in our @attributes variable. And here is the first step to our black magic: we will override the attr_accessor method.

module ActiveAttributes
  def attr_accessor(*args)
    args.each do |k|
      define_method("#{k}".to_sym) { @attributes[k.to_sym] }
      define_method("#{k}=".to_sym) { |value| @attributes[k.to_sym] = value }
    end
  end
end

I just wrapped the code into a single module. Remember: when you include the module in a class, all the module’ methods become class methods.

Now we will include this module before attr_accessor calls. But beware: you need to declare an @attributes instance variable in the constructor!

And let’s just agree with the following convention: all our attribute names should be symbols.

class Posting
  include ActiveModel::Validations
  include ActiveAttributes

  attr_accessor :id, :title, :body, :tags

  validates :title, :presence => true
  validates :body, :presence => true

  def initialize(attributes = {})
    @attributes = {}

    # ...
  end

  def save
    set_default_values

    # ...
  end

  def self.create(attributes = {})
    new(attributes).save
  end

  protected

  def set_default_values
    # ...
  end
end

Now, we can implement our constructor. We now have all the attributes’ getters and setter and thus we can simply call them in our constructor:

class Posting
  include ActiveModel::Validations
  include ActiveAttributes

  attr_accessor :id, :title, :body, :tags

  validates :title, :presence => true
  validates :body, :presence => true

  def initialize(attributes = {})
    @attributes = {}

    attributes.symbolize_keys.each do |k, v|
      v.symbolize_keys! if v.is_a? Hash

      send("#{k}=", v) if respond_to?("#{k}=".to_sym)
    end
  end

  def save
    set_default_values

    # ...
  end

  def self.create(attributes = {})
    new(attributes).save
  end

  protected

  def set_default_values
    # ...
  end
end

Now let’s implement some basic model persisting. First, we should not forget about our validations and add valid? test to the save method.

Let’s say our save method should return the model instance. Thus, we should put the model’ data into the database and get the id for that data (if we put the data with the INSERT statement).

So there is an important caveat: in order to get the correct model id, you need to get it from database in the same transaction as the update/insert statement. The mysql2 gem does support multiple query statements in a single transaction. But to perform such a query, you will need to set the MULTI_STATEMENTS flag when creating a Mysql2::Connection instance.

def save
  set_default_values

  return self unless valid?

  @connection = Mysql2::Client.new({ flags: Mysql2::Client::MULTI_STATEMENTS }.merge(...))

  # ...

  self
rescue
  self
ensure
  @connection.close
end

Here I used the instance variable @connection to make it available within the rescue and ensure statements.

Now we will use our instance variable, @attributes to create an SQL query:

def save
  set_default_values

  return self unless valid?

  @connection = Mysql2::Client.new({ flags: Mysql2::Client::MULTI_STATEMENTS }.merge(...))

    if @attributes[:id].blank?
    columns = @attributes.keys.map { |k| "`#{ k.to_s }`" }.join ','
    values = @attributes.values.map do |v|
      if v.nil?
        'NULL'
      else
        "'#{ ActionController::Base.helpers.sanitize(v.to_s) }'"
      end
    end.join ','

    query = "INSERT INTO postings#{ volume } (#{ columns }) VALUES (#{ values })"
  else
    mapping = @attributes.map { |k, v| "`#{ k.to_s }` = #{ v.nil? ? 'NULL' : "'#{ ActionController::Base.helpers.sanitize(v) }'" }" }.join ','

    query = "UPDATE postings#{ volume } SET #{ mapping } WHERE id = #{ @attributes[:id] }"
  end

  self
rescue
  self
ensure
  @connection.close
end

I used the ActionController::Base.helpers.sanitize helper method to escape the query parameters.

Now we should simply wrap our query into a transaction and get an id from the database.

def save
  set_default_values

  return self unless valid?

  @connection = Mysql2::Client.new({ flags: Mysql2::Client::MULTI_STATEMENTS }.merge(...))

  if @attributes[:id].blank?
    columns = @attributes.keys.map { |k| "`#{ k.to_s }`" }.join ','
    values = @attributes.values.map do |v|
      if v.nil?
        'NULL'
      else
        "'#{ ActionController::Base.helpers.sanitize(v.to_s) }'"
      end
    end.join ','

    query = "INSERT INTO postings#{ volume } (#{ columns }) VALUES (#{ values })"
  else
    mapping = @attributes.map { |k, v| "`#{ k.to_s }` = #{ v.nil? ? 'NULL' : "'#{ ActionController::Base.helpers.sanitize(v) }'" }" }.join ','

    query = "UPDATE postings#{ volume } SET #{ mapping } WHERE id = #{ @attributes[:id] }"
  end

  query = "START TRANSACTION; #{ query }; SELECT LAST_INSERT_ID() AS id; COMMIT;"

  @connection.query(query)

  while @connection.next_result
    result = @connection.store_result.to_a rescue nil

    @attributes[:id] = result.first['id'] if result.present? and result.first.present? and result.first.has_key? 'id'
  end

  self
rescue
  self
ensure
  @connection.close
end

Quite big method, sure. Yet, it performs all the UPDATEs and INSERTs for us.

Let’s add some attribute with the default value, created_at and check how the whole class works:

require 'date'

# ...

attr_accessor :created_at

# ...

protected

def set_default_values
  @attributes[:created_at] = DateTime.now
end

And the test:

p = Posting.new title: "Hello, ActiveModel!", body: "Hello, Database!"

p.save

puts p.created_at