Tag: Ruby 2.0

Installing Rhodes on Ubuntu and making it run on Ruby 2.1

People who want to use Rhodes are recommended to use it under Ruby 1.9.3. But to me it seems kinda old. This is a way to install and run it on 2.1:

Oracle Java

Oracle Java is a recommended one to use with Rhodes, so just:

sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java8-installer

SDK and NDK

Download both SDK and NDK. After that extract them in the same directory.

Rhodes gem

ruby -v
ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-linux]
gem install rhodes --no-ri --no-rdoc
# This will take some time...
Fetching: extlib-0.9.16.gem (100%)
Successfully installed extlib-0.9.16
Fetching: templater-1.0.0.gem (100%)
Successfully installed templater-1.0.0
# Bla bla bla...
7 gems installed

and now the harder part...

Rhodes setup

rhodes-setup
We will ask you a few questions below about your dev environment.
JDK path (required) (): /usr/lib/jvm/java-8-oracle
Android SDK path (blank to skip) (): /home/user/Android/android-sdk-linux
Android NDK path (blank to skip) (): /home/user/Android/android-ndk-r10
Windows Mobile 6 SDK CabWiz (blank to skip) (): 
BlackBerry JDE 4.6 (blank to skip) (): 
BlackBerry JDE 4.6 MDS (blank to skip) (): 
BlackBerry JDE 4.2 (blank to skip) (): 
BlackBerry JDE 4.2 MDS (blank to skip) (): 

Rhodes test app

Now we need a test app that will tell us what errors do we have related to our Ruby version:

rhodes app testapp
cd ./testapp

If you try to run rake -T you won't see any tasks. Instead you'll see path to your Rhodes gem sources:

rake -T
/home/user/.rvm/gems/ruby-2.1.2/gems/rhodes-3.5.1.12
# go there
cd /home/user/.rvm/gems/ruby-2.1.2/gems/rhodes-3.5.1.12

Rakefile changes

We need to make some changes to few files. To see rake tasks, we need to change one thing in Rhodes rakefile:

# I assume you're in Rhodes gem dir
# cd /home/user/.rvm/gems/ruby-2.1.2/gems/rhodes-3.5.1.12
# vim Rakefile

# Around line 33 - remove all of this:
module Rake
  class Task
    attr_accessor :comment
  end
end

Now in our app dir we can:

rake -T
rake build:android:eclipsebundle        # Build RhoBundle for Eclipse project
rake build:android:extensions           # Building native extensioons
rake build:android:rhobundle            # Build RhoBundle for android
rake build:symbian:rhobundle            # Build symbian rhobundle
rake build:wp8:rhobundle                # Build WP8 rhobundle
rake build:wp:rhobundle                 # Build WP7 rhobundle
rake clean:android                      # Clean Android
rake clean:bb                           # Clean bb
rake clean:bbsim                        # Clean bb and simulator
rake clean:iphone                       # Clean iphone
rake clean:win32                        # Clean win32
rake clean:wince                        # Clean windows ce
rake clean:wm                           # Clean wm
rake clean:wp                           # Clean wp
rake clean:wp8                          # Clean wp
rake config:checkbb                     # Check local blackberry configuration
rake device:android:debug               # Build debug self signed for device
rake device:android:production          # Build production signed for device
rake device:bb:debug                    # Build debug for device
rake device:bb:production               # Build production for device
rake device:iphone:production           # Builds and signs iphone for production
rake device:symbian:production          # Build production for device
rake device:win32:production            # Build installer for Windows
rake device:wince:production            # Build production for device or emulator
rake device:wm:production               # Build production for device or emulator
rake device:wp8:production              # Build production for device or emulator
rake device:wp:production               # Build production for device or emulator
rake run:android                        # build and launch emulator
rake run:android:device                 # build and install on device
rake run:android:rhosimulator           # Run application on RhoSimulator
# a lot of tasks...
rake uninstall:android                  # uninstall from emulator
rake uninstall:android:device           # uninstall from device

Android SDK setup

Go to your Android SDK dir and:

chmod +x ./tools/android
./tools/android

And use the Android 4.2.2 (API 17). Below you can see a printscreen of all the elements you need to have installed. If you have a Android L or any higher API than API 17, please remove them. Rhodes seems to have some issues with them.

android

androidcommon.rb changes

If you try to run your testapp, you will end up with following error:

Can't detect NDK toolchain path (corrupted NDK installation?)
/home/user/.rvm/gems/ruby-2.1.2/gems/rhodes-3.5.1.12/platform/android/build/androidcommon.rb:88:in `setup_ndk'
/home/user/.rvm/gems/ruby-2.1.2/gems/rhodes-3.5.1.12/platform/android/build/android.rake:388:in `block (2 levels) in <top (required)>'
/home/user/.rvm/gems/ruby-2.1.2/bin/ruby_executable_hooks:15:in `eval'
/home/user/.rvm/gems/ruby-2.1.2/bin/ruby_executable_hooks:15:in `<main>'
Tasks: TOP => run:android => run:android:emulator => config:android:emulator => config:android
(See full trace by running task with --trace)

