Hao's Thoughts

Ruby, Rails, Objective-C and everything else

Print to Label Printer Directly From Within Web Application

I’ve been helping a local store developing a Point of Sale (POS) system recently, and one of their requirements is printing price tag from within the product management interface. The first time I heard about this, I thought it was impossbile to have a web app to talk to a local printer. “There must be something like a client app, which installed on the client side, retriving the print jobs via a REST api and send it to the label printer.”, my initial thought leads me to start looking for Java Applet, which pretty much acts as a client app but residing in a web page.

After few google searches, I found a Java Applet named jZebra, which looks pretty much what I need, and it’s now moved to to QZ.

Download and install the free version of the software, now I have QZ-Tray as a broker who’s going to talk to the printer, the applet in the web page is going to communicate with QZ-Tray via WebSocket, it works like a magic, but there’re few pitfalls I need to mention here hoping it could help someone like me.

  • setup the label printer

QZ has provided a really great tutorial on how to setup the label printer, I tried to follow the instructions, but never succeeded. The thing is from within http://localhost:631/admin, you should not click “Add Printer”, while you should click “Find New Printers”, and follow the rest of the instructions from QZ. You may need to restart the QZ-Tray to pick up the changes.

Evaluate the Javascript From Server Side

A problem I run into recently is I am trying to send an AJAX request to fetch grouped options for a select input, the select input is dynamically generated, and I don’t want to assign an unique random ID to it, and pass the ID to the server as the DOM selector, I do believe there’s a better way of doing this, here’s what I come up:

1
2
3
# options/index.js.erb

var groupedOptionsHTML = "<%= j helper_method_generate_grouped_options %>";
1
2
3
4
5
6
7
8
9
10
11
12
var newSelectInput = generateSelectInput();

$.ajax({
  type: "GET",
  dataType: "script",
  url: "http://localhost:3000/options",
  success: function(data, xhr, status) {
      eval(data);

      newSelectInput.html(groupedOptionHTML);
  }
})

As you can see, the key to retrieve the variable groupedOptionsHTML is to evaluate the data returned using eval(data). Please drop a line if you have any better idea to solve this problem, cheers.

Gotcha: Rails Doesn’t Track in Place Changes to Serialized Column

Believe it or not, it’s been 6 years since the ticket was created about “Rails doesn’t track in place changes to serialized column”, it’s really a tricky problem rare people will run into. Consider the following scenario:

1
2
3
class Answer < ActiveRecord::Base
  serialize :options, Array
end
1
2
3
4
5
6
7
8
9
10
11
12
13
>> a = Answers.new(options: [1, 2, 3])

>> a.options
=> [1, 2, 3]

>> a.changed?
=> false

>> a.options << 4
=> [1, 2, 3, 4]

>> a.changed?
=> false

As commented by Jose Valim link, it’s a feature of Rails and it’s documented somewhere. The workaround is issue another options_will_change! to mark the object changed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>> a = Answers.new(options: [1, 2, 3])

>> a.options
=> [1, 2, 3]

>> a.changed?
=> false

>> a.options << 4
=> [1, 2, 3, 4]

>> a.options_will_change!

>> a.changed?
=> true

It gets more tricky especially when you are using accepts_nested_attributes_for, the Rails will ditch the changes to the children objects if changed? returns false.

1
2
3
4
class Question < ActiveRecord::Base
  has_many :answers, dependent: :destroy
  accepts_nested_attributes_for :answers
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# spec/controllers/questions_controller_spec.rb

describe QuestionsController do
  describe "PUT /update" do
    it "updates the question with its answers" do
      q1 = Question.create
      a1 = Answer.create(question: q1, options: [1, 2, 3])

      put :update, id: q1.id, question: {
        answers_attributes: {
          "0" => {id: a1.id, options: [1, 2, 3, 4]}
        }
      }

      a1.reload
      expect(a1.options).to eq [1, 2, 3, 4] # FAIL!!
    end
  end
end

It really got me and hope this will help somebody like me, happy hacking!!

Rails 4 Gotcha: Nested Form Created New Child Object Every Time Parent Object Is Updated

