Ben Morgan I/O

Web Development

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.

First, spree is amazing. Spree is a breathe of fresh air. Not just from when you move from say Magento to Rails, but each and everytime you run rails new app --database=postgresql && spree new app. Its like a new challenge. A new fight; and if you know me, you know I like to fight.

Its also the dawn of some new coding horrors.

You’ve seen the word “coding horror”. I bet you think I’m refering to Jeff Atwood, but to be honest, I’m actually referring to the actual definition of “coding horror”. No, Jeff Attwood is not the defeinition of a coding horror, move on…

A “coding horror”, at least to me, is a piece of code that is functional. Code that can run and get the job done. Its also bad code. Code that might make you wish you could rip your hair out. You can think of a coding horror as a code smell, “WET” code (as opposed to DRY), or an anti-pattern. Either way, you see it written, in the source, and on production… Its a coding horror.

When I was first beginning with spree I really wanted to learn it (and I did). My initial reaction was that it was terrible. Buggy.

Thing is, spree was developer friendly. It wasn’t until I pulled my socks up and knuckled down that I began to build my own personal spree cookbook.

And so I got good at it… I created a machine learning program for it for crying out loud.

Then people got in contact with me. People with money. People with power. People with products. People who wanted a storefront online. I accepted this small start up and began contract work with them. Small and simple, but start up. Just how I like it.

Then I began contract work part time with Rails Dog. The creators of Spree. They told me to get in contact with them. I did. I talked to them. Before I knew it, they had somehow, without telling me, pushed me through from casual friendly Skype chat to full on tech interviewing. Three or five interviews later… There’s a contract. I signed.

And there I was, working day and night with spree.

There’s also something that I need to confess: Spree is not easy. Spree makes you think. Spree is an ecommerce framework for Ruby on Rails. Rails is a web framework for Ruby. Ruby is a dynamic language that compiles down to C.

Spree’s issue is that it can burn a developer out. If you’ve ever seen the Shopify source code, you know what I mean. The enourmous amount of files and complexity can get at you and that’s when you burn out.

When something gets at you, you don’t just burn out, you might lock yourself in your room and go offline or (if you’re me) tackle the problem head on, get into a fight, and consider yourself victorious. It doesn’t matter what you do really, you’ve burned out.

Frankly, I’ve been getting tired lately. Oddly so. I used to get up at 8. Now its 10. I used to shut my computer down at a good time. Now I force myself at 9 some nights for my own good; last week not so much. Its 9:04pm right now. Mac is still on. I’m still typing. Failed that rule. I look out the window, its nightime. Somewhere in the world, there’s a sunrise. Someone is readying for a new day. Wish I was there.

The enormous amount of complexity that ensues with Spree is, unfortinately, too much for a full time job. I don’t mind writing ruby script or Rails apps full time, but for some reason, when you have to add a new layer of complexity, you start to feel the ground beneath you weakening.

Ruby is fantastic. Ruby has 1_759_542 lines of code. Ruby is simple, elegant, and amazing. Rails is also fantastic. Rails has 347_658 lines of code. Rails is powerful and definately a game changer for us web developers. Spree is my favourite. Spree has 197_207 lines of code. Spree is a full blown framework that is 56.724424578% the size of Rails. I mention this because if you think, for five seconds, that Spree is going to take you a day to learn, think again. Did Rails take you a year to learn? Then give Spree some credit and give it six monthes of your time. No joke. You’re learning a whole nother framework buddy. This ain’t going to be easy.

So you’re sitting there and programming on three difficult levels at once. No one said this was going to be easy. No one said it was pretty either. You burn out and you crash. Such is programming. Just remember: you made money doing it. You made it with Spree.

Now I move onto the conclusion of the blog post. As you can tell, I’m burning out. I’m crippling. By the end of November, I’ll be just doing programming part time with Spree. The other half of my time go to my personal health, which needs to be looked at. Sitting on your butt all day doesn’t help you much. Sorry, but I’m contracted part time to a company for a year. Probably going to use that to my advantage.

Posted 2 weeks ago on

If you checkout this CHANGELOG diff for the Spree 2.3.0 tag you’ll see that preferences were removed from all the models except for Spree::Calculator, Spree::PromotionRule, and Spree::PaymentMethod. If you’re wanting to store some preferences information, I’ll show you how in this blog post.

For our example, we’re going to assume that we have a store that requires us to collect the first and last name of a user. To do this, we’re going to have to add a new column to our user model.