edit androidcommon.rb and change:

@@ -71,8 +71,9 @@ def setup_ndk(ndkpath,apilevel)
   $ndktools = nil
   $ndkabi = "unknown"
   $ndkgccver = "unknown"
-  ["arm-linux-androideabi-4.4.3", "arm-eabi-4.4.0", "arm-eabi-4.2.1"].each do |abi|
+  ["arm-linux-androideabi-4.6", "arm-eabi-4.4.0", "arm-eabi-4.2.1"].each do |abi|
     variants = []
     variants << File.join(ndkpath, "toolchains", abi, "prebuilt", $ndkhost)
     variants << File.join(ndkpath, "build/prebuilt", $ndkhost, abi)
     variants.each do |variant|
@@ -118,6 +119,7 @@ def setup_ndk(ndkpath,apilevel)
   end
 
   variants.each do |variant|
     sysroot = File.join(ndkpath, variant, "android-#{last_api_level}/arch-arm")
     next unless File.directory? sysroot
     $ndksysroot = sysroot
@@ -244,7 +246,8 @@ def cc_run(command, args, chdir = nil)
   cmdstr = argv.map! { |x| x.to_s }.map! { |x| x =~ / / ? '' + x + '' : x }.join(' ')
   puts cmdstr
   $stdout.flush
-  argv = cmdstr if RUBY_VERSION =~ /^1\.[89]/
+  argv = cmdstr if RUBY_VERSION =~ /^(1\.[89]|2\.[0-9])/
   IO.popen(argv) do |f|
     while data = f.gets
       puts data

android_tools.rb changes

If you get this error:

NoMethodError: undefined method `rm_f' for AndroidTools:Module
/home/user/.rvm/gems/ruby-2.1.2/gems/rhodes-3.5.1.12/platform/android/build/android_tools.rb:211:in `run_emulator'
/home/user/.rvm/gems/ruby-2.1.2/gems/rhodes-3.5.1.12/platform/android/build/android.rake:1971:in `block (3 levels) in <top (required)>'
/home/user/.rvm/gems/ruby-2.1.2/bin/ruby_executable_hooks:15:in `eval'
/home/user/.rvm/gems/ruby-2.1.2/bin/ruby_executable_hooks:15:in `<main>'
Tasks: TOP => run:android => run:android:emulator
(See full trace by running task with --trace)

Here's fix for that (in android_tools.rb):

@@ -208,7 +208,7 @@ module_function :is_device_running
 def  run_emulator(options = {})
   system("\"#{$adb}\" start-server")
 
-  rm_f $applog_path if !$applog_path.nil?
+  FileUtils.rm_f $applog_path if !$applog_path.nil?
   logcat_process()
   
   unless is_emulator_running

Android SDK tools symlinks and changes

Apkbuilder

In your Android SDK dir run:

cat android | sed -e 's/com.android.sdkmanager.Main/com.android.sdklib.build.ApkBuilderMain/g' > apkbuilder
chmod a+x apkbuilder

Zipalign

cp ./build-tools/19.1.0/zipalign ./tools

aapt and lib

ln -s /home/mencio/Software/Android/android-sdk-linux/build-tools/19.1.0/aapt ./platform-tools/
ln -s /home/mencio/Software/Android/android-sdk-linux/build-tools/19.1.0/lib ./platform-tools/

error: device not found

Last thing to change. If you get this error:

* daemon not running. starting it now on port 5037 *
* daemon started successfully *
error: device not found
- waiting for device -
rake aborted!
Unable to create AVD image. No appropriate target API for SDK version: 2.1
/home/mencio/.rvm/gems/ruby-2.1.2/gems/rhodes-3.5.1.12/platform/android/build/android_tools.rb:231:in `run_emulator'
/home/mencio/.rvm/gems/ruby-2.1.2/gems/rhodes-3.5.1.12/platform/android/build/android.rake:1971:in `block (3 levels) in <top (required)>'
/home/mencio/.rvm/gems/ruby-2.1.2/bin/ruby_executable_hooks:15:in `eval'
/home/mencio/.rvm/gems/ruby-2.1.2/bin/ruby_executable_hooks:15:in `<main>'
Tasks: TOP => run:android => run:android:emulator
(See full trace by running task with --trace)

you need to edit your build.yml file and change:

android:
  version: 2.1

to 4.2.2 (or any other that you use)

android:
  version: 4.2.2

After all of that, you should be able to run:

rake run:android

NameError: uninitialized constant Gem::Builder

If you have this issue and you still want to build Rhodes from sources (Github), please downgrade:

gem update --system 1.8.25

Then just:

rake gem
gem install ./rhodes-5.0.2.gem

and get back to new gem version:

gem update --system

Upgrading to Rails 4.1 from Rails 4.0 – Ruby on Rails

Upgrading to Ruby on Rails 4.1 was much easier than moving from 3.2 to 4.0. Maybe because I try to keep all the apps up-2-date, maybe because Rails guys didn't change much stuff ;) (or maybe both). Either way, lets get through it.

Paperclip - String based terminators are deprecated, please use a lambda

DEPRECATION WARNING: String based terminators are deprecated, please use a lambda. 
(called from has_attached_file at app/config/initializers/paperclip_extensions.rb:22)

Well this one is really simple - just update Paperclip gem:

bundle update paperclip

More about this issue here.

The ability to pass in strings as a class name to set_fixture_class
will be removed

Next deprecation warning:

DEPRECATION WARNING: The ability to pass in strings as a class name to `set_fixture_class`
 will be removed in Rails 4.2. Use the class itself instead. 
(called from block in initialize at gems/activerecord-4.1.0/lib/active_record/fixtures.rb:465)

It you use Rspec you probably won't see this issue at all (or if you don't use fixtures). One of my apps unfortunately still does. Solution to this is really simple. Instead of:

set_fixture_class scanlation_categories:  'Scanlation::Category'
set_fixture_class scanlation_chapters:    'Scanlation::Chapter'
set_fixture_class scanlation_pages:       'Scanlation::Page'

use the class name itself (not its string version):

set_fixture_class scanlation_categories:  Scanlation::Category
set_fixture_class scanlation_chapters:    Scanlation::Chapter
set_fixture_class scanlation_pages:       Scanlation::Page

NameError: undefined method `_run_suite' for class `Test::Unit::Runner'