I’ve been playing with Rails 4 recently, the strong parameter, as you all know, is a new feature just appeared in Rails 4. It will get really tricky when you are posting a nested form.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# question.rb
class Question < ActiveRecord::Base
  has_one :answer, dependent: :destroy
  accepts_nested_attributes_for :answer, reject_if: Proc.new {|a| a["body"].blank?}
end

# answer.rb
class Answer < ActiveRecord::Base
  belongs_to :question
end



# questions_controller.rb
class QuestionsController < ApplicationController
  def update
      @question = Question.find(params[:id])
      
      if @question.update_attributes(question_params)
        redirect_to questions_path, notice: "Question updated."
      else
        render :edit
      end
  end

  protected
  def question_params
      params.require(:question).permit(:content, answer_attributes: [:body])
  end
end

# questions/edit.html.haml

= form_for @question do |f|
  = f.text_field :content

  = f.fields_for :answer, @question.answer || @question.build_answer do |builder|
    = builder.text_field :body

  = f.submit "Update", disable_with: "Updating ..."

The above code are really straightforward Rails 4 code for updating a given question with its answer, the problem right now is every time I updated the question, no matter if updated the associated answer or not, it will destroy the old answer object, and create a new answer object for me, that’s really annoying, the gotcha here is you need have the answer’s id field go through for strong parameter, otherwise, it will be filtered out, and the old answer will be destroyed, and a new answer object will be created silently. The revision is something like:

1
2
3
4
5
6
7
8
9
# questions_controller.rb
class QuestionsController < ApplicationController
  ...

  protected
  def question_params
      params.require(:question).permit(:content, answer_attributes: [:id, :body])
  end
end

Happy coding.

How to Capture Changes in After_commit

@flyerhzm has done a great job on when you should use after_commmit instead of after_save in this post. One thing is sometimes you may want to check if there’s any changes to a specific column before executing the code within the callback. Sadly, since it is in after_commit block, all the changes have been persisted into the database, you will never got a chance to check if there’s any changes to any columns, that’s the problem we are going to attack.

1
2
3
4
5
6
7
8
9
10
class Person < ActiveRecord::Base
  after_commit :notify_police, only: [:create, :update]

  private
  def notify_police
    if self.name_changed? or self.dob_changed?
      PoliceNotification.notify(self)
    end
  end
end

Obviously, you don’t want to bother the police every time you change your hair style is changed, believe me, you don’t want to do that. The fact is we need to let the police know once you change your name or your DOB. You will find a tricky bug in the above code, the PoliceNotification.notify(self) will never get triggered because in the after_commit block, you will never see any changes to any columns. So, the way I fix this problem is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Person < ActiveRecord::Base
  after_save :prepare_to_notify_police
  after_commit :notify_police, only: [:create, :update]

  private
  def prepare_to_notify_police
    @name_or_dob_changed = self.name_changed? or self.dob_changed?
  end

  def notify_police
    if @name_or_dob_changed
      PoliceNotification.notify(self)
    end
  end
end

As you can see, I set a flag @name_or_dob_changed within the after_save block, as long as you do not reload the object, you can do the check based on the flag in the after_commit even after all the changes are persisted into database.

I Am Happy I Have You in My Life

It’s been 12 years we know each other since 2002, I can never forget that summary vacation when I saw you, I didn’t know that was love.

2009, we got married, for the past 12 years, we take care of each other, we fight, sometimes we went too far to say the word “divorce”, we were too young.

2013, our angel baby girl came to this world, that’s the best thing I’ve had in my life, I can not forget the night when you are going to deliver, you woke me up gently and calmed me down. The moment you were sent into the delivery room, I had a lot in my mind, it was a rainy night, a peaceful night. When our baby was out, and you were sent to the ward, I can still remember the blood all over you, I can not help myself, you are a hero mom, to me and to our baby.

I am the most happy man in world I have you in my life, let’s expore this wonderful world together, never separated.

Customize the Polymorphic URL for STI

One thing I love Rails is it provides really handy URL helpers to the developers. Today, I am going to present you guys how to use polymorphic_url like a ninja.

Say, I’ve got the following models:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# app/models/vehicle.rb
class Vehicle < ActiveRecord::Base
  ...
end

# app/models/bicycle.rb
class Bicycle < Vehicle
  ...
end

# app/models/motercycle.rb
class Motorcycle < Vehicle
  ...
end