$ rails g migration add_preferences_to_spree_users

Then, within your migration, you would add the new column and its rollback:

class AddPreferencesToSpreeUsers < ActiveRecord::Migration
  def up
    add_column :spree_users, :preferences, :text
  end

  def down
    remove_column :spree_users, :preferences
  end
end

When I was first doing this, I thought that I would use :hstore instead of :text, but it turns out that they actually don’t store it within PG as JSON, just a textual form of some YAML. I can confirm this when I hit up the rails c and investigate the Spree::Calculator model:

pry(main)> Spree::Calculator
=> Spree::Calculator(id: integer, type: string, calculable_id: integer, calculable_type: string, created_at: datetime, updated_at: datetime, preferences: text)

As we can see, it is a text field that :preferences gets stored as.

Once you have this code, we need to actually set up preferences within the spree user model. Here, I show you how to #class_eval it and add in the preferences:

Spree::User.class_eval do
  preference :first_name, :text
  preference :last_name, :text
end

And that’s it! You’re done!

Now its up to you to be able to setup the views/controllers properly, this blog post was just about setting up preferences for Spree 2.3.

Posted 1 month ago on

I hate JavaScript. I really hate JavaScript. Everyone knows I hate JavaScript. I really hate it. Although I do love Dart. I freaking love Dart! I’d substitute “freak” with another word to go along with the way I usually talk, but considering this blog is public, I’ll be polite. JS sucks!

But lately I’ve been working with AngularJS and having to do some frontend development on not just one, but two spree applications at the same time. At first, I thought it was cool. I could collect the data through the Spree API, but somehow that didn’t seem plausible. the Object can be grabbed from the database via the rails and be passed off to the JavaScript via a rails controller and into an AngularJS controller. Hello headache!

This works actually quite well when you’re on development, but it completely falls apart in production. You have to seperate every single JS file for Angular out from Sprockets and that just not fun. When this occurred, I began using Gon gem. Gon was actually quite efficient in sending over some information, but I couldn’t figure out how to sending over the large amounts of information that Spree comes with even at its bare minimums, pushing me to forfeit this attempt and move onto a new way: inline JS or data hooks. I did inline JS…

Then, on my second Spree project, I gave Gon another try. This time I succeeded and carried my knowledge back over to my original project, further developing my knowledge.

First, lets get you Gon:

# Gemfile
gem 'gon'

Now do a bundle and add this line of code directly before your javascript_include_tag:

<!-- app/views/spree/_head.html.erb -->
<%= include_gon %>

That’s it! You have gon installed!

Now then, lets reopen the products controller and give Gon some data:

# app/controllers/spree/products_controller_decorator.rb
Spree::ProductsController.class_eval do
  alias_method :super_show, :show

  def show
    super_show
    gon.product = @product.gon_object
  end
end

Now, Spree uses a before_action to load up the @product method for the #show page. So we know we have access to @product. The original #show method has also been overwritten, so we’ve just aliased a method called super_show to show and continued with our work.

Once done, when you reload the page you’ll get a method missing for the #gon_object method. Lets fix that by reopening the product model class.

# app/models/spree/products_decorator.rb
Spree::Product.class_eval do
  def gon_object
    {
      id: self.id,
      name: self.name,
      description: self.description,
      available_on: self.available_on,
      deleted_at: self.deleted_at
    }
  end
end

Now if you reload the browser, head on over to the product show page, you’ll see your product, but if you head on over to the console, the gon object will be available to you. (One of the reasons I hate JS is how it defines “hashes/dictionaries” as “objects”. This I find straight up vexing. One small reason I <3 Dart.) Now lets write some JS.

If you type gon.product you’ll notice that you get that product hash right back out. I’m going to let you in on a secret, we didn’t have to write that #gon_object method. We could have just said that gon.product = @product and be done with it. Except this wouldn’t work because this is the exact same hash that you get when you set it equal to @product; there’s too little data.

Try this:

> gon.product.price
undefined

And that is why we have our own custom #gon_object method my friend. You see, the price of an object is stored not in the spree_products table, but in the spree_prices table. You can see an example here of the SQL doing on via the Rails console:

> Spree::Product.first.price
  Spree::Product Load (18.3ms)  SELECT  "spree_products".* FROM "spree_products"  WHERE "spree_products"."deleted_at" IS NULL  ORDER BY "spree_products"."id" ASC LIMIT 1
  Spree::Variant Load (3.4ms)  SELECT  "spree_variants".* FROM "spree_variants"  WHERE "spree_variants"."deleted_at" IS NULL AND "spree_variants"."product_id" = $1 AND "spree_variants"."is_master" = 't' LIMIT 1  [["product_id", 1]]
  Spree::Preference Load (0.6ms)  SELECT  "spree_preferences".* FROM "spree_preferences"  WHERE "spree_preferences"."key" = 'spree/app_configuration/currency' LIMIT 1
  Spree::Price Load (1.1ms)  SELECT  "spree_prices".* FROM "spree_prices"  WHERE "spree_prices"."variant_id" = $1 AND "spree_prices"."currency" = 'USD' LIMIT 1  [["variant_id", 1]]
 => #<BigDecimal:7ff17a31f218,'0.1599E2',18(18)>

Now then, lets edit that hash inside from the #gon_object method inside of Spree::Product. To get the price, we’ll just add a new key called price and give it a pretty simple key:

{
  ...
  price: self.price,
  ...
}

Now, if you go back into the browser console, you’ll notice that it gets written out as a string. (Why is everything saved as a freaking string in JS? Did you know that Dart is optionally typed?) To fixe this, we update the value to self.price.to_f to make it a float number.

Now that you have a way to get custom information from your model to your JS, lets give you a way to get those ActiveRecord relationships working.

Since you’re on the product page, I’m going to assume you need to get at all the different variants for your product. Luckily in spree we can just do:

{
  ...
  variants: self.variants,
  ...
}

That’s awesome! Now we have access to an array of variants! If you have to make variants customized (and I bet you will at some point to get anything useful out of it) then you’ll need to reopen the variants model and add a #gon_object method inside of it as well.

To do so, lets first update our variants value:

{
  ...
  variants: self.variants.map(&:gon_object)
  ...
}

Now, lets reopen the Spree variants model and give it some awesomeness!

Spree::Variant.class_eval do
  def gon_object
    {
      id: self.id,
      sku: self.sku,
      weight: self.weight.to_f,
      height: self.height.to_f,
      width: self.width.to_f,
      depth: self.depth.to_f,
      deleted_at: self.deleted_at,
      is_master: self.is_master,
      cost_price: self.cost_price.to_f,
      position: self.position,
      cost_currency: self.cost_currency,
      track_inventory: self.track_inventory,
      tax_category: self.tax_category
    }
  end
end

This is awesome! Now we know exactly what what data we’re sending to the browser! If you look at the very last piece of data in the hash, you can see that we’re trying to get the tax_category for the variant. This requires use to traverse from our initial variant model, over to the product, and out to the spree_tax_categories table to get our row of data. I’m mentioning this for two reasons. One, its a really good reason for writing your own method for Gon and two, you need to think about n+1 problems. When this happens, please head over to where you originally called the #gon_object and add an #includes method for that table:

# app/models/spree/product_decorator.rb
{
  ...
  variant: self.variants.includes(:variants).map(&:gon_object)
  ...
}

And there we go, you’re all set. You now know how to pass data from Spree to JS large frontend applications. Woot!

Posted 1 month ago on

When working with Spree, you’ll need to at some point move some of the work onto a backgorund process. When this happens, you end up having a background smackdown on what to use. There’s delayed jobs, resque, and sidekiq. Not only that, but how optimized is Spree for background jobs?

Well, to start I’ve worked on 3 spree applications in total. Yes, 3. One used delayed jobs, one used resque, and one used sidekiq.

Now, delayed jobs is great if you don’t want to hook redis up. Personelly, I don’t think its the best option for Spree. Spree already goes a bit overkill on ActiveRecord and I feel like delayed jobs might just add more of a weight to it. Not only that, but both resque and sidekiq provide better services via redis, which is a lot faster. In other words, I don’t care if you don’t want to hook redis up to an app, you need to.

When I began working with resque, it was just amazing. Setting up a worker class was also pretty easy and sending all the data over to redis was handled from the app’s end. When something went wrong, I went straight to the dashboard to figure it out. Moving to resque? Do it.

But here’s the thing about resque: its for applications that are high in CPU, but from my experiences, Spree is more memory high than anything else. This is where sidekiq comes in. Not only that, but from working with Rails Dog, I’ve discovered that resque can have a bit of a “split brain”. Due to this, I think it would be best to switch from resque over to sidekiq if one is using resque. The best part: its an easy process.

Posted 1 month ago on