MiniTest::Unit::TestCase is now Minitest::Test. From /unit/testcase.rb:8:in `<module:Unit>'
rake aborted!
NameError: undefined method `_run_suite' for class `Test::Unit::Runner'
gems/activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
gems/activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `block in require'
gems/activesupport-4.1.0/lib/active_support/dependencies.rb:232:in `load_dependency'
gems/activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
app/test/test_helper.rb:23:in `<top (required)>'

Just get rid of this line from your test/test_helper.rb file:

require 'test/unit'

cannot load such file -- polyamorous (LoadError)

in `require': cannot load such file -- polyamorous (LoadError)
from /activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `block in require'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:232:in `load_dependency'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
from /ransack/lib/ransack/adapters/active_record/context.rb:3:in `<top (required)>'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `block in require'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:232:in `load_dependency'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
from gems/ransack-d51c78f9071f/lib/ransack/adapters/active_record.rb:4:in `<top (required)>'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `block in require'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:232:in `load_dependency'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
from gems/ransack-d51c78f9071f/lib/ransack.rb:24:in `<top (required)>'
from /bundler-1.5.2/lib/bundler/runtime.rb:76:in `require'
from /bundler-1.5.2/lib/bundler/runtime.rb:76:in `block (2 levels) in require'
from /bundler-1.5.2/lib/bundler/runtime.rb:72:in `each'
from /bundler-1.5.2/lib/bundler/runtime.rb:72:in `block in require'
from /bundler-1.5.2/lib/bundler/runtime.rb:61:in `each'
from /bundler-1.5.2/lib/bundler/runtime.rb:61:in `require'
from /bundler-1.5.2/lib/bundler.rb:131:in `require'
from app/config/application.rb:6:in `<top (required)>'
from app/config/environment.rb:1:in `require'
from app/config/environment.rb:1:in `<top (required)>'
from app/spec/spec_helper.rb:21:in `require'
from app/spec/spec_helper.rb:21:in `<top (required)>'
from app/spec/controllers/portal/announcements_controller_spec.rb:1:in `require'
from app/spec/controllers/portal/announcements_controller_spec.rb:1:in `<top (required)>'
from /rspec-core-3.0.0.beta2/lib/rspec/core/configuration.rb:932:in `load'
from /rspec-core-3.0.0.beta2/lib/rspec/core/configuration.rb:932:in `block in load_spec_files'
from /rspec-core-3.0.0.beta2/lib/rspec/core/configuration.rb:932:in `each'
from /rspec-core-3.0.0.beta2/lib/rspec/core/configuration.rb:932:in `load_spec_files'
from /rspec-core-3.0.0.beta2/lib/rspec/core/command_line.rb:21:in `run'
from /rspec-core-3.0.0.beta2/lib/rspec/core/runner.rb:100:in `run'
from /rspec-core-3.0.0.beta2/lib/rspec/core/runner.rb:31:in `invoke'
from /rspec-core-3.0.0.beta2/exe/rspec:4:in `<top (required)>'
from /home/mencio/.rvm/gems/ruby-2.1.0@senpuu/bin/rspec:23:in `load'
from /home/mencio/.rvm/gems/ruby-2.1.0@senpuu/bin/rspec:23:in `<main>'
from /home/mencio/.rvm/gems/ruby-2.1.0@senpuu/bin/ruby_executable_hooks:15:in `eval'
from /home/mencio/.rvm/gems/ruby-2.1.0@senpuu/bin/ruby_executable_hooks:15:in `<main>'

To remove this issue, upgrade your Ransack, MetaSearch and Squeel gems to newest versions and/or add this to your Gemfile:

gem 'polyamorous', github: 'activerecord-hackery/polyamorous'

ActionView::Template::Error:
 undefined method `reverse!' for #<ActiveRecord::Relation []>
