Ben Morgan I/O

Web Development & Online Marketing

Do you like my blog?

I'm a programmer who rants and raves about SEO, social media, web programming, and maybe some physics. If you are in the same field as me, read! I have tutorials.

In Spree, I run into this error a LOT and it always takes some time to debug, so here, I am not only going to solve it and make a detailed listing of what the possible issues are, but make sure that I don’t spend another two hours going through this head ache.

What happens is that when you are using Spree, you will hit the checkout page and you will submit your address information. On submission you ge this infamous error.

This error is caused because you have either made a product with no shipping information (which is easy to solve) or your tax information is not correct…

to solve the shipping method error, just slip over to the admin product edit page and see if the product you’re trying to but has a shipping method. It usually does and this unlikely the error. Anywho, just select Default in the drop down if you’re on a brand new store.

If, however, this is not the solution (and it probably isn’t), then you need to do some taxes. To start, lets talk about zones. Zones in spree define exactly in what areas of the world some tax information applies to. This a great junction to introduct the problem because (a) you might not have a zone set up for your default tax or (b) the problem now lies in either the countries/states or the tax information.

In the right side bar to the configuration, do you see a “States” button? If you don’t you might want to load up this data into your app:

The Countries.

The States.

The Zones.

And since Spree (as of 2.3.1) does not contain the Canadian states:

canada = Spree::Country.find_by_name('Canada')
Spree::State.create!([
 { "name" => "Yukon", "abbr" => "YT", country: canada },
 { "name" => "Nunavut", "abbr" => "NU", country: canada },
 { "name" => "British Columbia", "abbr" => "BC", country: canada },
 { "name" => "Alberta", "abbr" => "AB", country: canada },
 { "name" => "Saskatchewan", "abbr" => "SK", country: canada },
 { "name" => "Manitoba", "abbr" => "MB", country: canada },
 { "name" => "Ontario", "abbr" => "ON", country: canada },
 { "name" => "Quebec", "abbr" => "QC", country: canada },
 { "name" => "New Brunswick", "abbr" => "NB", country: canada },
 { "name" => "Newfoundland and Labrador", "abbr" => "NL", country: canada },
 { "name" => "Nova Scotia", "abbr" => "NS", country: canada },
 { "name" => "Prince Edward Island", "abbr" => "PE", country: canada },
 { "name" => "Northwest Territories", "abbr" => "NT", country: canada }
])

And now your app works for the geography. Lets hook up the tax information.

There are currently three settings for taxes: Tax Categories, Tax Rates, and Tax Settings.

We’ll go ahead and create a tax category and tax rate for clothing using Spree Sample’s data.

Spree::TaxCategory.create!(:name => "Clothing")
north_america = Spree::Zone.find_by_name!("North America")
clothing = Spree::TaxCategory.find_by_name!("Clothing")
tax_rate = Spree::TaxRate.create(
  :name => "North America",
  :zone => north_america,
  :amount => 0.05,
  :tax_category => clothing)
tax_rate.calculator = Spree::Calculator::DefaultTax.create!
tax_rate.save!

Now, if you head into the admin section and set clothing as the default and the North America zone as your default you should be good to go from the tax/geo section of this error.

But, wait, remember that this was also being caused because of the shipping information?

Well, you can solve this by adding in shipping information, or rather, shipping methods:

begin
  north_america = Spree::Zone.find_by_name!("North America")
rescue ActiveRecord::RecordNotFound
  puts "Couldn't find 'North America' zone. Did you run `rake db:seed` first?"
  puts "That task will set up the countries, states and zones required for Spree."
  exit
end

europe_vat = Spree::Zone.find_by_name!("EU_VAT")
shipping_category = Spree::ShippingCategory.find_or_create_by!(name: 'Default')

Spree::ShippingMethod.create!([
  {
    :name => "UPS Ground (USD)",
    :zones => [north_america],
    :calculator => Spree::Calculator::Shipping::FlatRate.create!,
    :shipping_categories => [shipping_category]
  },
  {
    :name => "UPS Two Day (USD)",
    :zones => [north_america],
    :calculator => Spree::Calculator::Shipping::FlatRate.create!,
    :shipping_categories => [shipping_category]
  },
  {
    :name => "UPS One Day (USD)",
    :zones => [north_america],
    :calculator => Spree::Calculator::Shipping::FlatRate.create!,
    :shipping_categories => [shipping_category]
  },
  {
    :name => "UPS Ground (EU)",
    :zones => [europe_vat],
    :calculator => Spree::Calculator::Shipping::FlatRate.create!,
    :shipping_categories => [shipping_category]
  },
  {
    :name => "UPS Ground (EUR)",
    :zones => [europe_vat],
    :calculator => Spree::Calculator::Shipping::FlatRate.create!,
    :shipping_categories => [shipping_category]
  }
])