As you can see, we’ve have a STI table named vehicles in the database, and it stores all the bicycles, motorcycles and the other new vehicles we may have in the future, like unicycle.

We have a collection of vehicles, @vehicles, it contains bicycles and motercycles. What we are going to do is iterating the @vehicles, and display a link to the vehicle detail page. With polymorphic_url, we can write down the following code:

1
2
3
<% @vechicles.each do |v| %>
  <%= link_to "Vehicle Detail", polymorphic_url(v) %>
<% end %>

instead of:

1
2
3
4
5
6
7
<% @vehicles.each do |v| %>
  <% if v.is_a? Bicycle %>
      <%= link_to "Vehicle Detail", bicycle_page(v) %>
  <% elsif v.is_a? Motercycle %>
     <%= link_to "Vehicle Detail", motorcycle_page(v) %>
  <% end %>
<% end %>

Once we add a new kind of vehicle, we don’t need to open the above view file and add another elsif, it complies to the Open Closed Principle perfectly!

The request to bicycle detail will go to:

1
2
3
4
5
6
7
8
9
# app/controllers/bicycles_controller.rb
class BicyclesController < ApplicationController
  def show
    @bicycle = Bicycle.find(params[:id])
  end
end

# app/views/bicycles/show.html.erb
<h1>Here comes the bicycle details</h1>

And the request to motorcycle detail will go to:

1
2
3
4
5
6
7
8
9
# app/controllers/motorcycles_controller.rb
class MotorcyclesController < ApplicationController
  def show
    @motorcycle = Motorcycle.find(params[:id])
  end
end

# app/views/motorcycles/show.html.erb
<h1>Here comes the motorcycle details</h1>

What if we want to have the same controller rendering the same view for all the vehicles? Say, we only want one VehiclesController#show for all the vehicles’s detail, here we go:

1
2
3
4
5
6
7
8
9
# app/controllers/vehicles_controller.rb
class VechiclesController < ApplicationController
  def show
    @vehicle = Vehicle.find(params[:id])
  end
end

# app/views/vechicles/show.html.erb
<h1>Here comes the motorcycle details</h1>

You may say we can just use vehicle_url(v) to generate the URL, I can not agree more, but we are exploring something deep inside of Ruby on Rails, so, bare with me, :)

To have the polymorphic_url, generate the URL like vechicle_url, we need to overwrite self.model_name for the Vehicle, here’s how I found it out:

  1. the polymorphic_url will call build_named_route_call to generate the URL
  2. the build_named_route_call will call RecordIdentifier.__send__("plural_class_name", record) to find out reource name, say, a record of Bicycle will generate bicycles
  3. the plural_class_name will call model_name_from_record_or_class to determine the model name of the record
  4. model_name_from_record_or_class will call the record’s class model_name method to find out the model name of the class

We need to override the self.model_name to let polymorphic_url pick up the right model name:

1
2
3
4
5
6
7
8
# app/models/vehicle.rb
class Vehicle < ActiveRecord::Base
  ...

  def self.model_name
    ActiveModel::Name.new(self, nil, "Vehicle")
  end
end

If we want a custom URL and view template for specific vehicle, we can also write something like:

1
2
3
4
5
6
# app/models/unicycle.rb
class Unicycle < Vehicle
  def self.model_name
    ActiveModel::Name.new(self, nil, "Unicycle")
  end
end

With the following customization, polymorphic_url(@unicycle) will generate the URL unicycle_url(@unicycle).

Sortable Bootstrap Table With STI

You are working on a Rails 3 project and your client asks you to sort a list of items and display the items in order, the first thing come to your mind might be acts_as_list and jQuery sortable, you are not alone. I found that acts_as_list requires the items to be sorted belong to a parent, sadly, that’s not the case I am facing, the items I am trying to sort belongs to nothing, RankedModel come to rescue.

ranked-model is a modern row sorting library built for Rails 3 & 4. It uses ARel aggressively and is better optimized than most other libraries.

Lucky me, i found this great post introducing how to get RankdedModel work with Bootstrap table and jQuery sortable.

The requirement I am facing is bit more complex than the one explained in the above article, I have a list of items, which is an array of items of different types stored in one single tables, say, I have the following object layout:

1
2
3
4
5
6
7
8
9
10
class Employee < ActiveRecord::Base
  include RankedModel
  ranks :title