Shared Example Group: "has valid single" 
called from ./spec/controllers/episodes_controller_spec.rb:13
./lib/system/active_record/nearable.rb:54:in `near'
./app/views/portal/episodes/show.html.haml:43:in `block in _app_views_episodes_show_html_haml'
./app/views/portal/episodes/show.html.haml:1:in `_app_views_episodes_show_html_haml'
./app/controllers/application_controller.rb:68:in `respond_with'
./app/controllers/portal/base_controller.rb:64:in `respond_with'
./app/controllers/portal/episodes_controller.rb:13:in `show'
./spec/support/macros/controllers/actions.rb:80:in `block (4 levels) in <module:Actions>'

With ActiveRecord 4.1, you can't call reverse! directly on ActiveRecord::Relation. Example:

# This will throw an error
@articles = Article.limit(10).order('created_at DESC').reverse!

Instead you have to cast ActiveRecord::Relation to an array:

@articles = Article.limit(10).order('created_at DESC').to_a.reverse!

Keep in mind, that casting with to_a will deprive you from all benefits of lazy loading with Rails relations so use it carefully. But on the other hand, reverse! on ActiveRecord::Relation did the same, so if you used it and it was ok, than feel free ;)

Undefined method `graft' for class ActiveRecord::Associations::JoinDependency

gems/activesupport-4.1.0/lib/active_support/core_ext/module/aliasing.rb:32:in `alias_method': 
undefined method `graft' for class `ActiveRecord::Associations::JoinDependency' (NameError)
activesupport-4.1.0/lib/active_support/core_ext/module/aliasing.rb:32:in `alias_method_chain'
from gems/polyamorous-0.6.4/lib/polyamorous/join_dependency.rb:7:in `block in included'
from gems/polyamorous-0.6.4/lib/polyamorous/join_dependency.rb:5:in `class_eval'
from gems/polyamorous-0.6.4/lib/polyamorous/join_dependency.rb:5:in `included'
from gems/polyamorous-0.6.4/lib/polyamorous.rb:20:in `include'
from gems/polyamorous-0.6.4/lib/polyamorous.rb:20:in `<top (required)>'
from gems/activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
from gems/activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `block in require'
from gems/activesupport-4.1.0/lib/active_support/dependencies.rb:232:in `load_dependency'
from gems/activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
from gems/ransack/lib/ransack/adapters/active_record/context.rb:3:in `<top (required)>'
from gems/activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
from gems/activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `block in require'
from gems/activesupport-4.1.0/lib/active_support/dependencies.rb:232:in `load_dependency'
from gems/activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'

Just install the newest version of ransack gem.

gem 'ransack', github: 'ernie/ransack'

Scoped order and limit are ignored, it's forced to be batch order and batch size

This is quite logical - you can't have some of orders when batching (for example a RAND()). That's why ActiveRecord is ignoring it. Just keep that in mind ;)

Example:

Token.2.1.0 :001 > Token.order('RAND()').find_each{}
W, [2014-05-09T11:26:46.601539 #11569]  WARN -- : 
Scoped order and limit are ignored, it's forced to be batch order and batch size
D, [2014-05-09T11:26:46.698603 #11569] DEBUG -- :   
Token Load (3.7ms)  SELECT  "accounts".* FROM "accounts"   ORDER BY "accounts"."id" ASC LIMIT 1000

Other issues

Well to be honest I didn't have any more issues. I've decided to remove Squeel gem from all of my projects, since it is not currently maintained. Thanks to that I've finally got rid of this irritating deprecation warning:

DEPRECATION WARNING: Core extensions are deprecated and will be removed in Squeel 2.0.
 (called from /app/config/initializers/squeel.rb:2:in `block in <top (required)>')

Summary

Rails 4.1 is not a big step, although it is a required one if you want to upgrade to 4.2 in the future. If you have decent test coverage level, you should not have big issues with this upgrade.

Copyright © 2024 Closer to Code

Theme by Anders NorenUp ↑