{
  "UPS Ground (USD)" => [5, "USD"],
  "UPS Ground (EU)" => [5, "USD"],
  "UPS One Day (USD)" => [15, "USD"],
  "UPS Two Day (USD)" => [10, "USD"],
  "UPS Ground (EUR)" => [8, "EUR"]
}.each do |shipping_method_name, (price, currency)|
  shipping_method = Spree::ShippingMethod.find_by_name!(shipping_method_name)
  shipping_method.calculator.preferences = {
    amount: price,
    currency: currency
  }
  shipping_method.calculator.save!
  shipping_method.save!
end

Hope that works for you! It works for me. Have at it.

Posted 2 weeks ago on

Spree is an ecommerce framework for Ruby on Rails that is currently at version 2.2.2. I often find that individuals come to spree when Magento or Shopify just can’t serve their needs anymore and they need an even more custom solution.

To get started, we first need to install spree:

$ gem install spree

OK, that was fun, now let’s go ahead and make a new rails project:

$ rails _4.0.5_ new spree_app

Now that you have that done, try this out:

$ spree install spree_app

Or, if you’ve already navigated into spree_app:

$ spree install .

You will get a number of questions:

Would you like to install the default gateways? (Recommended) (yes/no) [yes]
Would you like to install the default authentication system? (yes/no) [yes]
Would you like to run the migrations? (yes/no) [yes]
Would you like to load the seed data? (yes/no) [yes]
Would you like to load the sample data? (yes/no) [yes]

Right now, please answer yes (the default) to all of them. When starting a new spree project, I often do spree install . -A which auto-accepts all parameters.

Now, as its installing, it will stop and ask you to create an Admin user:

Create the admin user (press enter for defaults).
Email [spree@example.com]:
Password [spree123]:

Just push the default options so that we can get going.

Throughout the installation, you might have noticed this warning:

[WARNING] You are not setting Devise.secret_key within your application!
You must set this in config/initializers/devise.rb. Here's an example:

Devise.secret_key = "a0c5e56c8764a93b03fce02083f4aed18aef63ef4d7be33f351accb002d4e2187ac6ba4a78090c341281f51a6abebd4fe499"

Now I’m going to tell you how to solve this. If you open up your Gemfile it should look like this:

source 'https://rubygems.org'

gem 'rails', '4.0.5'
gem 'sqlite3'

gem 'sass-rails', '~> 4.0.2'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.0.0'

gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 1.2'

group :doc do
  gem 'sdoc', require: false
end

gem 'spree', '2.2.2'
gem 'spree_gateway', github: 'spree/spree_gateway', branch: '2-2-stable'
gem 'spree_auth_devise', github: 'spree/spree_auth_devise', branch: '2-2-stable'

Notice at the bottom there were 3 gems that got installed. spree is the main project and is definately what you wanted to install. There’s also two more: spree_gateway and spree_auth_devise. spree_gateway basically handles active merchant, stripe, checks, stuff that allows you to receive money. spree_auth_devise is used for authenticating users. Its different from devise in that it requires you to be running devise; since bundler detects that you don’t have it in your Gemfile, it does it for you - the magic of Bundler.

Because spree_auth_devise is its own gem, it actually never got installed fully when you ran spree install. Therefore, we have to do another installation for spree_auth_devise. Here’s how you install spree_auth_devise:

$ bundle exec rails g spree:auth:install

you will see the error pop up one more time and then directly after that you get:

create  config/initializers/devise.rb

And there we go, its gone. Alternatively, you could have also created the initializer yourself and copy and pasted the devise secret key. To generate secret keys, you can use rake secret like so:

$ rake secret
9ba50700679fc17712ce1a1538bb9dd05c31038e12d1155cb8d437a9dd69a0a2fc8b7f9425f254c77d5bfa0587c9e50df0931f3803d947eb5fe13c7d1b6cec00

And there you go, now lets start the application:

$ rails s

IF you head over to localhost:3000 you will see the spree skeleton. Awesome! But, you probably don’t like that design, so lets get bootstrap in there! In your Gemfile, add:

gem 'spree_bootstrap_frontend', github: '200Creative/spree_bootstrap_frontend', branch: '2-2-stable'

Now, bundle and then run:

$ rails generate spree_bootstrap_frontend:install

It should now ask you if you would like to overwrite one of your assets. Answer Y.

If everything is working for you right now, just go and type in rails s and watch the design completely change for the better.

You can now change the theme of you spree application with ease!

Posted 1 month ago on

Watch the screencast on Rails TV!

Currently, ruby is at 2.1.2 and Rails is at 4.1.1. If you’ve tried hooking up Neo4j into Rails, you might have encountered the shear pain of this process and given up. I know I did. Many times. Then I succeeded.