end

class Manager < Employee
end

class Salesman < Employee
end

Say, I have a list of employees, including managers, salesman shown in order, I can now drag and drop to sort the items in the list, great, ready to charge the customer? Not yet, you will find it will only sort the managers and salesmen separately, it will not sort them as a whole entity, dig into the source of RankedModel, i found something really interesting,

1
2
3
4
#lib/ranked-model/ranker.rb
def instance_class
  ranker.class_name.nil? ? instance.class : ranker.class_name.constantize
end

This where the RankedModel decides which class to use as the finder, the problem it could not sort managers and salesmen as a whole entity is because it will use Manager and Salesman separately to do the sorting, RankedModel found this problem before I do, and they provide an option class_name to unify the finder lookup, the solution is:

1
2
3
4
class Employee < ActiveRecord::Base
  include RankedModel
  ranks :title, :class_name => "Employee"
end

Back to the items listing page, viola, it sorts the Manager and Salesman as a whole entity.

Happy hacking!

爷爷,走好

“时光时光慢些吧,不要让你再老了,我愿用我一切换你岁月长留……”,不知不觉泪水模糊了双眼,心中隐隐作痛,呼吸变得困难,闭上眼睛,爷爷清瘦的脸庞缓缓浮现,微笑着,看着我。

爷爷,一个严厉的老头,严厉的有些怪,童年的回忆里,都是他冷峻的面庞和不留情面的训斥。他是新中国第一批飞行员,听人说,爷爷是因为坚持跟奶奶的婚姻,离开部队,回到地方。文革中,因为仗义执言,被打成右派,十几年没有工资,被送到崂山修水库,文革结束后,爷爷得到平反,回到国棉三厂任养鸡场场长,一直干到离休。

不知道是不是那十几年的磨难,让他变得阴森古怪,印象中,爷爷没有对我笑过,可能是他对我的要求太高了吧,我是你最亲最爱的孙子啊,爷爷!

慢慢的,我长大了,离开了青岛,去外地上学,每次从家离开,爷爷都要坚持送我到大门口,帮我整理肩上的背包,我装作轻松,摆摆手让他回去,回头已是泪眼模糊,从未想过有一天会与他阴阳两隔。

2005年,我寒假回家,爷爷提前在电话里跟我说搬家了,为了腿脚不太方便的奶奶,爷爷特地买了一楼,我记下了地址。晚上10点多,我下了火车,急急忙忙赶回家,在小区门口看到寒风中等我的爷爷,嘴上却怪他多虑。

2008年,我毕业了,留在了北京,每个星期都会给他打电话,问问家里的情况,爷爷闭口不谈家里的困难,他和奶奶行动都已经比较困难了,去医院拿药已经是比较困难的事情了,爷爷没有跟我提一个“难”字,怕我担心,怕耽误我的“大好前程”,那时的我也是没心没肺,心思全都放在工作上了,压根儿就没想到家里的情况已经不像从前了。

2010年春节,在青岛陪爷爷奶奶一起过年三十儿,爷爷很为难的跟我说:“我和你奶奶年纪都大了,你看你能不能回来青岛工作?”,看得出来,他是斟酌了很久,才把这句话说出来的,爷爷奶奶一辈子要强,从不会轻易求人。我没有多想,一口答应下来。

2011年初,我回到了青岛,干的还是老本行,因为都是给外国客户做活,经常需要熬夜,爷爷看了不忍,多次劝我说,“林林,你能不能换个工作啊?开个小店什么的,或者包个出租车也行啊。”,我总是一笑而过,但我知道,爷爷是心疼我,怕我熬坏了身子。平常没事儿的时候,他会出去转悠转悠,其实是帮我寻摸生意去了,看看哪家店干的挺好,哪家店准备出兑,回来跟我说,让我考虑考虑。你心疼我,我都知道,只是我跟你一样,不善于表达,有些话,我不说,我很后悔。

随着年龄的增长,我也慢慢的跟爷爷从爷孙变成了朋友,跟他开玩笑,跟他犟嘴,跟他讲我在twitter上看到小道消息,他像个孩子一样,问这问那。

爷爷驾鹤西去,我无处寻找,只能从记忆中挤出片段,拼凑成断续的影像,愿他在天国一切安好。