Due to my success, Neo4j has asked me to write this blog post to help document the process. This one is free, on my blog, and owned by me. If you have any questions, please ask via CodersClan and set a price.

First, lets get you started with Rails and make sure you’re on the bleeding edge as of this post.

$ rvm install 2.1.2 && rvm use 2.1.2
$ gem install rails --version 4.1.1

I hope that makes it clear that this is the most up-to-date post you’ll find on the internet. (Don’t believe me? Then send me an email and prove it.)

Now that we have Rails, lets get Neo4j.

$ brew update && brew install neo4j
$ neo4j --version
NEO4J_INSTANCE:    /usr/local/Cellar/neo4j/2.1.2/libexec

And that is the latest version of Neo4j. To get started, lets run this command:

$ neo4j start
Using additional JVM arguments:  -server -XX:+DisableExplicitGC -Dorg.neo4j.server.properties=conf/neo4j-server.properties -Djava.util.logging.config.file=conf/logging.properties -Dlog4j.configuration=file:conf/log4j.properties -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -Dneo4j.ext.udc.source=homebrew -Djava.awt.headless=true
Starting Neo4j Server...WARNING: not changing user
process [22519]... waiting for server to be ready........ OK.
http://localhost:7474/ is ready.

Now you can check out http://localhost:7474. Honestly, just go through the high-level introduction. Its not that bad. Neo4j is using AngularJS to represent the data and run the client-side application. You can also see that this application was scaffold using Yeoman meaning they’re also using Grunt and Bower as well. I’d love to meet the developers.

For now, just accept that your database will exist on localhost:7474. Don’t touch anything else. Don’t think about anything else. Just be happy its running and that this is where your data will reside. That’s it. Now stop thinking about databases and starting thinking about ruby code! Run:

$ rails new neo4j

Now, we’re going to hit up the Gemfile:

source 'https://rubygems.org'
ruby '2.1.2'

gem 'rails', '4.1.1'
gem 'sqlite3'

gem 'sass-rails', '~> 4.0.3'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.0.0'

gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 2.0'
gem 'sdoc', '~> 0.4.0', group: :doc

gem 'thin'
gem 'neo4j', github: 'andreasronge/neo4j'

group :development do
  gem 'spring'
  gem 'os'
  gem 'better_errors'
  gem 'binding_of_caller'
  gem 'meta_request'
end

I’ve included the gems in the development group to help you debug your application. Don’t hesitate to add more development gems.

thin is just for the webserver, but you’re probably interested in the neo4j gem. Resist the urge to checkout its README on Github and just follow along here. It will confuse you and you may get lost.

When we bundle, we should get no errors. Lets keep moving.

The first step is to implement the views and to get the blog running on sqlite3. Once we move it over to Neo4j, we will remove ActiveRecord altogether in favour of a graph database. (If you want more information on how to use MySQL and PostgreSQL, checkout the neoid gem.)

First, lets run:

$ rails g controller posts

And then we will run:

$ rails g controller comments

Paste this into your posts controller:

class PostsController < ApplicationController
  before_action :set_post, only: [:show, :edit, :update, :destroy]

  def index
    @posts = Post.all
  end

  def show
  end

  def new
    @post = Post.new
  end

  def edit
  end

  def create
    @post = Post.new(post_params)

    respond_to do |format|
      if @post.save
        format.html { redirect_to @post, notice: 'Post was successfully created.' }
        format.json { render action: 'show', status: :created, location: @post }
      else
        format.html { render action: 'new' }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    respond_to do |format|
      if @post.update(post_params)
        format.html { redirect_to @post, notice: 'Post was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @post.destroy
    respond_to do |format|
      format.html { redirect_to posts_url }
      format.json { head :no_content }
    end
  end

  private

  def set_post
    @post = Post.find(params[:id])
  end

  def post_params
    params[:post]
  end
end

And then paste this into your comments controller:

class CommentsController < ApplicationController
  before_action :set_comment, only: [:show, :edit, :update, :destroy]
  before_action :set_post, only: [:new, :create, :destroy, :update]

  def new
    @comment = Comment.new
  end

  def create
    @comment = Comment.new(comment_params)

    respond_to do |format|
      if @comment.save
        # create a relationship with a created property between post and comment
        @post.comments.create(@comment, :created => Time.now.to_i)
        # alternative
        # @post.comments << @comment

        format.html { redirect_to @post, notice: 'Comment was successfully created.' }
        format.json { render action: 'show', status: :created, location: @comment }
      else
        format.html { render action: 'new' }
        format.json { render json: @comment.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    respond_to do |format|
      if @comment.update(comment_params)
        format.html { redirect_to @comment, notice: 'Comment was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @comment.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    # it will automatically destroy the relationship as well
    @comment.destroy
    respond_to do |format|
      format.html { redirect_to @post }
      format.json { head :no_content }
    end
  end

  private

  def set_comment
    @comment = Comment.find(params[:id])
  end

  def set_post
    @post = Post.find(params[:post_id])
  end

  def comment_params
    params[:comment]
  end
end

Now lets get the config/routes.rb set up:

Rails.application.routes.draw do
  root 'posts#index'

  resources :posts do
    resources :comments
  end

  resources :comments
end

As you can see, we’re setting up a blogging application. That’s it, but once you have this set up, I’ll introduce you to devise with Neo4j and then you can really mash things together.

This will be our app/views/application/layout.html.erb:

<!DOCTYPE html>
<html>
<head>
  <title>Neo4j</title>

  <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
  <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css">
  <script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
  <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>

  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>

  <%= csrf_meta_tags %>
</head>
<body>
  <div class="container">
    <%= yield %>
  </div>
</body>
</html>

app/views/posts/index.html.erb:

<div class="panel panel-default">
  <div class="panel-heading">
    <h1 class="text-center">Listing posts</h1>
  </div>

  <table class="table">
    <% @posts.each do |post| %>
      <tr>
        <td><%= post.title %></td>
        <td><%= link_to 'Show', post, class: 'btn btn-primary' %></td>
        <td><%= link_to 'Edit', edit_post_path(post), class: 'btn btn-info' %></td>
        <td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger' %></td>
      </tr>
    <% end %>
  </table>
</div>

<%= link_to 'New Post', new_post_path, class: 'btn btn-default' %>

app/view/posts/index.json.jbuilder:

json.array!(@posts) do |post|
  json.extract! post, :id
  json.url post_url(post, format: :json)
end

app/views/posts/new.html.erb:

<div class="panel panel-default">
  <div class="panel-heading">
    <h1 class="text-center">New post</h1>
  </div>

  <%= render 'form' %>
</div> 

<%= link_to 'Back', posts_path, class: 'btn btn-default' %>

app/views/posts/show.html.erb:

<% if notice %>
  <div id="notice" class="well bg-info">
    <%= notice %>
  </div>
<% end %>

<div class="panel panel-default">
  <div class="panel-heading">
    <h1>
      <%= @post.title %>
      <br>
      <small>Score: <%= @post.score %></small>
    </h1>
  </div>

  <div class="panel-body lead">
    <%= @post.text %>
  </div>

  <div class="panel-footer">
    <h3>Comments</h3>

    <table class="table">
      <% @post.comments.each do |comment| %>
        <tr>
          <td>
            <%= comment.title %>
          </td>

          <td class="text-right">
            <%= link_to 'Destroy', [@post,comment], method: :delete, class: 'btn btn-danger' %>
          </td>
        </tr>
      <% end %>
    </table>

    <div class="row">
      <p class="col-md-6 text-left">
        <%= link_to 'Edit Post', edit_post_path(@post), class: 'btn btn-info' %>
        <%= link_to 'Back', posts_path, class: 'btn btn-default' %>
      </p>

      <p class="col-md-6 text-right">
        <%= link_to 'New Comment', new_post_comment_path(@post), class: 'btn btn-primary' %>
      </p>
    </div>
  </div>
</div>

app/views/posts/show.json.jbuilder:

json.extract! @post, :id, :created_at, :updated_at

app/views/posts/edit.html.erb:

<div class="panel panel-default">
  <div class="panel-heading">
    <h1 class="text-center">Editing post</h1>
  </div>

  <%= render 'form' %>
</div>

<%= link_to 'Show', @post %> |
<%= link_to 'Back', posts_path %>

app/views/posts/_form.html.erb:

<div class="row">
  <div class="col-md-8 col-md-offset-2">
    <%= form_for(@post) do |f| %>
      <% if @post.errors.any? %>
        <div id="error_explanation">
          <h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2>

          <ul>
          <% @post.errors.full_messages.each do |msg| %>
            <li><%= msg %></li>
          <% end %>
          </ul>
        </div>
      <% end %>

      <div class="field form-group col-md-10">
        <%= f.label :title %><br />
        <%= f.text_field :title, class: 'form-control' %>
      </div>

      <div class="field form-group col-md-2">
        <%= f.label :score %><br />
        <%= f.number_field :score, class: 'form-control' %>
      </div>

      <div class="field form-group col-md-12">
        <%= f.label :text %><br />
        <%= f.text_area :text, class: 'form-control' %>
      </div>

      <div class="actions form-group col-md-12">
        <%= f.submit nil, class: 'btn btn-primary' %>
      </div>
    <% end %>
  </div>
</div>

That’s it for the posts. Let’s move on to getting the comments set up so that we have something to relate to:

app/views/comments/new.html.erb:

<div class="panel panel-default">
  <div class="panel-heading">
    <h1 class="text-center">New Comment</h1>
  </div>

  <%= render 'form' %>
</div>

<%= link_to 'Back', post_path(@post), class: 'btn btn-default' %>

app/views/comments/_form.html.erb:

<div class="row">
  <div class="col-md-8 col-md-offset-2">
    <%= form_for([@post, @comment]) do |f| %>
      <% if @comment.errors.any? %>
        <div id="error_explanation">
          <h2><%= pluralize(@comment.errors.count, "error") %> prohibited this comment from being saved:</h2>

          <ul>
          <% @comment.errors.full_messages.each do |msg| %>
            <li><%= msg %></li>
          <% end %>
          </ul>
        </div>
      <% end %>

        <div class="field form-group">
          <%= f.label :title %><br />
          <%= f.text_field :title, class: 'form-control' %>
        </div>

        <div class="field form-group">
          <%= f.label :text %><br />
          <%= f.text_area :text, class: 'form-control' %>
        </div>

        <div class="actions form-group">
        <%= f.submit nil, class: 'btn btn-primary' %>
      </div>
    <% end %>
  </div>
</div>

That’s all the code for the views. I’m following all the code I wrote and testing to see if this works… This is what I get:

$ rails s
=> Booting Thin
=> Rails 4.1.1 application starting in development on http://0.0.0.0:3000
=> Run `rails server -h` for more startup options
=> Notice: server is listening on all interfaces (0.0.0.0). Consider using 127.0.0.1 (--binding option)
=> Ctrl-C to shutdown server
Thin web server (v1.6.2 codename Doc Brown)
Maximum connections set to 1024
Listening on 0.0.0.0:3000, CTRL+C to stop

And if I load up the site:

uninitialized constant PostsController::Post

Looks like we have to set up our models. Lets set them up!

$ rails g model post
$ rails g model comment

Now, we’re going to do this the Neo4j way! Not the ActiveModel way. Lets replace the models with this code. I’m going to assume you can guess what everything means; its quite readable:

app/models/post.rb:

class Post
  include Neo4j::ActiveNode
  property :title
  property :text, default: 'bla bla bla'
  property :score, type: Integer, default: 0

  validates :title, presence: true
  validates :score, numericality: { only_integer: true }

  index :title

  before_save do
    self.score = score * 100
  end

  has_n(:comments).to(Comment)
end

app/models/comment.rb:

class Comment
  include Neo4j::ActiveNode
  property :title
  property :text

  index :title
  has_one(:post).from(Post, :comments)
end

You’ll notice that in these two models, we do not inherit from ActiveRecord::Base. Instead, we include this thing called Neo4j::ActiveNode which will understand that each model we create is a node in Neo4j. Awesome.

There’s also the has_n and the has_one relationships. They’re just like has_many and belongs_to!

Now if we restart our server:

ActiveRecord::PendingMigrationError -
Migrations are pending. To resolve this issue, run:
    bin/rake db:migrate RAILS_ENV=development

But we aren’t going to run any migrations. We are not going to use ActiveRecord!

Fix this by deleting the db/migrate folder. Done? Awesome.

If we reload the page, we now see undefined method 'find_all_nodes' for nil:NilClass problem. Lets investigate.

First, we notice that this is for the @post variable. @post is set inside PostsController#index which says:

@posts = Post.all

Considering there’s no posts table, I’m not surprised. We can confirm this by running:

$ rails c
Loading development environment (Rails 4.1.1)
2.1.2 :001 > Post
 => Post(score: Integer, text: Object, title: Object)
2.1.2 :002 > Post.connection
NoMethodError: undefined method `connection' for Post(score: Integer, text: Object, title: Object):Class
2.1.2 :003 > Post.all
NoMethodError: undefined method `find_all_nodes' for nil:NilClass

Isn’t that interesting? Post.all calls this thing called find_all_nodes?! Looks like we need to get our models hooked up to Neo4j!

Go to config/application.rb and use this code:

require File.expand_path('../boot', __FILE__)

require "rails"

%w(
  neo4j
  action_controller
  action_mailer
  sprockets
).each do |framework|
  begin
    require "#{framework}/railtie"
  rescue LoadError
  end
end

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module Neo4j
  class Application < Rails::Application
    config.neo4j.session_type = :server_db
    config.neo4j.session_path = ENV['GRAPHENEDB_URL'] || 'http://localhost:7474'
  end
end

Alright, so you see where it has require "rails"? It actually used to be require "rails/all". We change this to the %w( ... ).each { ... } because we do not want ActiveRecord. rails/all loads five modules. Rails, ActiveRecord, ActionController, ActionMailer, and Sprockets. I’ve seperate Rails into its own require at the top. Then we have the four modules. Replace active_record with neo4j and viola. Its done.

If you look inside Neo4j::Application you’ll see it using some neo4j configuation methods. session_type says “we want a :server_db and not an :embeddable_db”. session_path is the location of our database. If we’re on Heroku, we’ll be using GrapheneDB, but if we’re on development/test, we hook up to http://localhost:7474. (Note: You do not need to set the session_options in the configuration in this example. Don’t waste your time debugging it. Its not needed. sessions_options carries the basic authentication, but that will be in the ENV['GRAPHENEDB_URL'], so its not needed.)

Now, if we run rails s:

$ rails s
=> Booting Thin
=> Rails 4.1.1 application starting in development on http://0.0.0.0:3000
=> Run `rails server -h` for more startup options
=> Notice: server is listening on all interfaces (0.0.0.0). Consider using 127.0.0.1 (--binding option)
=> Ctrl-C to shutdown server
Exiting
/Users/benmorgan/.rvm/gems/ruby-2.1.2/gems/railties-4.1.1/lib/rails/railtie/configuration.rb:95:in `method_missing': undefined method `active_record' for #<Rails::Application::Configuration:0x007fa48b4db2c8> (NoMethodError)

The solution is to go to your config/environments/development.rb and comment line 23:

  # config.active_record.migration_error = :page_load

See how it calls config.active_record? You can guess why we’re turning this guy off.

If we boot up our server again with rails s and load up the root, we discover that the page is loading again! Shut down the server and run this:

$ rails c
Loading development environment (Rails 4.1.1)
2.1.2 :001 > Post
 => Post(score: Integer, text: Object, title: Object)
2.1.2 :002 > Post.connection
NoMethodError: undefined method `connection' for Post(score: Integer, text: Object, title: Object):Class
2.1.2 :003 > Post.all
 => #<Enumerator: #<Enumerator::Generator:0x007feba2325880>:each>

Looks like Post.all works.

Now, if we head over tothe browser and click on “New Post”, make a post, and then save it. Guess what happens? It Works!

Hed over to http://localhost:7474, click on the three dots to the top left, and in Node Lables, click “*”. Watch what happens. For me, an orange dot appears with the id inside of it. How cool is that? That’s your post.

Now then, within the Rakefile, set it to this:

require File.expand_path('../config/application', __FILE__)
require 'neo4j/tasks/neo4j_server'

Rails.application.load_tasks

Not sure what that does, but I think its needed. Lets keep moving on.

In your Gemfile, please remove sqlite3 and then bundle. Now delete config/database.yml and the whole db folder.

Does your app still work? If it does, then you are officialy No SQL! Not one relational database!

Lets deploy to Heroku.

First we add to our Gemfile:

group :production do
  gem 'rails_12factor'
end

And then we run:

$ git init && git add . && git commit -m "initial commit"
$ heroku create
$ git push heroku master

This is what mine looked like:

$ git push heroku master
Initializing repository, done.
Counting objects: 90, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (82/82), done.
Writing objects: 100% (90/90), 19.52 KiB | 0 bytes/s, done.
Total 90 (delta 8), reused 0 (delta 0)

-----> Ruby app detected
-----> Compiling Ruby/Rails
-----> Using Ruby version: ruby-2.1.2
-----> Installing dependencies using 1.5.2
       Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment
       Fetching gem metadata from https://rubygems.org/........
       Fetching additional metadata from https://rubygems.org/..
       Fetching git://github.com/andreasronge/neo4j.git
       Using json (1.8.1)
       Installing thread_safe (0.3.4)
       Installing minitest (5.3.4)
       Installing rake (10.3.2)
       Installing i18n (0.6.9)
       Installing builder (3.2.2)
       Installing mime-types (1.25.1)
       Installing rack (1.5.2)
       Installing erubis (2.7.0)
       Installing polyglot (0.3.5)
       Installing coffee-script-source (1.7.0)
       Installing arel (5.0.1.20140414130214)
       Installing execjs (2.2.0)
       Installing thor (0.19.1)
       Installing daemons (1.1.9)
       Installing hike (1.2.3)
       Installing multi_xml (0.5.5)
       Installing multi_json (1.10.1)
       Installing os (0.9.6)
       Using bundler (1.5.2)
       Installing zip (2.0.2)
       Installing orm_adapter (0.5.0)
       Installing tilt (1.4.1)
       Installing rails_serve_static_assets (0.0.2)
       Installing rails_stdout_logging (0.0.3)
       Installing rdoc (4.1.1)
       Installing sass (3.2.19)
       Installing tzinfo (1.2.1)
       Installing rack-test (0.6.2)
       Installing coffee-script (2.2.0)
       Installing treetop (1.4.15)
       Installing uglifier (2.5.1)
       Installing sprockets (2.11.0)
       Installing httparty (0.13.1)
       Installing rails_12factor (0.0.2)
       Installing activesupport (4.1.1)
       Installing sdoc (0.4.0)
       Installing mail (2.5.4)
       Installing actionview (4.1.1)
       Installing activemodel (4.1.1)
       Installing jbuilder (2.1.0)
       Installing actionpack (4.1.1)
       Installing neo4j-core (3.0.0.alpha.16)
       Installing activerecord (4.1.1)
       Installing active_attr (0.8.3)
       Installing actionmailer (4.1.1)
       Installing railties (4.1.1)
       Installing sprockets-rails (2.1.3)
       Using neo4j (3.0.0.alpha.7) from git://github.com/andreasronge/neo4j.git (at master)
       Installing coffee-rails (4.0.1)
       Installing jquery-rails (3.1.0)
       Installing turbolinks (2.2.2)
       Installing rails (4.1.1)
       Installing sass-rails (4.0.3)
       Installing eventmachine (1.0.3)
       Installing thin (1.6.2)
       Your bundle is complete!
       Gems in the groups development and test were not installed.
       It was installed into ./vendor/bundle
       Post-install message from rdoc:
       Depending on your version of ruby, you may need to install ruby rdoc/ri data:
       <= 1.8.6 : unsupported
       = 1.8.7 : gem install rdoc-data; rdoc-data --install
       = 1.9.1 : gem install rdoc-data; rdoc-data --install
       >= 1.9.2 : nothing to do! Yay!
       Post-install message from httparty:
       When you HTTParty, you must party hard!
       Bundle completed (25.56s)
       Cleaning up the bundler cache.
-----> Preparing app for Rails asset pipeline
       Running: rake assets:precompile
       rake aborted!
       NoMethodError: undefined method `active_record' for #<Rails::Application::Configuration:0x007f1ab5bf4218>
       /tmp/build_3bc3db89-ff81-4dff-872a-b8073c2928c8/vendor/bundle/ruby/2.1.0/gems/railties-4.1.1/lib/rails/railtie/configuration.rb:95:in `method_missing'
       /tmp/build_3bc3db89-ff81-4dff-872a-b8073c2928c8/config/environments/production.rb:82:in `block in <top (required)>'
       /tmp/build_3bc3db89-ff81-4dff-872a-b8073c2928c8/vendor/bundle/ruby/2.1.0/gems/railties-4.1.1/lib/rails/railtie.rb:210:in `instance_eval'
       Tasks: TOP => environment
       (See full trace by running task with --trace)
 !
 !     Precompiling assets failed.
 !

 !     Push rejected, failed to compile Ruby app

To git@heroku.com:cryptic-bastion-3009.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'git@heroku.com:cryptic-bastion-3009.git'

Lets fix that active record issue! In config/environments/production.rb comment line 82:

# config.active_record.dump_schema_after_migration = false

Now lets try another git push heroku herkou after committing the changes:

$ git add . && git commit -m "deactive active record on production environment"
$ git push heroku master
    .
    .
-----> Preparing app for Rails asset pipeline
       Running: rake assets:precompile
       rake aborted!
       Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 7474
       /tmp/build_9964e2bc-6799-479b-88a4-a004aff84caf/vendor/bundle/ruby/2.1.0/gems/httparty-0.13.1/lib/httparty/request.rb:93:in `perform'
       /tmp/build_9964e2bc-6799-479b-88a4-a004aff84caf/vendor/bundle/ruby/2.1.0/gems/httparty-0.13.1/lib/httparty.rb:521:in `perform_request'
       /tmp/build_9964e2bc-6799-479b-88a4-a004aff84caf/vendor/bundle/ruby/2.1.0/gems/httparty-0.13.1/lib/httparty.rb:457:in `get'

Looks like we need to set up our Graph database on production:

$ heroku addons:add graphenedb

While we’re adding some Heroku addons, lets get some more into there as well:

$ heroku addons:add newrelic
$ heroku addons:add papertrail

Lets do another push to production:

$ git push heroku master
  .
  .
-----> Preparing app for Rails asset pipeline
       Running: rake assets:precompile
       I, [2014-06-16T01:40:38.805761 #1003]  INFO -- : Writing /tmp/build_d38d82f9-99fe-471e-b78a-54a35d95b1bd/public/assets/application-958ecb4fb9542c4780a50a5263b53b34.js
       I, [2014-06-16T01:40:38.845432 #1003]  INFO -- : Writing /tmp/build_d38d82f9-99fe-471e-b78a-54a35d95b1bd/public/assets/application-9cc0575249625b8d8648563841072913.css
       Asset precompilation completed (11.69s)
       Cleaning assets
       Running: rake assets:clean
-----> WARNINGS:
       No Procfile detected, using the default web server (webrick)
       https://devcenter.heroku.com/articles/ruby-default-web-server
-----> Discovering process types
       Procfile declares types -> (none)
       Default types for Ruby  -> console, rake, web, worker

-----> Compressing... done, 64.5MB
-----> Launching... done, v9
-----> Deploy hooks scheduled, check output in your logs
       http://cryptic-bastion-3009.herokuapp.com/ deployed to Heroku

To git@heroku.com:cryptic-bastion-3009.git
 * [new branch]      master -> master

Woot! Its up there! Lets check it out!

$ heroku open

And its working!!! YES!!!

We can also add a Procfile just to keep Heroku happy and to get it to use thin:

web: bundle exec thin start -p $PORT

Commit and push it up. How awesome was that?

If you would like to see the graph representation, don’t forget to use:

$ heroku addons:open graphenedb

This will open the GrapheneDB UI in your browser.

If you go to your Heroku dashboard, you can also see that you can access GrapheneDB here and Launch the Neo4j browser interface. Now you know how to get access to your data!

GrapheneDB can be found here and their Heroku add on here. Thank gosh they exist.

I also stated at the top that I’d introduce you to devise, well here it is. Have fun figuring it out!

Posted 1 month ago on

Today I am encountering Ruby at some pretty deep levels. No, I’m not jumping into the deep depths of its C code and asking what the hell eval.c does, but I am looking at metaprogramming.

I’m doing a call up to an API and it is returning a Hash. Awesome? Not really. This means that I have to do ['name'] instead of #name. Not impressed.

To solve this, I made this within my Rails application. (If you have any advice on where to store the Hash class for ruby in a Rails application, please send me an Ask.)

# config/initializers/hash.rb
class Hash
  def method_missing(method, *args, &block)
    method = method.to_s
    self.has_key? method ? self[method] : super
  end
end

I hit up my console and it works! I can now call #name! I run the server and:

=> Booting Thin
=> Rails 4.1.1 application starting in development on http://0.0.0.0:3000
=> Run `rails server -h` for more startup options
=> Notice: server is listening on all interfaces (0.0.0.0). Consider using 127.0.0.1 (--binding option)
=> Ctrl-C to shutdown server
Exiting
/Users/benmorgan/Sites/app/config/initializers/hash.rb:10:in `method_missing': no id given (ArgumentError)
    from /Users/benmorgan/Sites/railstv/config/initializers/hash.rb:10:in `method_missing'
    from /Users/benmorgan/.rvm/gems/ruby-2.1.2/gems/thin-1.6.2/lib/thin/server.rb:107:in `==='
    from /Users/benmorgan/.rvm/gems/ruby-2.1.2/gems/thin-1.6.2/lib/thin/server.rb:107:in `block in initialize'
    from /Users/benmorgan/.rvm/gems/ruby-2.1.2/gems/thin-1.6.2/lib/thin/server.rb:105:in `each'
    from /Users/benmorgan/.rvm/gems/ruby-2.1.2/gems/thin-1.6.2/lib/thin/server.rb:105:in `initialize'
    from /Users/benmorgan/.rvm/gems/ruby-2.1.2/gems/rack-1.5.2/lib/rack/handler/thin.rb:14:in `new'
    from /Users/benmorgan/.rvm/gems/ruby-2.1.2/gems/rack-1.5.2/lib/rack/handler/thin.rb:14:in `run'
    from /Users/benmorgan/.rvm/gems/ruby-2.1.2/gems/rack-1.5.2/lib/rack/server.rb:264:in `start'
    from /Users/benmorgan/.rvm/gems/ruby-2.1.2/gems/railties-4.1.1/lib/rails/commands/server.rb:69:in `start'
    from /Users/benmorgan/.rvm/gems/ruby-2.1.2/gems/zeus-0.15.1/lib/zeus/rails.rb:160:in `server'
    from /Users/benmorgan/.rvm/gems/ruby-2.1.2/gems/zeus-0.15.1/lib/zeus.rb:148:in `block in command'
    from /Users/benmorgan/.rvm/gems/ruby-2.1.2/gems/zeus-0.15.1/lib/zeus.rb:135:in `fork'
    from /Users/benmorgan/.rvm/gems/ruby-2.1.2/gems/zeus-0.15.1/lib/zeus.rb:135:in `command'
    from /Users/benmorgan/.rvm/gems/ruby-2.1.2/gems/zeus-0.15.1/lib/zeus.rb:50:in `go'
    from -e:1:in `<main>'

This is caused by changing the method parameter before calling super. As you can see, I do call super. Therefore, we have now created this guideline:

Do not change the parameter. Do Not Change The Parameter. Do not touch the parameter.

That’s it. Now my code becomes:

# config/initializers/hash.rb
class Hash
  def method_missing(method, *args, &block)
    self.has_key? method.to_s ? self[method.to_s] : super
  end
end

Not as DRY, but it works. Have fun.

Posted 2 months ago on